Skip to content

String::retain: convert only the untouched UTF-8 tail - #163624

Open
Talha-Dmr wants to merge 1 commit into
rust-lang:mainfrom
Talha-Dmr:string-retain-tail-utf8
Open

Talha-Dmr wants to merge 1 commit into
rust-lang:mainfrom
Talha-Dmr:string-retain-tail-utf8

Conversation

@Talha-Dmr

Copy link
Copy Markdown

During compaction, String::retain reads the next character with g.s.get_unchecked(read..len). This invokes String’s Deref, constructing a &str over the entire 0..len buffer before selecting the unread tail.

For example, removing 'é' from "éab" and moving 'a' left changes the buffer from C3 A9 61 62 to 61 A9 61 62. The next iteration reads the valid 'b' tail, but first converts the entire buffer, including the orphaned A9 continuation byte, to &str.

Constructing a non-UTF-8 &str is not immediate language-level UB under the Reference’s validity requirements. However, this conversion violates from_utf8_unchecked’s documented safety precondition. The libs discussion in #134598 is defining which operations accept invalid UTF-8; str::get_unchecked is absent from the tentative list.

The fix slices read..len directly from the byte vector and converts only that untouched tail to &str. The original string was valid UTF-8, and read remains on a character boundary. #154583 uses the same approach for extract_if.

Behavior is unchanged. A separate codegen comparison produced identical optimized x86-64 assembly for the tested predicates.

Validation

I ran:

  • ./x test library/alloc: all 1,491 tests passed, including test_retain.
  • ./x test tidy: passed.
  • ./x miri library/alloc: test_retain and the retain documentation tests passed under both Stacked Borrows and Tree Borrows, without reported UB.

I also ran differential comparisons covering:

  • 2,054,353 exhaustive cases, including 1,754,760 cases where the predicate panicked.
  • 39,745 randomized cases.
  • One dedicated "éab" case.

These total 2,094,099 comparison cases; the panic cases are included in the exhaustive count.

AI involvement

An AI assistant initially noticed the potential issue during a verification attempt. I independently verified the finding and confirmed the issue myself. I wrote the patch, SAFETY comment, and this description.

I used AI assistance to research the implementation and related PRs, and to assist with differential comparisons and Miri checks.

Related: #150067, #134598, #154583.

Slice the byte vector before converting to str, avoiding a whole-buffer
conversion while compaction may leave invalid UTF-8.
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Oct 1, 2026
@rustbot

rustbot commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the pull request, and welcome! The Rust Project has assigned @JohnTitor (or someone else) to review your changes, you should hear from them (or someone else) within the next two weeks.

Please see the contribution instructions and our LLM policy for more information.

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: libs
  • libs expanded to 12 candidates
  • Random selection from Darksonn, JohnTitor, Mark-Simulacrum, clarfonthey

@JohnTitor

Copy link
Copy Markdown
Member

r? libs

@rustbot rustbot assigned Mark-Simulacrum and unassigned JohnTitor Oct 22, 2026
@Mark-Simulacrum

Copy link
Copy Markdown
Member

Hi! The code changes here look good.

However, we commit PR descriptions into history, and it's not particularly useful to note that you ran a specific amount of tests from a particular bucket: that number is not meaningful.

I also note that it seems like you're describing somewhat redundant validation: "A separate codegen comparison produced identical optimized x86-64 assembly for the tested predicates." and relatively simple inspection of the code changes implies that there cannot be any behavior differences, so stating that there was a bunch of differential comparison done is not useful.

Can you adjust your PR description to focus on the present review and future readers, rather than an exhaustive review of what you and/or your LLM helped do? Thank you!

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 24, 2026
@rustbot

rustbot commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator

Reminder, once the PR becomes ready for a review, use @rustbot ready.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants