#[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 variance
What'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.
|
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.
should compile but results in the following error
What'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'dare external regions.We have assumptions
'b: 'aand'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
fn check_universal_regionthen checks for every universal region in the closure, whether it transitively outlives any other regions. We check'b: 'a,'c: 'a,'d: 'bAND'd: 'a(transitive)'b: 'aand'c: 'aare implied by our assumptions. We can propagate'd: 'bto the parent without issues.Propagating
'd: 'ais scuffed. Figuring out how to propagate this looks at upper bounds on'a:'band'cand simply requires'dto outlive both. This is unnecessary and results in the incorrect outlives error in the parent.