Skip to content

Hint for missing lifetime bound on trait object is missing if type alias is used #103582

Description

@leo60228

Given the following code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=a0979812dc1acbc732481dd2d3185637

trait Greeter {
    fn greet(&self);
}

type BoxedGreeter = Box<dyn Greeter>;

struct FixedGreeter<'a>(pub &'a str);

impl Greeter for FixedGreeter<'_> {
    fn greet(&self) {
        println!("{}", self.0)
    }
}

struct Greetings(pub Vec<String>);

impl Greetings {
    pub fn get(&self, i: usize) -> BoxedGreeter {
        Box::new(FixedGreeter(&self.0[i]))
    }
}

The current output is:

error: lifetime may not live long enough
  --> src/lib.rs:19:9
   |
18 |     pub fn get(&self, i: usize) -> BoxedGreeter {
   |                - let's call the lifetime of this reference `'1`
19 |         Box::new(FixedGreeter(&self.0[i]))
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`

However, by removing the type alias: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=bfde1cf5c8a72349b117aa21bbd61c3d

trait Greeter {
    fn greet(&self);
}

struct FixedGreeter<'a>(pub &'a str);

impl Greeter for FixedGreeter<'_> {
    fn greet(&self) {
        println!("{}", self.0)
    }
}

struct Greetings(pub Vec<String>);

impl Greetings {
    pub fn get(&self, i: usize) -> Box<dyn Greeter> {
        Box::new(FixedGreeter(&self.0[i]))
    }
}

The output looks like this, which is much more helpful:

error: lifetime may not live long enough
  --> src/lib.rs:17:9
   |
16 |     pub fn get(&self, i: usize) -> Box<dyn Greeter> {
   |                - let's call the lifetime of this reference `'1`
17 |         Box::new(FixedGreeter(&self.0[i]))
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
   |
help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound
   |
16 |     pub fn get(&self, i: usize) -> Box<dyn Greeter + '_> {
   |                                                    ++++

Without the hint, this error isn't very helpful for beginners, as it doesn't do anything to explain why '1 must outlive 'static. It would be helpful if a similar hint could be provided when a type alias is used.

Activity

  1. added
    A-diagnosticsArea: Messages for errors, warnings, and lints
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Oct 26, 2022
  2. leo60228 commented on Oct 26, 2022

    @leo60228
    ContributorAuthor

    A similar issue occurs for fields of a struct, but that might be harder to fix.

  3. yanchen4791 commented on Dec 1, 2022

    @yanchen4791

    @rustbot claim

  4. added a commit that references this issue on Jan 24, 2023
  5. added 2 commits that reference this issue on Jan 25, 2023
  6. chylex commented on Jun 24, 2023

    @chylex

    I've run into the same confusing error, but with a function call:

    fn create_confirmation_dialog<'a>() -> Option<MessageDialogLayer<'a>> {
    	Some(MessageDialogLayer::new(Color::LightRed, "Error", "Test", Box::new(MessageDialogActionMap::ok())))
    }

    obrazek

    After searching for a while, I found it was because a Box<dyn MessageDialogActions<'a> parameter in my new function was implicitly converted into Box<dyn ... + 'static>. Very confusing for a beginner, especially with the additional compiler notes about variance that don't seem to even be relevant here?

    pub fn new(..., actions: Box<dyn MessageDialogActions<'a>>) -> Self      // error
    pub fn new(..., actions: Box<dyn MessageDialogActions<'a> + 'a>) -> Self // correct

    This is the closest existing issue I found, is this a similar enough case or should I open a new issue?

  7. added
    A-lifetimesArea: Lifetimes / regions
    D-terseDiagnostics: An error or lint that doesn't give enough information about the problem at hand.
    A-dyn-traitArea: trait objects, vtable layout
    on Dec 21, 2024
  8. fmease commented on Dec 21, 2024

    @fmease
    Member

    Re. the snippet from the issue description, ideally the compiler would suggest:

    - type BoxedGreeter = Box<dyn Greeter>;
    + type BoxedGreeter<'a> = Box<dyn Greeter + 'a>;

    This makes the snippet compile (unless the lint elided_lifetime_in_paths was denied) because BoxedGreeter in the return type means BoxGreeter<'_> which "picks up" the anonymous lifetime of the self parameter.

  9. estebank commented on Nov 11, 2025

    @estebank
    Contributor

    Current output:

    error: lifetime may not live long enough
      --> src/lib.rs:19:9
       |
    18 |     pub fn get(&self, i: usize) -> BoxedGreeter {
       |                - let's call the lifetime of this reference `'1`
    19 |         Box::new(FixedGreeter(&self.0[i]))
       |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
       |
    help: to declare that the trait object captures data from argument `self`, you can add a lifetime parameter `'a` in the type alias
       |
     5 | type BoxedGreeter<'a> = Box<dyn Greeter + 'a>;
       |                  ++++                   ++++
    
    error: lifetime may not live long enough
      --> src/lib.rs:17:9
       |
    16 |     pub fn get(&self, i: usize) -> Box<dyn Greeter> {
       |                - let's call the lifetime of this reference `'1`
    17 |         Box::new(FixedGreeter(&self.0[i]))
       |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
       |
    help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound
       |
    16 |     pub fn get(&self, i: usize) -> Box<dyn Greeter + '_> {
       |                                                    ++++
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsA-dyn-traitArea: trait objects, vtable layoutA-lifetimesArea: Lifetimes / regionsD-terseDiagnostics: An error or lint that doesn't give enough information about the problem at hand.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions