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

Lifetimes not inferred when using Self constructor instead of named one #102494

Closed
tomkarw opened this issue Sep 29, 2022 · 4 comments
Closed

Lifetimes not inferred when using Self constructor instead of named one #102494

tomkarw opened this issue Sep 29, 2022 · 4 comments
Labels
C-bug Category: This is a bug.

Comments

@tomkarw
Copy link

tomkarw commented Sep 29, 2022

I tried this code:

struct A<'a> {
    x: &'a str,
}

impl<'a> A<'a> {
    pub fn new<'b>(x: &'b str) -> A<'b> {
        Self { x }
    }
}

Link to playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c11bc82b8e33841719b8e1fb765d0529.

I expected to see this happen:

The code to compile, the same way this snippet compiles (notice that only Self -> A changed)

struct A<'a> {
    x: &'a str,
}

impl<'a> A<'a> {
    pub fn new<'b>(x: &'b str) -> A<'b> {
        A { x }
    }
}

Instead, this happened:

error: lifetime may not live long enough
 --> src/lib.rs:7:9
  |
5 | impl<'a> A<'a> {
  |      -- lifetime `'a` defined here
6 |     pub fn new<'b>(x: &'b str) -> A<'b> {
  |                -- lifetime `'b` defined here
7 |         Self { x }
  |         ^^^^^^^^^^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
  |
  = help: consider adding the following bound: `'a: 'b`

error: lifetime may not live long enough
 --> src/lib.rs:7:16
  |
5 | impl<'a> A<'a> {
  |      -- lifetime `'a` defined here
6 |     pub fn new<'b>(x: &'b str) -> A<'b> {
  |                -- lifetime `'b` defined here
7 |         Self { x }
  |                ^ this usage requires that `'b` must outlive `'a`
  |
  = help: consider adding the following bound: `'b: 'a`

help: `'a` and `'b` must be the same: replace one with the other

The actual fix is to unify the lifetimes, but the fact that changing the constructor from Self to named fixed the issue is confusing and unexpected. Seems like an edge-case during compiler lifetime resolution.

Real world occurrence: durch/rust-s3@a6adbf2 (fails before this commit, but works after the Self -> HyperRequest change).

Meta

rustc --version --verbose:

rustc 1.63.0 (4b91a6ea7 2022-08-08)

I see same behavior on rustc 1.65.0-beta.2 (e5da98475 2022-09-24) and rustc 1.66.0-nightly (98ad6a551 2022-09-17).

@tomkarw tomkarw added the C-bug Category: This is a bug. label Sep 29, 2022
@compiler-errors
Copy link
Member

This is not a bug. The identifier Self, unlike A, is not a type constructor -- it's a single type in the scope of the impl. So when one writes Self within that impl, it always means A<'a>, and never A<'_>.

@tomkarw
Copy link
Author

tomkarw commented Sep 30, 2022

Got it. Two questions then:

  • Why is Self alias for A<'a> and not the more relaxed A<'_>?
  • Could we at least make a better compiler message, that basically notices this specific case and suggest the proper change?
    Something like:
`Self` is an alias for `A<'a>` in this context, try using the type constructor `A<'_>` explicitly

@compiler-errors
Copy link
Member

Why is Self alias for A<'a> and not the more relaxed A<'_>?

because Self refers to exactly the type that's in the impl block's header, i.e. A<'a>. It does no processing of that type, just exactly refers to it.

Could we at least make a better compiler message, that basically notices this specific case and suggest the proper change?

I think @aliemjay was working on a PR for this.

@aliemjay
Copy link
Member

aliemjay commented Oct 9, 2022

The diagnostic issue is tracked in #101393, so this can be closed as a duplicate.

@tomkarw tomkarw closed this as completed Oct 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

3 participants