about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2014-06-20 22:26:14 +0200
committerFelix S. Klock II <pnkfelix@pnkfx.org>2014-06-22 06:19:56 +0200
commit36caa7a729a72df100d760e80bed84149ff4cab1 (patch)
tree0393a57db6accbd325c99fa76e6feb6a1266ba8f
parent43d193826000d22d0c2b5969f7b9b603f406f60f (diff)
downloadrust-36caa7a729a72df100d760e80bed84149ff4cab1.tar.gz
rust-36caa7a729a72df100d760e80bed84149ff4cab1.zip
RegionFolder should only invoke callback on free regions.
In other words, Late-bound regions that occur non-free should be
skipped.

Fix #10846.
-rw-r--r--src/librustc/middle/ty_fold.rs56
1 files changed, 51 insertions, 5 deletions
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index 2488d2da779..c90d9af9b78 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -15,6 +15,7 @@ use middle::subst::VecPerParamSpace;
 use middle::ty;
 use middle::typeck;
 use std::rc::Rc;
+use syntax::ast;
 use syntax::owned_slice::OwnedSlice;
 use util::ppaux::Repr;
 
@@ -449,10 +450,23 @@ impl<'a> TypeFolder for BottomUpFolder<'a> {
 ///////////////////////////////////////////////////////////////////////////
 // Region folder
 
+/// Folds over the substructure of a type, visiting its component
+/// types and all regions that occur *free* within it.
+///
+/// That is, `ty::t` can contain function or method types that bind
+/// regions at the call site (`ReLateBound`), and occurrences of
+/// regions (aka "lifetimes") that are bound within a type are not
+/// visited by this folder; only regions that occur free will be
+/// visited by `fld_r`.
+///
+/// (The distinction between "free" and "bound" is represented by
+/// keeping track of each `FnSig` in the lexical context of the
+/// current position of the fold.)
 pub struct RegionFolder<'a> {
     tcx: &'a ty::ctxt,
     fld_t: |ty::t|: 'a -> ty::t,
     fld_r: |ty::Region|: 'a -> ty::Region,
+    within_binder_ids: Vec<ast::NodeId>,
 }
 
 impl<'a> RegionFolder<'a> {
@@ -463,7 +477,8 @@ impl<'a> RegionFolder<'a> {
         RegionFolder {
             tcx: tcx,
             fld_t: fld_t,
-            fld_r: fld_r
+            fld_r: fld_r,
+            within_binder_ids: vec![],
         }
     }
 
@@ -474,22 +489,53 @@ impl<'a> RegionFolder<'a> {
         RegionFolder {
             tcx: tcx,
             fld_t: noop,
-            fld_r: fld_r
+            fld_r: fld_r,
+            within_binder_ids: vec![],
         }
     }
 }
 
+/// If `ty` has `FnSig` (i.e. closure or fn), return its binder_id;
+/// else None.
+fn opt_binder_id_of_function(t: ty::t) -> Option<ast::NodeId> {
+    match ty::get(t).sty {
+        ty::ty_closure(ref f) => Some(f.sig.binder_id),
+        ty::ty_bare_fn(ref f) => Some(f.sig.binder_id),
+        _                     => None,
+    }
+}
+
 impl<'a> TypeFolder for RegionFolder<'a> {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.tcx }
 
     fn fold_ty(&mut self, ty: ty::t) -> ty::t {
         debug!("RegionFolder.fold_ty({})", ty.repr(self.tcx()));
+        let opt_binder_id = opt_binder_id_of_function(ty);
+        match opt_binder_id {
+            Some(binder_id) => self.within_binder_ids.push(binder_id),
+            None => {}
+        }
+
         let t1 = super_fold_ty(self, ty);
-        (self.fld_t)(t1)
+        let ret = (self.fld_t)(t1);
+
+        if opt_binder_id.is_some() {
+            self.within_binder_ids.pop();
+        }
+
+        ret
     }
 
     fn fold_region(&mut self, r: ty::Region) -> ty::Region {
-        debug!("RegionFolder.fold_region({})", r.repr(self.tcx()));
-        (self.fld_r)(r)
+        match r {
+            ty::ReLateBound(binder_id, _) if self.within_binder_ids.contains(&binder_id) => {
+                debug!("RegionFolder.fold_region({}) skipped bound region", r.repr(self.tcx()));
+                r
+            }
+            _ => {
+                debug!("RegionFolder.fold_region({}) folding free region", r.repr(self.tcx()));
+                (self.fld_r)(r)
+            }
+        }
     }
 }