Confusing wording of Vec::from_raw_parts pointer allocation requirement · Issue #98780 · rust-lang/rust (original) (raw)

The Alternatives section of the documentation for core::mem::transmute has this to say about a better way to turn a Vec<&X> into a Vec<Option<&X>>:

// This is the proper no-copy, unsafe way of "transmuting" a Vec, without relying on the // data layout. Instead of literally calling transmute, we perform a pointer cast, but // in terms of converting the original inner type (&i32) to the new one (Option<&i32>), // this has all the same caveats. Besides the information provided above, also consult the // [from_raw_parts] documentation. let v_from_raw = unsafe { // Ensure the original vector is not dropped. let mut v_clone = std::mem::ManuallyDrop::new(v_clone); Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>, v_clone.len(), v_clone.capacity()) };

The documentation for Vec::from_raw_parts has this to say about where you can get the pointer from:

ptr needs to have been previously allocated via String/Vec<T> (at least, it’s highly likely to be incorrect if it wasn’t).

A strict reading, if I understand correctly, says that these two statements are contradictory. The transmute documentation says that it is safe to create a Vec<&i32> and then use from_raw_parts to create a Vec<Option<&i32>> out of its pointer. But the Vec documentation says that, when creating a Vec<T>, ptr must have previously been allocated via precisely and only Vec<T>, not Vec<U> for some other type U—not even if U happens to be transmutable from T, not even if T and U are ABI-compatible, not only if T is a repr(transparent) wrapper around U, but only T itself.

I suspect it was meant to say it must have previously been allocated by Vec, not Vec<T>; after all, if it could only have been allocated by Vec<T> in the first place, the next bullet point would be redundant (because obviously T has the same alignment as T).