Skip to content

Commit a96b0cf

Browse files
committed
replace constant regions with a post-inference check
Rather than declaring some region variables to be constant, and reporting errors when they would have to change, we instead populate each free region X with a minimal set of points (the CFG plus end(X)), and then we let inference do its thing. This may add other `end(Y)` points into X; we can then check after the fact that indeed `X: Y` holds. This requires a bit of "blame" detection to find where the bad constraint came from: we are currently using a pretty dumb algorithm. Good place for later expansion.
1 parent 932452e commit a96b0cf

File tree

3 files changed

+163
-100
lines changed

3 files changed

+163
-100
lines changed

src/librustc/middle/free_region.rs

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -63,28 +63,28 @@ impl<'a, 'gcx, 'tcx> RegionRelations<'a, 'gcx, 'tcx> {
6363
-> bool {
6464
let result = sub_region == super_region || {
6565
match (sub_region, super_region) {
66-
(&ty::ReEmpty, _) |
67-
(_, &ty::ReStatic) =>
66+
(ty::ReEmpty, _) |
67+
(_, ty::ReStatic) =>
6868
true,
6969

70-
(&ty::ReScope(sub_scope), &ty::ReScope(super_scope)) =>
71-
self.region_scope_tree.is_subscope_of(sub_scope, super_scope),
70+
(ty::ReScope(sub_scope), ty::ReScope(super_scope)) =>
71+
self.region_scope_tree.is_subscope_of(*sub_scope, *super_scope),
7272

73-
(&ty::ReScope(sub_scope), &ty::ReEarlyBound(ref br)) => {
73+
(ty::ReScope(sub_scope), ty::ReEarlyBound(ref br)) => {
7474
let fr_scope = self.region_scope_tree.early_free_scope(self.tcx, br);
75-
self.region_scope_tree.is_subscope_of(sub_scope, fr_scope)
75+
self.region_scope_tree.is_subscope_of(*sub_scope, fr_scope)
7676
}
7777

78-
(&ty::ReScope(sub_scope), &ty::ReFree(ref fr)) => {
78+
(ty::ReScope(sub_scope), ty::ReFree(fr)) => {
7979
let fr_scope = self.region_scope_tree.free_scope(self.tcx, fr);
80-
self.region_scope_tree.is_subscope_of(sub_scope, fr_scope)
80+
self.region_scope_tree.is_subscope_of(*sub_scope, fr_scope)
8181
}
8282

83-
(&ty::ReEarlyBound(_), &ty::ReEarlyBound(_)) |
84-
(&ty::ReFree(_), &ty::ReEarlyBound(_)) |
85-
(&ty::ReEarlyBound(_), &ty::ReFree(_)) |
86-
(&ty::ReFree(_), &ty::ReFree(_)) =>
87-
self.free_regions.sub_free_regions(&sub_region, &super_region),
83+
(ty::ReEarlyBound(_), ty::ReEarlyBound(_)) |
84+
(ty::ReFree(_), ty::ReEarlyBound(_)) |
85+
(ty::ReEarlyBound(_), ty::ReFree(_)) |
86+
(ty::ReFree(_), ty::ReFree(_)) =>
87+
self.free_regions.sub_free_regions(sub_region, super_region),
8888

8989
_ =>
9090
false,
@@ -162,23 +162,23 @@ impl<'tcx> FreeRegionMap<'tcx> {
162162
/// (with the exception that `'static: 'x` is not notable)
163163
pub fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) {
164164
debug!("relate_regions(sub={:?}, sup={:?})", sub, sup);
165-
if (is_free(sub) || *sub == ty::ReStatic) && is_free(sup) {
165+
if is_free_or_static(sub) && is_free(sup) {
166166
self.relation.add(sub, sup)
167167
}
168168
}
169169

170-
/// True if `r_a <= r_b` is known to hold. Both `r_a` and `r_b`
171-
/// must be free regions from the function header.
170+
/// Tests whether `r_a <= sup`. Both must be free regions or
171+
/// `'static`.
172172
pub fn sub_free_regions<'a, 'gcx>(&self,
173173
r_a: Region<'tcx>,
174174
r_b: Region<'tcx>)
175175
-> bool {
176-
debug!("sub_free_regions(r_a={:?}, r_b={:?})", r_a, r_b);
177-
assert!(is_free(r_a));
178-
assert!(is_free(r_b));
179-
let result = r_a == r_b || self.relation.contains(&r_a, &r_b);
180-
debug!("sub_free_regions: result={}", result);
181-
result
176+
assert!(is_free_or_static(r_a) && is_free_or_static(r_b));
177+
if let ty::ReStatic = r_b {
178+
true // `'a <= 'static` is just always true, and not stored in the relation explicitly
179+
} else {
180+
r_a == r_b || self.relation.contains(&r_a, &r_b)
181+
}
182182
}
183183

184184
/// Compute the least-upper-bound of two free regions. In some
@@ -224,6 +224,13 @@ fn is_free(r: Region) -> bool {
224224
}
225225
}
226226

227+
fn is_free_or_static(r: Region) -> bool {
228+
match *r {
229+
ty::ReStatic => true,
230+
_ => is_free(r),
231+
}
232+
}
233+
227234
impl_stable_hash_for!(struct FreeRegionMap<'tcx> {
228235
relation
229236
});

0 commit comments

Comments
 (0)