Skip to content

Commit f27166d

Browse files
Auto merge of #148329 - LorrensP-2158466:closure-prop, r=<try>
Do not propogate unnecessary closure constraints.
2 parents f5711a5 + a36dc08 commit f27166d

File tree

3 files changed

+53
-0
lines changed

3 files changed

+53
-0
lines changed

compiler/rustc_borrowck/src/region_infer/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,6 +1292,26 @@ impl<'tcx> RegionInferenceContext<'tcx> {
12921292
// so slightly larger than `shorter_fr`.
12931293
let shorter_fr_plus =
12941294
self.universal_region_relations.non_local_upper_bounds(shorter_fr);
1295+
1296+
// If any of the `shorter_fr+` regions are already outlived by `fr-`, we propagate only those.
1297+
// Otherwise, we might incorrectly reject valid code.
1298+
//
1299+
// Consider this example (`'b: 'a` == `a -> b`), where we try to propagate `'d: 'a`:
1300+
// a --> b --> d
1301+
// \
1302+
// \-> c
1303+
// Here, `shorter_fr+` of `'a` == `['b, 'c]`.
1304+
// Propagating `'d: 'b` is correct and should occur; `'d: 'c` is redundant because of `'d: 'b`
1305+
// and could reject valid code.
1306+
//
1307+
// So we filter `shorter_fr+` to regions already outlived by `fr-`, but if the filter yields an empty set,
1308+
// we fall back to the original one.
1309+
let subset: Vec<_> = shorter_fr_plus
1310+
.iter()
1311+
.filter(|&&fr_plus| self.eval_outlives(fr_minus, fr_plus))
1312+
.copied()
1313+
.collect();
1314+
let shorter_fr_plus = if subset.is_empty() { shorter_fr_plus } else { subset };
12951315
debug!("try_propagate_universal_region_error: shorter_fr_plus={:?}", shorter_fr_plus);
12961316
for fr in shorter_fr_plus {
12971317
// Push the constraint `fr-: shorter_fr+`
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//@ check-pass
2+
3+
4+
struct MyTy<'x, 'a, 'b>(std::cell::Cell<(&'x &'a u8, &'x &'b u8)>);
5+
fn wf<T>(_: T) {}
6+
fn test<'a, 'b>() {
7+
|_: &'a u8, x: MyTy<'_, 'a, 'b>| wf(x);
8+
|x: MyTy<'_, 'a, 'b>, _: &'a u8| wf(x);
9+
}
10+
11+
fn main(){}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//@ check-pass
2+
3+
#[derive(Clone, Copy)]
4+
struct Inv<'a>(*mut &'a ());
5+
impl<'a> Inv<'a> {
6+
fn outlived_by<'b: 'a>(self, _: Inv<'b>) {}
7+
}
8+
struct OutlivedBy<'a, 'b: 'a>(Inv<'a>, Inv<'b>);
9+
10+
fn closure_arg<'b, 'c, 'd>(
11+
_: impl for<'a> FnOnce(Inv<'a>, OutlivedBy<'a, 'b>, OutlivedBy<'a, 'c>, Inv<'d>),
12+
) {
13+
}
14+
fn foo<'b, 'c, 'd: 'b>() {
15+
closure_arg::<'b, 'c, 'd>(|a, b, c, d| {
16+
a.outlived_by(b.1);
17+
a.outlived_by(c.1);
18+
b.1.outlived_by(d);
19+
});
20+
}
21+
22+
fn main() {}

0 commit comments

Comments
 (0)