Rust's trait objects are fat pointers that contain 2 regular pointers: to data and to a vtable. The vtable is a structure containing a destructor function pointer, all trait method pointers and finally the size and alignment of the data.
What are the size and alignment fields for?
I couldn't find much:
Box
store location, size and alignment of its allocation? Every size variant of every DST can't get its own version of a vtable, can it?)A trait object is an opaque value of another type that implements a set of traits. The set of traits is made up of an object safe base trait plus any number of auto traits. Trait objects implement the base trait, its auto traits, and any supertraits of the base trait.
(Also, as more anecdotal evidence: the Rust compiler is known to generate multiple vtables for the same type if they happen to be needed in separate codegen units.)
Object Safety A trait is object safe if it has the following qualities (defined in RFC 255): All supertraits must also be object safe. Sized must not be a supertrait. In other words, it must not require Self: Sized . It must not have any associated constants.
Dynamic dispatch. Rust provides dynamic dispatch through a feature called 'trait objects'. Trait objects, like &Foo or Box<Foo> , are normal values that store a value of any type that implements the given trait, where the precise type can only be known at runtime.
Here's what I've found so far:
The size & alignment properties in a vtable are loaded in the librustc_codegen_llvm::glue::size_and_align_of_dst()
function which returns the size and alignment of a dynamically sized type. For ty::Dynamic(..)
values (the compiler's internal way of describing trait objects), the size and alignment are read from the vtable:
match t.sty {
ty::Dynamic(..) => {
// load size/align from vtable
let vtable = info.unwrap();
(meth::SIZE.get_usize(bx, vtable), meth::ALIGN.get_usize(bx, vtable))
}
...
}
This function in turn is used in several places:
librustc_codegen_llvm::operand::store_unsized()
for allocating enough storage space on the stack for the storing the unboxed value. librustc_codegen_llvm::intrinsic::codegen_intrinsic_call()
for implementing the size_of_val()
intrinsic
librustc_codegen_llvm::intrinsic::codegen_intrinsic_call()
for implementing the min_align_of_val()
intrinsic
I didn't spot any places where these values are currently fed into the Rust deallocation function (__rust_dealloc()
), but they could certainly be used for that in the future.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With