I wonder why the metadata of the raw pointer in box is ()
, but the metadata of sized
, which is stored on the stack, is the metadata of a slice ([T]
), which is described as the number of items and has the type usize
in Pointee
s documentation.
I have read the explanation on Pointee
, and wrote the following code:
#![feature(box_as_ptr)]
#![feature(ptr_metadata)]
#![allow(unused)]
struct MySuperSliceable<T: ?Sized> {
info: u32,
data: T,
}
fn main() {
let sized: MySuperSliceable<[u8; 8]> = MySuperSliceable {
info: 17,
data: [0; 8],
};
let box_sized = Box::new(MySuperSliceable {
info: 18,
data: [0; 12],
});
let dynamic: &MySuperSliceable<[u8]> = &sized;
let box_dynamic = Box::as_ptr(&box_sized);
assert_eq!(std::ptr::metadata(dynamic), 8_usize);
assert_eq!(std::ptr::metadata("hello, world!"), 13_usize);
let a = 10;
assert_eq!(std::ptr::metadata(&a), ());
assert_eq!(std::ptr::metadata(box_dynamic), ());
assert_eq!(std::ptr::metadata(box_sized.as_ref()), ());
}
I think these assertions
assert_eq!(std::ptr::metadata(box_dynamic), ());
assert_eq!(std::ptr::metadata(box_sized.as_ref()), ());
should be
assert_eq!(std::ptr::metadata(box_dynamic), 12_usize);
assert_eq!(std::ptr::metadata(box_sized.as_ref()), 12_usize);
but it is wrong.
Moreover, I would appreciate it if someone could write an extra example to explain the metadata of DST (Dynamically Sized Types), I also confused about it.
Your problem is that you made assumptions about what the types of your variables and expressions are, but your assumptions are wrong, box_dynamic
despite it's name is not a DST nor does it point to one, it's a *const MySuperSliceable<[i32; 12]>
, which is a pointer to a statically sized type and hence a thin pointer, without metadata.
The same is true for box_sized.as_ref()
which you again assume to return a pointer to a DST, but it returns a &MySuperSliceable<[i32; 12]>
, similarly to above, the size of an array is statically known and so this is a thin pointer, too.
the metadata of
sized
, which is stored on the stack, is the metadata of a slice ([T]
)
How do you get to that conclusion? sized
is not a pointer, so it can't even have (pointer-)metadata. Maybe you're referring to the metadata that dynamic
carries, but despite sized
being of statically known size, dynamic
is a pointer, that points to a MySuperSliceable<[i32]>
, which is a DST. The compiler is able to convert these pointers between each other and adds the corresponding metadata where applicable, the mechanism by which it happens here is called unsized coersion and happens because you assign &sized
to an explicitly typed variable let dynamic: &MySuperSliceable<[u8]>
where the type is a DST. What memory the variables are stored in and thus where the pointer points to, be it heap, stack, static memory, …, does not play a role on whether a pointer is eligible for unsized coercion.