-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Open
Labels
A-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsA-lifetimesArea: Lifetimes / regionsArea: Lifetimes / regionsD-terseDiagnostics: An error or lint that doesn't give enough information about the problem at hand.Diagnostics: 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.Relevant to the compiler team, which will review and decide on the PR/issue.
Description
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
Metadata
Metadata
Assignees
Labels
A-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsA-lifetimesArea: Lifetimes / regionsArea: Lifetimes / regionsD-terseDiagnostics: An error or lint that doesn't give enough information about the problem at hand.Diagnostics: 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.Relevant to the compiler team, which will review and decide on the PR/issue.