Skip to content

Commit ae6838d

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 c75a4f3 commit ae6838d

File tree

3 files changed

+169
-92
lines changed

3 files changed

+169
-92
lines changed

src/librustc/middle/free_region.rs

+35-14
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.relation.contains(&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,
@@ -161,7 +161,7 @@ impl<'tcx> FreeRegionMap<'tcx> {
161161
// Record that `'sup:'sub`. Or, put another way, `'sub <= 'sup`.
162162
// (with the exception that `'static: 'x` is not notable)
163163
pub fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) {
164-
if (is_free(sub) || *sub == ty::ReStatic) && is_free(sup) {
164+
if is_free_or_static(sub) && is_free(sup) {
165165
self.relation.add(sub, sup)
166166
}
167167
}
@@ -183,6 +183,20 @@ impl<'tcx> FreeRegionMap<'tcx> {
183183
result
184184
}
185185

186+
/// Tests whether `sub <= sup`. Both must be free regions or
187+
/// `'static`.
188+
pub fn sub_free_regions<'a, 'gcx>(&self,
189+
sub: Region<'tcx>,
190+
sup: Region<'tcx>)
191+
-> bool {
192+
assert!(is_free_or_static(sub) && is_free_or_static(sup));
193+
if let ty::ReStatic = sup {
194+
true // `'a <= 'static` is just always true, and not stored in the relation explicitly
195+
} else {
196+
self.relation.contains(&sub, &sup)
197+
}
198+
}
199+
186200
/// Returns all regions that are known to outlive `r_a`. For
187201
/// example, in a function:
188202
///
@@ -204,6 +218,13 @@ fn is_free(r: Region) -> bool {
204218
}
205219
}
206220

221+
fn is_free_or_static(r: Region) -> bool {
222+
match *r {
223+
ty::ReStatic => true,
224+
_ => is_free(r),
225+
}
226+
}
227+
207228
impl_stable_hash_for!(struct FreeRegionMap<'tcx> {
208229
relation
209230
});

0 commit comments

Comments
 (0)