Putting a value of type
T in an
Rc doesn't – can't – change the lifetime annotations of
T: 'a means that values of type
T only contain references that point to values living at least as long as
'a. Thus, instances of
T are valid to hold on to for the lifetime
This is unchanged by where you move such instances. Putting stuff in an
Rc is like owning it (since Rc doesn't borrow anything). But if you own a value and move it somewhere, and that value borrows something, then it still is borrowing the previously-borrowed thing. To the borrow checker,
Rc<T> have exactly the same ownership structure.
Smart pointers can't keep stuff alive by-reference. Because nothing can keep stuff alive by-reference. References are for borrowing, not for owning.
Box, and other smart pointer types can't change this, nor can any other type. Thus, wrapping a type in another type can't possibly change the validity of references in the inner type.
There is one more thing that you might be misunderstanding, and which is the direct cause of the compiler error. A trait object is a dynamic type, unknown to the compiler at the points where you actually, usefully interact with it (i.e., at any time after construction). But the compiler always needs lifetimes in order to apply borrow checking and reject invalid code!
However, for most types, the compiler can infer the most important relationships between implicitly-generated and user-annotated lifetimes. Usually, when you use a static type, the compiler can look inside it, and know exactly what is inside, and what you should and should not be allowed to do with instances of that type.
But for a trait object, the specific underlying type it was created from is unknown. The compiler can't possibly "look into" a trait object and check whether it contains any temporary references, because by definition the type is only known at runtime, not at compile time. Thus, you must explicitly add an annotation to the trait object that tells the compiler whether there are temporary references of a given lifetime inside.
There are at least two solutions to your problem:
- In function signatures, a bare (owned)
dyn Trait is actually implicitly expected to be
'static. Thus, you can slap a
'static bound on your
T and call it a day. Demo.
- You can propagate any non-
'static lifetimes from your handler to your generic type. Demo.
In either case, don't accept an
&Rc<T> and clone it. Accepting an explicit, concretely-typed reference-to-smart-pointer is an anti-pattern, and it's almost never what you want. (It can come up in generics accidentally, but here you specifically requested
&Rc<T>). You should just accept an
Rc<T> by value. The caller can then decide to pass it by-value if they don't need it anymore, or clone it if necessary. With your current signature, it is always cloned, even if it is unnecessary.