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 callingtransmute
, 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
).