Repository navigation
Weird lifetime error on closure in thread::scope #95527
Description
Activity
- addedA-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsA-lifetimesArea: Lifetimes / regionsArea: Lifetimes / regionsC-bugCategory: This is a bug.Category: This is a bug.D-confusingDiagnostics: Confusing error or lint that should be reworked.Diagnostics: Confusing error or lint that should be reworked.
on Mar 31, 2022 It compiles fine with
#![feature(nll)]enabled.- addedfixed-by-NLLBugs fixed, but only when NLL is enabled.Bugs fixed, but only when NLL is enabled.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.
on Mar 31, 2022 danielhenrymantilla commented
on Mar 31, 2022 ContributorMore actionsSo, I think I've managed to reduce it a bit further:
fn bar<'at_x, 'x> (at_x: &'at_x &'x u8) { ::std::thread::scope::<'at_x>(move |s| { s.spawn(move || drop(*at_x)); }); }
passes, but if we remove the
'at_xannotation (the value of'env):fn bar<'at_x, 'x> (at_x: &'at_x &'x u8) { ::std::thread::scope::<'_>(move |s| { s.spawn(move || drop(*at_x)); }); }
then it fails.
So basically the borrow checker, together with lifetime inference, is looking for a
'env?inferred lifetime parameter, so that for all'scope where 'env? ⊇ 'scope, we have'at_x ⊇ 'scope. And it doesn't see all those choices of'envwhere'at_x ⊇ 'env(e.g.,'env = 'at_x) would work.Stand-alone repro
The following snippet, involving no libraries, and tested from
1.0.0up to 2021-edition-nightly, fails with the same error when the lifetime parameter is not provided:struct T<'scope, 'up : 'scope> ( &'scope mut (&'scope (), &'up ()), // in practice `'up` can have whatever variance, even contra; it's the non-covariance of `'scope` which scares Rust into thinking it may have to deal with too big of a `'scope` ); impl<'scope, 'up : 'scope> T<'scope, 'up> { fn set<U> (self, _: &'scope U) {} } fn with_higher_order<'up, F : for<'scope> FnOnce(T<'scope, 'up>)> (_: F) {} fn foo<'at_x, 'x> (at_x: &'at_x &'x ()) { with_higher_order/*::<'at_x>*/(move |it| { it.set(at_x); }) }
I don't get why
#![feature(nll)]makes it compile – wasn't the whole idea of currently enabled "migration mode" to run old borrowck and nll just for cases nll rejects, but old borrowck accepts and thus we issue compat warning? I'm very confused... Because if old borrowck still have a veto posibility, then I don't get how even we can accept "problem case#1" and "problem case#2" now (which we do). From description of #57895 I understand that switch to nll can only cause code to stop compiling, not start.library/std/src/collections/hash/map.rsalso has code that doesn't compile if we remove#![feature(nll)].Should this be closed now that #95565 has been merged?
Reacted by Mara Bos- added a commit that references this issue
on Jun 16, 2022 - added a commit that references this issue
on Sep 15, 2022 - added a commit that references this issue
on Aug 29, 2024
This was reported here: #93203 (comment)
This should compile, but this fails to compile:
Error:
(rustc 1.61.0-nightly (1eb7258 2022-03-08))
It seems to be complaining that it cannot find a lifetime no longer than the one of the
x: &u8argument, but no shorter than the scope closure. The error is very hard to read though.It's interesting how the capture tuple
(&&u8,)of the closure is visible in the diagnostic.