bobpsv
bobpsv

Reputation: 3

What is implementation principle of std::ptr::slice_from_raw_parts in rust

my rust version is 1.64.0.

In file "C:\Users\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs". I see the implementation of std::ptr::slice_from_raw_parts:

pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
    from_raw_parts(data.cast(), len)
}

In file "C:\Users\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\metadata.rs". I see the implementation of from_raw_parts:

pub const fn from_raw_parts<T: ?Sized>(
    data_address: *const (),
    metadata: <T as Pointee>::Metadata,
) -> *const T {
    // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
    // and PtrComponents<T> have the same memory layouts. Only std can make this
    // guarantee.
    unsafe { PtrRepr { components: PtrComponents { data_address, metadata } }.const_ptr }
}

The function slice_from_raw_parts return type is *const [T], the function from_raw_parts return type is *const T.

Why function slice_from_raw_parts can directly return function from_raw_parts's result?

They have different return type.

Upvotes: 0

Views: 229

Answers (2)

Cerberus
Cerberus

Reputation: 10247

These are two different Ts.

First, slice_from_raw_parts is essentially this:

pub const fn slice_from_raw_parts<T_slice_from>(data: *const T_slice_from, len: usize) -> *const [T_slice_from] {
    from_raw_parts::<T_from>(data.cast(), len)
}

Note that T_from and T_slice_from doesn't have to be the same.

Now about from_raw_parts:

pub const fn from_raw_parts<T_from: ?Sized>(
    data_address: *const (),
    metadata: <T_from as Pointee>::Metadata,
) -> *const T_from {
    // impl omitted
}

From this you can see that *const T_from must be equal (or coercible to) *const [T_slice_from], i.e. T_from = [T_slice_from], which is possible since from_raw_parts allows its generic type to be non-Sized.

And, to make the picture complete, - the metadata: it is typed as usize in the caller and as <T_from as Pointee>::Metadata, i.e. <[T_slice_from] as Pointee>::Metadata, in the callee. There's no explicit documented implementation of Pointee for slices, but documentation for trait itself mentions that slice's metadata is usize - which matches our observations.

Upvotes: 0

Chayim Friedman
Chayim Friedman

Reputation: 71380

T of from_raw_parts() is inferred to be [T] of slice_from_raw_parts(), so they have compatible return types.

Upvotes: 0

Related Questions