How to refer to objects like this?


#1

Consider the following code:

trait Tr {
    fn to_str(&self) -> &str;
}

struct Data;

impl Tr for Data {
    fn to_str(&self) -> &str {
        "Data"
    }
}

struct Obj<T: ?Sized> {
    val: T
}

fn foo(o: &Obj<dyn Tr>) {
    println!("output = {:?}", o.val.to_str());
}

fn main() {
    let d = Data;
    let o = Obj { val: d };
    foo(&o);
}

&Obj<dyn Tr> is not a trait object because it’s not a pointer to a trait, at least not exactly. But it looks like Data's vtable for Foo is part of the pointer (and not Obj's layout) because mem::size_of::<&Obj<dyn Tr>>() == 16 on my system.

I haven’t seen any mention of this type of object in the book, and the definition of “trait object” doesn’t seem to include it. Should this be covered somehow? Should it have its own name or stretch “trait object” to be more inclusive. Could a unified nomenclature encompass pointers to other unsized or dynamically sized types, like &[u8] or &str, or are these different because they don’t require a vtable (although they may require size information instead)?


#2

Doc probably best description;
https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html


#3
struct Obj<T: ?Sized> {
   val: T
}

is a DST (dynamically sized type), just like slices and trait objects. Your own structs can participate in the DST system, albeit awkwardly, if their last member is a ?Sized type. In that case, the reference to such a struct is a fat pointer, just like a slice or trait object, except the size information about the struct that it calculates is the combination of the static and dynamic sizes that comprise the struct.