Skip to content

Commit

Permalink
Auto merge of rust-lang#91680 - saethlin:spare_capacity_mut-in-join, …
Browse files Browse the repository at this point in the history
…r=dtolnay

Use spare_capacity_mut instead of invalid unchecked indexing when joining str

This is a fix for rust-lang#91574

I think in general I'd prefer to see this code implemented with raw pointers or `MaybeUninit::write_slice`, but there's existing code in here based on copying from slice to slice, so converting everything from `&[T]` to `&[MaybeUninit<T>]` is less disruptive.
  • Loading branch information
bors committed Dec 14, 2021
2 parents a2d25b4 + 14f4ffa commit 7ca74ea
Showing 1 changed file with 10 additions and 2 deletions.
12 changes: 10 additions & 2 deletions library/alloc/src/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,12 +178,20 @@ where

unsafe {
let pos = result.len();
let target = result.get_unchecked_mut(pos..reserved_len);
let target = result.spare_capacity_mut().get_unchecked_mut(..reserved_len - pos);

// Convert the separator and slices to slices of MaybeUninit
// to simplify implementation in specialize_for_lengths
let sep_uninit = core::slice::from_raw_parts(sep.as_ptr().cast(), sep.len());
let iter_uninit = iter.map(|it| {
let it = it.borrow().as_ref();
core::slice::from_raw_parts(it.as_ptr().cast(), it.len())
});

// copy separator and slices over without bounds checks
// generate loops with hardcoded offsets for small separators
// massive improvements possible (~ x2)
let remain = specialize_for_lengths!(sep, target, iter; 0, 1, 2, 3, 4);
let remain = specialize_for_lengths!(sep_uninit, target, iter_uninit; 0, 1, 2, 3, 4);

// A weird borrow implementation may return different
// slices for the length calculation and the actual copy.
Expand Down

0 comments on commit 7ca74ea

Please sign in to comment.