This code has UB under both Stacked and Tree Borrows:
fn main() {
let mut s = String::with_capacity(10);
s.push('x');
let ptr = s.as_mut_ptr();
unsafe { ptr.write(0x20) };
let _ptr2 = s.as_mut_ptr(); // creates a slice that aliases with `ptr`.
// That is considered like a read access, and since `ptr` is derived from
// a mutable reference such a foreign read access invalidates `ptr`.
unsafe { ptr.write(97) }; // UB
println!("{s:?}");
}
The corresponding code with Vec is fine, because Vec::as_mut_ptr avoids invalidating previously created raw pointers to the vec's contents. String::as_mut_ptr does not exist, the code above relies on DerefMut for String and str::as_mut_ptr, which creates some extra references that cause unexpected invalidation.
Cc @rust-lang/libs-api -- would you be open to the idea of having as_mut_ptr on String as well?
Also see #97483, #106593
This code has UB under both Stacked and Tree Borrows:
The corresponding code with
Vecis fine, becauseVec::as_mut_ptravoids invalidating previously created raw pointers to the vec's contents.String::as_mut_ptrdoes not exist, the code above relies onDerefMut for Stringandstr::as_mut_ptr, which creates some extra references that cause unexpected invalidation.Cc @rust-lang/libs-api -- would you be open to the idea of having
as_mut_ptronStringas well?Also see #97483, #106593