Hello! This is my first day writing Rust. I'm loving it so far, but have a question broadly about type erasure, trait objects and dynamic dispatch.
Assume I'm defining a struct Vehicle
, with a field motor
. This field should be able to take any type that implements the trait Motor
-- we want to allow for different implementations/kinds of motor.
I know I can declare motor
as &dyn Motor
(with proper lifetime annotations) or Box<dyn Motor>
. This makes sense to me: we don't know how much space our motor takes, because it could be any type that implements the trait. Therefore, we put the actual motor somewhere else, make the struct field a reference to it, and dynamically dispatch any calls at runtime (like C++ virtual
).
But, in the struct declaration, Rust also allows me to create a field motor: dyn Motor
without any errors. When declared like this, it is unclear to me how much space would be reserved for motor
.
Only when the struct is actually initialized do we get an error ("structs must have a statically known size to be initialized").
Why does Rust not complain about the declaration?
Is there any way to initialize this that would not generate an error? Perhaps somehow I can specify that any types with trait Motor
always have a fixed size?
I'm copying a short example to clarify what I'm talking about:
trait Motor {}
struct CombustionEngine {} // could also have ElectricMotor, etc.
impl Motor for CombustionEngine {}
struct VehicleWithMotorOnHeap { motor: Box<dyn Motor> }
struct VehicleWithBorrowedMotor<'a> { motor: &'a dyn Motor }
struct VehicleError { motor: dyn Motor }
// ^ why is this allowed?
fn main() {
let (motor_a, motor_b, motor_c) =
(CombustionEngine {}, CombustionEngine {}, CombustionEngine {});
let vehicle_a = VehicleWithMotorOnHeap { motor: Box::new(motor_a) };
let vehicle_b = VehicleWithBorrowedMotor { motor: &motor_b };
let vehicle_c = VehicleError{ motor: motor_c };
/* Error: the size for values of type `(dyn Motor + 'static)` cannot be
known at compilation time within `VehicleError`, the trait `Sized` is
not implemented for `(dyn Motor + 'static)`
structs must have a statically known size to be initialized */
}