Skip to content

Commit 9d74bff

Browse files
committed
smarter algorithm for finding an equal region
Smarter and simpler!
1 parent 09524bf commit 9d74bff

File tree

4 files changed

+11
-106
lines changed

4 files changed

+11
-106
lines changed

compiler/rustc_borrowck/src/region_infer/mod.rs

+9-67
Original file line numberDiff line numberDiff line change
@@ -1098,51 +1098,22 @@ impl<'tcx> RegionInferenceContext<'tcx> {
10981098
let tcx = infcx.tcx;
10991099

11001100
let ty = tcx.fold_regions(ty, |r, _depth| {
1101-
let region_vid = self.to_region_vid(r);
1101+
let r_vid = self.to_region_vid(r);
1102+
let r_scc = self.constraint_sccs.scc(r_vid);
11021103

11031104
// The challenge if this. We have some region variable `r`
11041105
// whose value is a set of CFG points and universal
11051106
// regions. We want to find if that set is *equivalent* to
11061107
// any of the named regions found in the closure.
1107-
//
1108-
// To do so, we compute the
1109-
// `non_local_universal_upper_bound`. This will be a
1110-
// non-local, universal region that is greater than `r`.
1111-
// However, it might not be *contained* within `r`, so
1112-
// then we further check whether this bound is contained
1113-
// in `r`. If so, we can say that `r` is equivalent to the
1114-
// bound.
1115-
//
1116-
// Let's work through a few examples. For these, imagine
1117-
// that we have 3 non-local regions (I'll denote them as
1118-
// `'static`, `'a`, and `'b`, though of course in the code
1119-
// they would be represented with indices) where:
1120-
//
1121-
// - `'static: 'a`
1122-
// - `'static: 'b`
1123-
//
1124-
// First, let's assume that `r` is some existential
1125-
// variable with an inferred value `{'a, 'static}` (plus
1126-
// some CFG nodes). In this case, the non-local upper
1127-
// bound is `'static`, since that outlives `'a`. `'static`
1128-
// is also a member of `r` and hence we consider `r`
1129-
// equivalent to `'static` (and replace it with
1130-
// `'static`).
1131-
//
1132-
// Now let's consider the inferred value `{'a, 'b}`. This
1133-
// means `r` is effectively `'a | 'b`. I'm not sure if
1134-
// this can come about, actually, but assuming it did, we
1135-
// would get a non-local upper bound of `'static`. Since
1136-
// `'static` is not contained in `r`, we would fail to
1137-
// find an equivalent.
1138-
let upper_bound = self.non_local_universal_upper_bound(region_vid);
1139-
if self.region_contains(region_vid, upper_bound) {
1140-
tcx.mk_re_var(upper_bound)
1141-
} else {
1108+
// To do so, we simply check every candidate `u_r` for equality.
1109+
self.scc_values
1110+
.universal_regions_outlived_by(r_scc)
1111+
.filter(|&u_r| !self.universal_regions.is_local_free_region(u_r))
1112+
.find(|&u_r| self.eval_equal(u_r, r_vid))
1113+
.map(|u_r| tcx.mk_re_var(u_r))
11421114
// In the case of a failure, use `ReErased`. We will eventually
11431115
// return `None` in this case.
1144-
tcx.lifetimes.re_erased
1145-
}
1116+
.unwrap_or(tcx.lifetimes.re_erased)
11461117
});
11471118

11481119
debug!("try_promote_type_test_subject: folded ty = {:?}", ty);
@@ -1155,35 +1126,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
11551126
Some(ClosureOutlivesSubject::Ty(ClosureOutlivesSubjectTy::new(tcx, ty)))
11561127
}
11571128

1158-
/// Given some universal or existential region `r`, finds a
1159-
/// non-local, universal region `r+` that outlives `r` at entry to (and
1160-
/// exit from) the closure. In the worst case, this will be
1161-
/// `'static`.
1162-
///
1163-
/// This is used for two purposes. First, if we are propagated
1164-
/// some requirement `T: r`, we can use this method to enlarge `r`
1165-
/// to something we can encode for our creator (which only knows
1166-
/// about non-local, universal regions). It is also used when
1167-
/// encoding `T` as part of `try_promote_type_test_subject` (see
1168-
/// that fn for details).
1169-
///
1170-
/// This is based on the result `'y` of `universal_upper_bound`,
1171-
/// except that it converts further takes the non-local upper
1172-
/// bound of `'y`, so that the final result is non-local.
1173-
fn non_local_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
1174-
debug!("non_local_universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
1175-
1176-
let lub = self.universal_upper_bound(r);
1177-
1178-
// Grow further to get smallest universal region known to
1179-
// creator.
1180-
let non_local_lub = self.universal_region_relations.non_local_upper_bound(lub);
1181-
1182-
debug!("non_local_universal_upper_bound: non_local_lub={:?}", non_local_lub);
1183-
1184-
non_local_lub
1185-
}
1186-
11871129
/// Returns a universally quantified region that outlives the
11881130
/// value of `r` (`r` may be existentially or universally
11891131
/// quantified).

compiler/rustc_borrowck/src/type_check/free_region_relations.rs

-25
Original file line numberDiff line numberDiff line change
@@ -93,31 +93,6 @@ impl UniversalRegionRelations<'_> {
9393
res
9494
}
9595

96-
/// Returns the "postdominating" bound of the set of
97-
/// `non_local_upper_bounds` for the given region.
98-
pub(crate) fn non_local_upper_bound(&self, fr: RegionVid) -> RegionVid {
99-
let upper_bounds = self.non_local_upper_bounds(fr);
100-
101-
// In case we find more than one, reduce to one for
102-
// convenience. This is to prevent us from generating more
103-
// complex constraints, but it will cause spurious errors.
104-
let post_dom = self.inverse_outlives.mutual_immediate_postdominator(upper_bounds);
105-
106-
debug!("non_local_bound: post_dom={:?}", post_dom);
107-
108-
post_dom
109-
.and_then(|post_dom| {
110-
// If the mutual immediate postdom is not local, then
111-
// there is no non-local result we can return.
112-
if !self.universal_regions.is_local_free_region(post_dom) {
113-
Some(post_dom)
114-
} else {
115-
None
116-
}
117-
})
118-
.unwrap_or(self.universal_regions.fr_static)
119-
}
120-
12196
/// Finds a "lower bound" for `fr` that is not local. In other
12297
/// words, returns the largest (*) known region `fr1` that (a) is
12398
/// outlived by `fr` and (b) is not local.

tests/ui/nll/closure-requirements/type-test-subject-non-trivial-region.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// chek-fail
2-
// known-bug: #108639
1+
// See #108639 for description.
2+
// check-pass
33

44
trait Trait {
55
type Item<'a>: 'a;

tests/ui/nll/closure-requirements/type-test-subject-non-trivial-region.stderr

-12
This file was deleted.

0 commit comments

Comments
 (0)