E0772 - Error codes index
Description: Book listing all Rust error codes

# Error code E0772

#### Note: this error code is no longer emitted by the compiler.

A trait object has some specific lifetime `'1`, but it was used in a way that requires it to have a `'static` lifetime.

Example of erroneous code:

    #![allow(unused)]
    fn main() {
    trait BooleanLike {}
    trait Person {}

    impl BooleanLike for bool {}

    impl dyn Person {
        fn is_cool(&self) -> bool {
            // hey you, you're pretty cool
            true
        }
    }

    fn get_is_cool<'p>(person: &'p dyn Person) -> impl BooleanLike {
        // error: `person` has an anonymous lifetime `'p` but calling
        //        `print_cool_fn` introduces an implicit `'static` lifetime
        //        requirement
        person.is_cool()
    }
    }

The trait object `person` in the function `get_is_cool`, while already being behind a reference with lifetime `'p`, also has it's own implicit lifetime, `'2`.

Lifetime `'2` represents the data the trait object might hold inside, for example:

    #![allow(unused)]
    fn main() {
    trait MyTrait {}

    struct MyStruct<'a>(&'a i32);

    impl<'a> MyTrait for MyStruct<'a> {}
    }

With this scenario, if a trait object of `dyn MyTrait + '2` was made from `MyStruct<'a>`, `'a` must live as long, if not longer than `'2`. This allows the trait object's internal data to be accessed safely from any trait methods. This rule also goes for any lifetime any struct made into a trait object may have.

In the implementation for `dyn Person`, the `'2` lifetime representing the internal data was omitted, meaning that the compiler inferred the lifetime `'static`. As a result, the implementation's `is_cool` is inferred by the compiler to look like this:

    #![allow(unused)]
    fn main() {
    trait Person {}

    impl dyn Person {
    fn is_cool<'a>(self: &'a (dyn Person + 'static)) -> bool {unimplemented!()}
    }
    }

While the `get_is_cool` function is inferred to look like this:

    #![allow(unused)]
    fn main() {
    trait Person {}
    trait BooleanLike {}

    fn get_is_cool<'p, R: BooleanLike>(person: &'p (dyn Person + 'p)) -> R {
        unimplemented!()
    }
    }

Which brings us to the core of the problem; the assignment of type `&'_ (dyn Person + '_)` to type `&'_ (dyn Person + 'static)` is impossible.

Fixing it is as simple as being generic over lifetime `'2`, as to prevent the compiler from inferring it as `'static`:

    #![allow(unused)]
    fn main() {
    trait Person {}

    impl<'d> dyn Person + 'd {/* ... */}

    // This works too, and is more elegant:
    //impl dyn Person + '_ {/* ... */}
    }

See the [Rust Reference on Trait Object Lifetime Bounds][trait-objects] for more information on trait object lifetimes.