dyn Supertrait
and dyn Subtrait
are distinct types, the second is not a subtype of the first. This is necessary because they have different vtable layouts. In addition, dyn Trait
is not a supertype of dyn Trait + AutoTrait
. These do have the same memory layout, and therefore the second could theoretically be a subtype of the first. However, backward compatibility prevents us from changing this, and the current design does have advantages (you can't specialize a trait impl for a subtype). However, this lack of subtyping also causes problems, in that trait implementations for trait objects don't apply to closely related objects even when it would make sense.
A simplified example from a rust-lang/rust GitHub issue:
use core::fmt;
pub trait ConnectionDriver {
// ...
}
impl fmt::Debug for dyn ConnectionDriver {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "A conection driver")
}
}
#[derive(Debug)] // Error, doesn't work!
// `dyn ConnectionDriver + Send` is not `Debug`
// even though `dyn ConnectionDriver` is
pub struct SendConnection(Box<dyn ConnectionDriver + Send>);
Ideally, the Debug
impl could be generic over any auto-traits the dyn ConnectionDriver
might have, or it could even apply to dyn SubtraitOfConnectionDriver
.