1. 13
  1.  

    1.  

      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).

      1.  

        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.

        1.  

          How does upcasting work (layout-wise) when a trait has multiple super-traits? I’d assume some redundancy is necessary in that case.

          1.  

            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.