The short answer as to why, on a technical – almost syntactical – level comes from lifetime elision rules that make
-
Box<dyn Com>
be merely a shorthand for Box<dyn Com + 'static>
, but
-
impl Com
is not a shorthand for anything, but just a different (weaker) requirement than impl Com + 'static
,
so the impl Com
type simply does not fulfill the full required (but implicit in your code) Com + 'static
trait bound.
As for why that pescy – seemingly unproductive/annoying – + 'static
is implicitly added to your dyn Com
for you: trait object types actually always need to come with a lifetime bound, so dyn Trait
must actually always be of the form dyn Trait + 'some_lifetime
, and leaving out the “+ 'some_lifetime
” part can only ever be a shorthand for some implicitly added one, which will end up being 'static
for Box<dyn Trait>
, and 'a
for something like &'a dyn Trait
, i.e. that’s a shorthand for &'a (dyn Trait + 'a)
.
As a last step of the argument, why trait object types always need to come with a lifetime bound, it’s because you can never (fully) hide a short-lived reference in a struct. If you tried to define a struct
struct Foo {
field: &u8
}
the compiler will ask you to put a lifetime argument on the struct itself, Foo<'a>
, which is necessary for the same reasons the reference type itself needed a lifetime: so that the borrow checker can properly reason about it and make sure your code is safe! It’s thus unsurprising that you cannot turn a &u8
into Box<dyn Trait>
without any lifetimes on the type, either.
…talking of hiding lifetimes in a type…
FYI: In fact, trait objects do have a small “magical” power that normal structs cannot achieve: they allow you to consolidate multiple lifetimes into a common lower bound. E.g. if you have a &'a mut &'b mut &'c mut SomeType
(admittedly, not the most common type
, and want to put it into a struct Foo
, you’ll find that you’ll need to add three lifetime parameters Foo<'a, 'b, 'c>
for the 3 lifetimes 'a
, 'b
, 'c
in &'a mut &'b mut &'c mut SomeType
. And since all the lifetimes (except 'a
) are invariant, you cannot solve this by coercing it into something like Cell<&'a mut &'a mut &'a mut SomeType>
either… but it does work to put this kind of value into a Box<dyn SomeTrait + 'a>
only mentioning the shortest of the 3 lifetimes, 'a
.
Of course, as a Rust beginner, feel free to ignore any of the more “advanced” comments above – especially the last ”FYI“ paragraph –or look back at them when you learned more of the advanced Rust concept I’m touching upon here. 