Bonus question: The above doesn’t compile if you substitute Box or Rc for BufReader. Why not? Something about the CoercedUnsized impls on those? I don’t know the answer.
BufReader<dyn File> is an unsized type, Box<dyn File> and Rc<dyn File> aren’t. There isn’t a coercion defined from &Box<T> to &Box<dyn Trait>, which you can see by writing let r: &Box<dyn File> = &b as _;, the compiler tells you that it’s a non-primitive cast. What you can do is write … = &(b as _);, that forces the coercion before wrapping it in a reference (though it also moves the value).
I was poking vtables this week so if anyone’s interested in their layout, it currently goes: pointer to the drop function, two usizes for size and alignment, then n pointers to the object’s methods.
I believe that with the new upcasting feature, the super-trait’s function pointers come first followed by the sub-trait’s function pointers. That way you can treat the vtable as matching either trait.
Hmm, I’m not sure actually. There’s a proposed layout in the original RFC proposal in which some of a super-trait’s methods can come after the sub-trait’s, and sometimes a pointer to a new vtable is required.
BufReader<dyn File>is an unsized type,Box<dyn File>andRc<dyn File>aren’t. There isn’t a coercion defined from&Box<T>to&Box<dyn Trait>, which you can see by writinglet r: &Box<dyn File> = &b as _;, the compiler tells you that it’s a non-primitive cast. What you can do is write… = &(b as _);, that forces the coercion before wrapping it in a reference (though it also moves the value).I was poking vtables this week so if anyone’s interested in their layout, it currently goes: pointer to the drop function, two
usizes for size and alignment, thennpointers to the object’s methods.I believe that with the new upcasting feature, the super-trait’s function pointers come first followed by the sub-trait’s function pointers. That way you can treat the vtable as matching either trait.
How does upcasting work (layout-wise) when a trait has multiple super-traits? I’d assume some redundancy is necessary in that case.
Hmm, I’m not sure actually. There’s a proposed layout in the original RFC proposal in which some of a super-trait’s methods can come after the sub-trait’s, and sometimes a pointer to a new vtable is required.