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

Confusing diagnostic when forgetting to capture lifetime in a APIT #124479

Open
WaffleLapkin opened this issue Apr 28, 2024 · 0 comments
Open

Confusing diagnostic when forgetting to capture lifetime in a APIT #124479

WaffleLapkin opened this issue Apr 28, 2024 · 0 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: lifetime related D-terse Diagnostics: An error or lint that doesn't give enough information about the problem at hand. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@WaffleLapkin
Copy link
Member

WaffleLapkin commented Apr 28, 2024

Code

trait A<'a> {
    type Assoc;
}

trait B {}

fn f(_: impl for<'a> A<'a, Assoc = impl B>) {}

impl<'a> A<'a> for () {
    type Assoc = &'a u8;
}

impl B for &u8 {}

fn main() {
    f(());
}

Current output

error[E0308]: mismatched types
  --> ./t.rs:16:5
   |
16 |     f(());
   |     ^^^^^ one type is more general than the other
   |
   = note: expected reference `&'a _`
              found reference `&_`
note: the lifetime requirement is introduced here
  --> ./t.rs:7:28
   |
7  | fn f(_: impl for<'a> A<'a, Assoc = impl B>) {}
   |                            ^^^^^^^^^^^^^^

Desired output

error[E0308]: mismatched types
  --> ./t.rs:16:5
   |
16 |     f(());
   |     ^^^^^ one type is more general than the other
   |
   = note: expected reference `for<'a> &'a _`
              found reference `&'0 _` for some specific lifetime `'0`
   = note: `impl B` can't name `'a`
note: the lifetime requirement is introduced here
  --> ./t.rs:7:28
   |
7  | fn f(_: impl for<'a> A<'a, Assoc = impl B>) {}
   |                            ^^^^^^^^^^^^^^

Rationale and extra context

It is not very clear from the error why impl B introduces the lifetime requirement or why we "found" a &_ (this leaks generalizer impl kinda). Ideally we would explain the actual cause of the error (impl B introduces a new generic parameter outside of the scope of for<'a>).

I don't like having for<'a> &'a _ in the desired error either, because it implies that it's a type that exists, but I couldn't come up with a better explanation for the fact that 'a is from the for<'a>...

Maybe we could even suggest impl for<'a> A<'a, Assoc: B>) but @BoxyUwU says it's probably hard. We could just lint on impl Trait<Assoc = impl Other> as a style thing suggesting Assoc: Other since it allows more things.

Other cases

If you add `+ 'a` the diagnostic is a bit better:


trait A<'a> {
    type Assoc;
}

trait B {}

fn f(_: impl for<'a> A<'a, Assoc = impl B + 'a>) {}

impl<'a> A<'a> for () {
    type Assoc = &'a u8;
}

impl B for &u8 {}

fn main() {
    f(());
}
error: `impl Trait` can only mention lifetimes from an fn or impl
 --> ./t.rs:7:45
  |
7 | fn f(_: impl for<'a> A<'a, Assoc = impl B + 'a>) {}
  |                  -- lifetime declared here  ^^

error[E0308]: mismatched types
  --> ./t.rs:16:5
   |
16 |     f(());
   |     ^^^^^ one type is more general than the other
   |
   = note: expected reference `&'a _`
              found reference `&_`
note: the lifetime requirement is introduced here
  --> ./t.rs:7:28
   |
7  | fn f(_: impl for<'a> A<'a, Assoc = impl B + 'a>) {}
   |                            ^^^^^^^^^^^^^^^^^^^

Rust Version

rustc 1.79.0-nightly (ef8b9dcf2 2024-04-24)
binary: rustc
commit-hash: ef8b9dcf23700f2e2265317611460d3a65c19eff
commit-date: 2024-04-24
host: x86_64-unknown-linux-gnu
release: 1.79.0-nightly
LLVM version: 18.1.4

Anything else?

No response

@WaffleLapkin WaffleLapkin added A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: lifetime related T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. D-terse Diagnostics: An error or lint that doesn't give enough information about the problem at hand. labels Apr 28, 2024
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 A-lifetimes Area: lifetime related D-terse Diagnostics: An error or lint that doesn't give enough information about the problem at hand. 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

1 participant