So my impression is that a trait fat pointer results in type-erasure and cannot be cast back to (a pointer of) the original object type. Specifically, all accesses to the object within the trait would need to be done through methods in the trait vtable pointed to in the fat pointer. This understanding of mine was partially solidified by my implementation of a similar concept in nim (previously nimrod) a bit back.
But then, it occurred to me that due to this type erasure, it's not obvious how one can drop the object referenced by the trait fat pointer, since the vtable would need a reference to drop(). But it works fine in rust as demonstrated below,
struct HasDrop;
impl Drop for HasDrop {
fn drop(&mut self) {
println!("Dropping!");
}
}
trait TraitThatDoesNotRequireDrop {}
impl TraitThatDoesNotRequireDrop for HasDrop {}
// [] moved into here to get Dropped, but Boxed trait doesn't indicate presence of drop().
fn foo(item: Box<[Box<TraitThatDoesNotRequireDrop>]>) {
println!("In foo!");
// But drop() runs successfully on foo completion.
}
fn main() {
let x : Box<[Box<TraitThatDoesNotRequireDrop>]> = Box::new([Box::new(HasDrop)]);
println!("HasDrop box created");
foo(x);
println!("Last statement in main");
}
The output is
HasDrop box created
In foo
Dropping!
Last statement in main
Does that mean that Drop is included in the vtable of all traits (effectively being implemented for all types and never being required within the type constraints)? If so, is there any other trait that has that property?