Vec::from_raw_parts¶
Level: reference · for working programmers
One line: Rebuild a Vec from a pointer, a length and a capacity.
Stable since 1.0.0. Its const form is still unstable.
The unsafe counterpart of into_raw_parts, and the conditions are strict enough that the only reliably correct source of the three numbers is a Vec that produced them:
ptrmust come from aVec(or the same global allocator) with the sameT— the size and alignment are used to compute the deallocationcapacitymust be the capacity the buffer was allocated with, not the length- the first
lengthelements must be initialised length <= capacity
Getting capacity wrong corrupts the allocator. Getting T wrong is worse.
Lowering the length on the way back in is allowed: the elements above it are then leaked rather than dropped, but the buffer is still freed correctly because the capacity is right.
Almost every use has a safe alternative. For a Box<[T]>, Vec::from(boxed) is free and safe. For borrowing a buffer, as_slice. Reach for this only across an FFI boundary where a Vec really was decomposed on the other side.
Example¶
vec_from_raw_parts.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
fn main() {
// The only reliably correct source of the three numbers is a Vec that
// produced them, which is what into_raw_parts is for.
let original = vec![1u16, 2, 3];
let (ptr, len, cap) = original.into_raw_parts();
// Same pointer, same length, same capacity, same T. All four must match.
let v = unsafe { Vec::from_raw_parts(ptr, len, cap) };
println!("round trip: {v:?}");
// Length may be lowered on the way back in — the elements above it are
// then leaked rather than dropped, but the buffer is still freed correctly
// because the capacity is right.
let (ptr, _len, cap) = v.into_raw_parts();
let shorter = unsafe { Vec::from_raw_parts(ptr, 2, cap) };
println!("rebuilt with len 2 of 3: {shorter:?} cap {}", shorter.capacity());
drop(shorter);
// Building one from a Box<[T]> is the safe way to do the same thing, and
// is what you almost always actually want.
let boxed: Box<[u16]> = Box::new([7, 8, 9]);
let from_box: Vec<u16> = boxed.into();
println!("Vec::from(Box<[T]>): {from_box:?} cap {}", from_box.capacity());
// A Vec's own buffer, borrowed rather than taken — no unsafe needed.
let borrow = vec![4u16, 5];
println!("as_slice instead: {:?}", borrow.as_slice());
}
Verified output of vec_from_raw_parts.rs — regenerated by tools/run_examples.py, never hand-typed.
round trip: [1, 2, 3]
rebuilt with len 2 of 3: [1, 2] cap 3
Vec::from(Box<[T]>): [7, 8, 9] cap 3
as_slice instead: [4, 5]
See also¶
Vec::into_raw_parts— where the three numbers should come fromVec::into_boxed_slice— the safe hand-offVec::set_len— the other unchecked length claimVec::as_ptr— the pointer half