Object safety

Only an object-safe trait can be passed as a trait object parameter to a function.

All parameters to a function must have a known size a.k.a Sized.

Traits are ?Sized. They have an unknown size since the sizes may vary for different concrete types.

If a trait method returns Self, then from the perspective of the trait, the method is returning a type of varying size depending on the size of the concrete type. A function cannot return something of unknown size. It is fine to declare such a method for a trait because any concrete type that implements the Trait will need to be Sized or else compiler will know to complain.

But it is not okay to pass a reference to an object of that trait dyn &T as an argument to some other function since that other function may call the method returning Self.

Side Note: Rust does not look at the implementation to see if the method is actually being called - if a parameter is okay to be passed into a function then it should be okay to call any of its methods in the function logic.

) and that size may vary which is not allowed (we need to know how many bytes on the stack to allocate for the return value of a function before we call the function).

So, when a type

A trait is object safe if all the methods defined in the trait have the following properties: - The return type isn’t Self. - There are no generic type parameters.

For a trait to be object safe the underlying concrete type should be referred to by a &self reference and not by self value. A reference is a known size (it is the same size, the size of a pointer, regardless of type) but a value is unknown (it varies depending on the type).

trait T1 {
    fn foo(self); // not object safe,
                  // size of object is unknowable at compile time.
}

trait T2 {
    fn foo(&self); // object safe
}