-
Notifications
You must be signed in to change notification settings - Fork 13.9k
Description
#[derive(Clone, Copy)]
struct Inv<'a>(*mut &'a ());
impl<'a> Inv<'a> {
fn outlived_by<'b: 'a>(self, _: Inv<'b>) {}
}
struct OutlivedBy<'a, 'b: 'a>(Inv<'a>, Inv<'b>);
fn closure_arg<'b, 'c, 'd>(_: impl for<'a> FnOnce(Inv<'a>, OutlivedBy<'a, 'b>, OutlivedBy<'a, 'c>, Inv<'d>)) {}
fn foo<'b, 'c, 'd: 'b>() {
closure_arg::<'b, 'c, 'd>(|a, b, c, d| {
a.outlived_by(b.1);
a.outlived_by(c.1);
b.1.outlived_by(d);
});
}should compile but results in the following error
error: lifetime may not live long enough
--> src/main.rs:9:5
|
8 | fn foo<'b, 'c, 'd: 'b>() {
| -- -- lifetime `'d` defined here
| |
| lifetime `'c` defined here
9 | / closure_arg::<'b, 'c, 'd>(|a, b, c, d| {
10 | | a.outlived_by(b.1);
11 | | a.outlived_by(c.1);
12 | | b.1.outlived_by(d);
13 | | });
| |______^ argument requires that `'d` must outlive `'c`
|
= help: consider adding the following bound: `'d: 'c`
= note: requirement occurs because of the type `Inv<'_>`, which makes the generic argument `'_` invariant
= note: the struct `Inv<'a>` is invariant over the parameter `'a`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about varianceWhat's going on is that the closure has the signature for<'a> fn(Inv<'a>, OutlivedBy<'a, 'b>, OutlivedBy<'a, 'c>, Inv<'d>) where 'b, 'c, and 'd are external regions.
We have assumptions 'b: 'a and 'c: 'a.
Borrow checking the closure results in requirements 'b: 'a, 'c: 'a, 'd: 'b.
rust/compiler/rustc_borrowck/src/region_infer/mod.rs
Lines 1222 to 1227 in 72fe2ff
| for shorter_fr in self.scc_values.universal_regions_outlived_by(longer_fr_scc) { | |
| if let RegionRelationCheckResult::Error = self.check_universal_region_relation( | |
| longer_fr, | |
| shorter_fr, | |
| propagated_outlives_requirements, | |
| ) { |
fn check_universal_region then checks for every universal region in the closure, whether it transitively outlives any other regions. We check 'b: 'a, 'c: 'a, 'd: 'b AND 'd: 'a (transitive)
'b: 'a and 'c: 'a are implied by our assumptions. We can propagate 'd: 'b to the parent without issues.
Propagating 'd: 'a is scuffed. Figuring out how to propagate this looks at upper bounds on 'a: 'b and 'c and simply requires 'd to outlive both. This is unnecessary and results in the incorrect outlives error in the parent.