In this document, the second field of pointer to trait object should be vtable of methods that Container<T> implements Hello:
Each instance of a pointer to a trait object includes:
- a pointer to an instance of a type T that implements SomeTrait
- a virtual method table, often just called a vtable, which contains, for each
method of SomeTrait and its supertraits that T implements, a pointer to T's
implementation (i.e. a function pointer).
So by this definition, c_dyn is not a pointer to trait object? And obviously, it is neither a pointer to slice, I want to know is there any document about this type of fat pointer?
Trait objects are written as the optional keyword dyn followed by a set of trait bounds
Collection<dyn Hello> is not a set of trait bounds optionally preceded by dyn, so as far as this page is concerned, no, Collection<dyn Hello> is not a trait object type. dyn Hello is a trait object; Collection<dyn Hello> is "merely" a struct that contains one.
That doesn't seem like quite the right generalization — or, at least, it doesn't capture all the cases where a fat pointer exists. Box<dyn Foo> is Sized, so it is not a DST, but it has a vtable pointer. (And so does Rc etc. and any user-defined type that contains a DST through some pointer type.)
[Edit:] Never mind, I was slightly confused. Boxis the (smart) pointer, and so the vtable pointer lives there. Otherwise, containers with multiple Boxes wouldn't work becuse there would be too many pointers, such as in:
use std::fmt::Debug;
struct Foo<T: ?Sized, U: ?Sized> {
a: Box<T>,
b: Box<U>,
}
fn main() {
let foo = Foo {
a: Box::new(1) as Box<dyn Debug>,
b: Box::new(2) as Box<dyn Debug>,
};
}
My question is not for DST itself, but for pointers to DST, these two type of fat pointers are common:
&dyn Trait
&[u8]
When I read code in rust-gc, I see something like this NonNull<GcBox<dyn Trace>>. It is a fat pointer but is not of these two types, so I'm curious about what this pointer is.
Anyway, this is not terribly important. I'll mark it as resolved.
NonNull is a pointer type, so when it points to a DST it becomes a fat pointer, just like &dyn Trait, *dyn Trait, or Box<dyn Trait>. This applies equally to all varieties of pointers to DSTs.
With a type like this, a reference &Container<T> will contain the same kind of metadata as a reference &T would. I.e. a &Container<[u8]> consists of a pointer to the struct and the length of the contained slice, and a &Contained<dyn Trait> consists of a pointer to the struct and a pointer to the vtable of the contained dyn Trait trait object.
E.g. when you have a variable let reference: &Container<dyn Trait> = …; and create a reference to its field with the expression &reference.value, which is a &dyn Trait, then this &dyn Trait fat pointer is created by adding the offset of the value field to the pointer part of reference and keeping the metadata part (i.e. the vtable pointer) the same.