1

Where is the 'static lifetime requirement coming from when using a trait type in std::rc::Rc and how can I prevent it? E.g. when trying to compile this code

trait Handler{}

fn add(a: std::rc::Rc<Handler>) {
}

fn main() {
    add(0);
}

rust reports

error[E0308]: mismatched types
 --> test.rs:7:9
...
  = note: expected type `std::rc::Rc<Handler + 'static>`
             found type `{integer}`

NOTE: the error itself is expected; I am just interested in the Handler + 'static diagnostic output. The Real program creates instances of a trait type, stores them into a HashMap and runs a type specific function on it. It fails to compile with

| - borrowed value only lives until here
|
= note: borrowed value must be valid for the static lifetime...

at this place.

Second example

The following code is more real-world and demonstrates the issue perhaps better:

trait Handler {
}

struct SomeHandler<'a>(&'a u32);

impl <'a> SomeHandler<'a> {
    fn new(a: &'a u32) -> std::rc::Rc<Handler> {
        std::rc::Rc::new(SomeHandler(a))
    }
}

impl <'a> Handler for SomeHandler<'a> {
}

fn main() {
    let a: u32;
    SomeHandler::new(&a);
}

It fails with

8 |         std::rc::Rc::new(SomeHandler(a))
  |                                      ^
  = note: but, the lifetime must be valid for the static lifetime...
  = note: ...so that the expression is assignable:
          expected std::rc::Rc<Handler + 'static>
             found std::rc::Rc<Handler>

Why explicit lifetimes do not work

The simple demo might be fixed by adding an explicit lifetime (e.g. Rc<Handler + 'a>). Unfortunately, this is not an option (nor trying to make anything 'static) because real code is intended to look like

struct PollRegistry {
    ...
    handlers: std::collections::HashMap<mio::Token, std::rc::Weak<PollHandler>>,
}

impl PollRegistry {
    fn register<'a>(&mut self, handler: &std::rc::Rc<PollHandler>,
                interest: mio::Ready, opts: mio::PollOpt)
                -> std::io::Result<()> {
        ....
        self.handlers.insert(token, std::rc::Rc::downgrade(handler));
    }
}

and methods in PollHandler specializations create and own other PollHandler specializations which are registered in the registry by these methods.

rustc 1.27.1

ensc
  • 6,704
  • 14
  • 22
  • `fn new(a: &'a u32) -> std::rc::Rc` – Boiethios Aug 03 '18 at 11:45
  • 1
    Possible duplicate of [The compiler suggests I add a 'static lifetime because the parameter type may not live long enough, but I don't think that's what I want](https://stackoverflow.com/questions/40053550/the-compiler-suggests-i-add-a-static-lifetime-because-the-parameter-type-may-no) – Boiethios Aug 03 '18 at 11:48
  • @Boiethios works in demo code, but purpose if `Rc<>` indirection was to avoid lifetime specifications completely. – ensc Aug 03 '18 at 11:56
  • 1
    You cannot do that with the demo code because you most own the object to remove the lifetime specification. You **must** specify the lifetime of a reference. See the answer of the duplicate, it explains how to solve your issue. – Boiethios Aug 03 '18 at 11:58
  • @Boiethios I am 250% sure that I do not want to add a `'static` lifetime requirement somewhere in my code (because objects are allocated dynamically). Things are fine when I return `Rc` directly (but rest breaks) and specifying lifetimes like `Rc<... + 'a>` is not possible because `add()` will be called e.g. from functions of the trait objects itself to create other handlers (which are owned by the calling object). – ensc Aug 03 '18 at 12:17
  • Did you read the answers of the duplicate? [This one](https://stackoverflow.com/a/40053649/4498831) will help you to understand. – Boiethios Aug 03 '18 at 12:51
  • *a `'static` lifetime [...] because objects are allocated dynamically* — That's not what `'static` means. It basically means that the returned type will not contain any references. If the returned type *did* contain a reference, then it couldn't live longer than the referenced value, that's a giant purpose of the Rust language. Perhaps you are interested in using `Rc` / `Arc` to have lighter-weight shared copies a value. – Shepmaster Aug 03 '18 at 12:55
  • @Shepmaster yes, I am already using `Rc<>`, but rust seems to require an explicit lifetime parameter when working with traits (which is not the case when using "normal" objects). – ensc Aug 03 '18 at 12:59
  • Perhaps you could read over [Why is adding a lifetime to a trait with the plus operator (Iterator + 'a) needed?](https://stackoverflow.com/q/42028470/155423) if you don't understand that. – Shepmaster Aug 03 '18 at 13:05
  • Possible duplicate of [Why is adding a lifetime to a trait with the plus operator (Iterator + 'a) needed?](https://stackoverflow.com/questions/42028470/why-is-adding-a-lifetime-to-a-trait-with-the-plus-operator-iteratoritem-foo) – trent Aug 03 '18 at 13:38
  • I think your question is answered clearly by [this answer](https://stackoverflow.com/a/42028805/3650362) (the `'static` appears by default on trait objects when you don't provide a lifetime). Your "real code" with the `PollRegistry` might have other issues -- why have the `'a` lifetime parameter at all if you're not going to use it? -- but if you want help with that, please make a [mcve] so that we can tell what you're dealing with. You might be trying to do something unsound. – trent Aug 03 '18 at 13:45

0 Answers0