Open
Description
Given the following code: https://godbolt.org/z/he33YcxPM
struct C<'a, 'b>(&'a &'b ());
fn foo<'a>(f: impl FnOnce(&mut C<'_, 'a>)) {}
fn bar<'a>(f: impl FnOnce(&mut C<'_, 'a>)) {
foo(|x: &mut C<'_, 'a>| f(x))
}
The current output is the default borrow check diagnostic.
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
--> <source>:5:29
|
5 | foo(|x: &mut C<'_, 'a>| f(x))
| ^^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 4:8...
--> <source>:4:8
|
4 | fn bar<'a>(f: impl FnOnce(&mut C<'_, 'a>)) {
| ^^
note: ...so that the declared lifetime parameter bounds are satisfied
--> <source>:5:29
|
5 | foo(|x: &mut C<'_, 'a>| f(x))
| ^^^^
note: but, the lifetime must be valid for the anonymous lifetime #2 defined on the body at 5:9...
--> <source>:5:9
|
5 | foo(|x: &mut C<'_, 'a>| f(x))
| ^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that the expression is assignable
--> <source>:5:31
|
5 | foo(|x: &mut C<'_, 'a>| f(x))
| ^
= note: expected `&mut C<'_, 'a>`
found `&mut C<'_, '_>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0495`.
Compiler returned: 1
This code can be made to compile (ht @Manishearth) by observing that the compiler infers 'b: 'a
for C<'a, 'b>
:
struct C<'a, 'b>(&'a &'b ());
fn foo<'b, 'a: 'b>(f: impl FnOnce(&mut C<'b, 'a>)) {}
fn bar<'b, 'a: 'b>(f: impl FnOnce(&mut C<'b, 'a>)) {
foo(|x: &mut C<'b, 'a>| f(x))
}
It would be useful for rustc to suggest this fix, but it looks a bit hard to find. Either way, this one puzzled me for several hours until I poked Manish.
It is unclear if this is a bug, but it seems incorrect for rustc to accept the original code for borrow check at all, since x
types at for<'1, '2> C<'1, '2>
in the closure argument, not for<'1> C<'1, 'a>
, as the user has written. In particular, the following compiles, but should probably be rejected:
struct C<'a, 'b>(&'a &'b ());
fn foo<'a>(f: impl FnOnce(&mut C<'_, 'a>)) {}
fn bar<'a>(f: impl FnOnce(&mut C<'_, 'a>)) {
foo(|x: &mut C<'_, 'a>| {})
}
Metadata
Metadata
Assignees
Labels
Area: The borrow checkerArea: Closures (`|…| { … }`)Area: Messages for errors, warnings, and lintsArea: Higher-ranked things (e.g., lifetimes, types, trait bounds aka HRTBs)Area: Lifetimes / regionsDiagnostics: Confusing error or lint that should be reworked.Diagnostics: Confusing error or lint; hard to understand for new users.Relevant to the compiler team, which will review and decide on the PR/issue.