Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
leo60228 opened this issue Oct 26, 2022 · 3 comments
Assignees
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@leo60228
Copy link
Contributor

leo60228 commented Oct 26, 2022

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.

@leo60228 leo60228 added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 26, 2022
@leo60228
Copy link
Contributor Author

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

@yanchen4791
Copy link
Contributor

@rustbot claim

Dylan-DPC added a commit to Dylan-DPC/rust that referenced this issue Jan 24, 2023
…ckh726

Add hint for missing lifetime bound on trait object when type alias is used

Fix issue rust-lang#103582.

The problem: When a type alias is used to specify the return type of the method in a trait impl, the suggestion for fixing the problem of "missing lifetime bound on trait object" of the trait impl will not be created. The issue caused by the code which searches for the return trait objects when constructing the hint suggestion is not able to find the trait objects since they are specified in the type alias path instead of the return path of the trait impl.

The solution: Trace the trait objects in the type alias path and provide them along with the alias span to generate the suggestion in case the type alias is used in return type of the method in the trait impl.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Jan 25, 2023
…ckh726

Add hint for missing lifetime bound on trait object when type alias is used

Fix issue rust-lang#103582.

The problem: When a type alias is used to specify the return type of the method in a trait impl, the suggestion for fixing the problem of "missing lifetime bound on trait object" of the trait impl will not be created. The issue caused by the code which searches for the return trait objects when constructing the hint suggestion is not able to find the trait objects since they are specified in the type alias path instead of the return path of the trait impl.

The solution: Trace the trait objects in the type alias path and provide them along with the alias span to generate the suggestion in case the type alias is used in return type of the method in the trait impl.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Jan 25, 2023
…ckh726

Add hint for missing lifetime bound on trait object when type alias is used

Fix issue rust-lang#103582.

The problem: When a type alias is used to specify the return type of the method in a trait impl, the suggestion for fixing the problem of "missing lifetime bound on trait object" of the trait impl will not be created. The issue caused by the code which searches for the return trait objects when constructing the hint suggestion is not able to find the trait objects since they are specified in the type alias path instead of the return path of the trait impl.

The solution: Trace the trait objects in the type alias path and provide them along with the alias span to generate the suggestion in case the type alias is used in return type of the method in the trait impl.
@chylex
Copy link

chylex commented Jun 24, 2023

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants