rust-lang / rust · Issue No. 163155
Ill-formed closure argument and return types during borrow check.
#151510 introduces WF checks on closure argument and return types to fix https://github.com/rust-lang/rust/issues/104478. However, a crater run caught some crates depending on this behaviour. So we now make any errors caused by this check to be FCW, which will be turned into a hard error in a future release.
trait Bound<'a> {}
impl<'a> Bound<'a> for &'a str {}
struct Container<'a, K>
where
K: Bound<'a>,
{
_d: &'a [u8],
_k: std::marker::PhantomData<K>,
}
fn main() {
let _closure = |_: Container<&str>| {};
}
Which outputs:
warning: lifetime may not live long enough
--> repro.rs:13:21
|
13 | let _closure = |_: Container<&str>| {};
| ^ - let's call the lifetime of this reference `'2`
| |
| has type `Container<'1, &str>`
| requires that `'1` must outlive `'2`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #163155 <https://github.com/rust-lang/rust/issues/163155>
warning: lifetime may not live long enough
--> repro.rs:13:21
|
13 | let _closure = |_: Container<&str>| {};
| ^ - let's call the lifetime of this reference `'2`
| |
| has type `Container<'1, &str>`
| requires that `'2` must outlive `'1`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #163155 <https://github.com/rust-lang/rust/issues/163155>
It's not really easy to circumvent this when you really want to use closures.
One way: Originally posted by @lcnr in https://github.com/rust-lang/rust/issues/151510#issuecomment-5114720867
you can work around this with deduce_closure_signature but I don't want to force users to do so.
trait Bound<'a> {}
impl<'a> Bound<'a> for &'a str {}
struct Container<'a, K: Bound<'a>>(std::marker::PhantomData<*mut (&'a (), K)>);
fn id<F: for<'a> FnOnce(Container<'a, &'a str>)>(f: F) -> F { f }
fn main() {
let _ = id(|x: Container<'_, &str>| drop(x)); // compiles
}
Using a nightly feature #![feature(closure_lifetime_binder)] : https://github.com/rust-lang/rust/issues/97362
TODO: others?
TODO
See #151510
Relay reads this issue against the repository's contribution signals: the files it is likely to touch, how the maintainers triage work this size, and what the first contribution would exercise.
The full analysis for this issue is still being assembled. Until then, the description above and the thread on GitHub are the most reliable context.