]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/middle/resolve_lifetime.rs
Auto merge of #30341 - pnkfelix:call-site-scope, r=nikomatsakis
[rust.git] / src / librustc / middle / resolve_lifetime.rs
index fa0c6c41ce5ccae18d2141e26394f72003d584cd..89fa76f2fa769d5b9f181fc44b1bd0ba0324abe9 100644 (file)
@@ -32,7 +32,7 @@
 
 use rustc_front::hir;
 use rustc_front::print::pprust::lifetime_to_string;
-use rustc_front::visit::{self, Visitor, FnKind};
+use rustc_front::intravisit::{self, Visitor, FnKind};
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
 pub enum DefRegion {
@@ -42,7 +42,7 @@ pub enum DefRegion {
                         /* lifetime decl */ ast::NodeId),
     DefLateBoundRegion(ty::DebruijnIndex,
                        /* lifetime decl */ ast::NodeId),
-    DefFreeRegion(/* block scope */ region::DestructionScopeData,
+    DefFreeRegion(region::CallSiteScopeData,
                   /* lifetime decl */ ast::NodeId),
 }
 
@@ -83,9 +83,9 @@ enum ScopeChain<'a> {
     /// LateScope(['a, 'b, ...], s) extends s with late-bound
     /// lifetimes introduced by the declaration binder_id.
     LateScope(&'a Vec<hir::LifetimeDef>, Scope<'a>),
-    /// lifetimes introduced by items within a code block are scoped
-    /// to that block.
-    BlockScope(region::DestructionScopeData, Scope<'a>),
+
+    /// lifetimes introduced by a fn are scoped to the call-site for that fn.
+    FnScope { fn_id: ast::NodeId, body_id: ast::NodeId, s: Scope<'a> },
     RootScope
 }
 
@@ -95,30 +95,29 @@ enum ScopeChain<'a> {
 
 pub fn krate(sess: &Session, krate: &hir::Crate, def_map: &DefMap) -> NamedRegionMap {
     let mut named_region_map = NodeMap();
-    visit::walk_crate(&mut LifetimeContext {
-        sess: sess,
-        named_region_map: &mut named_region_map,
-        scope: &ROOT_SCOPE,
-        def_map: def_map,
-        trait_ref_hack: false,
-        labels_in_fn: vec![],
-    }, krate);
-    sess.abort_if_errors();
+    sess.abort_if_new_errors(|| {
+        krate.visit_all_items(&mut LifetimeContext {
+            sess: sess,
+            named_region_map: &mut named_region_map,
+            scope: &ROOT_SCOPE,
+            def_map: def_map,
+            trait_ref_hack: false,
+            labels_in_fn: vec![],
+        });
+    });
     named_region_map
 }
 
 impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
     fn visit_item(&mut self, item: &hir::Item) {
-        // Items save/restore the set of labels. This way inner items
-        // can freely reuse names, be they loop labels or lifetimes.
-        let saved = replace(&mut self.labels_in_fn, vec![]);
+        assert!(self.labels_in_fn.is_empty());
 
         // Items always introduce a new root scope
         self.with(RootScope, |_, this| {
             match item.node {
                 hir::ItemFn(..) => {
                     // Fn lifetimes get added in visit_fn below:
-                    visit::walk_item(this, item);
+                    intravisit::walk_item(this, item);
                 }
                 hir::ItemExternCrate(_) |
                 hir::ItemUse(_) |
@@ -128,7 +127,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                 hir::ItemStatic(..) |
                 hir::ItemConst(..) => {
                     // These sorts of items have no lifetime parameters at all.
-                    visit::walk_item(this, item);
+                    intravisit::walk_item(this, item);
                 }
                 hir::ItemTy(_, ref generics) |
                 hir::ItemEnum(_, ref generics) |
@@ -140,14 +139,14 @@ fn visit_item(&mut self, item: &hir::Item) {
                     let early_scope = EarlyScope(subst::TypeSpace, lifetimes, &ROOT_SCOPE);
                     this.with(early_scope, |old_scope, this| {
                         this.check_lifetime_defs(old_scope, lifetimes);
-                        visit::walk_item(this, item);
+                        intravisit::walk_item(this, item);
                     });
                 }
             }
         });
 
-        // Done traversing the item; restore saved set of labels.
-        replace(&mut self.labels_in_fn, saved);
+        // Done traversing the item; remove any labels it created
+        self.labels_in_fn.truncate(0);
     }
 
     fn visit_foreign_item(&mut self, item: &hir::ForeignItem) {
@@ -160,11 +159,11 @@ fn visit_foreign_item(&mut self, item: &hir::ForeignItem) {
             match item.node {
                 hir::ForeignItemFn(_, ref generics) => {
                     this.visit_early_late(subst::FnSpace, generics, |this| {
-                        visit::walk_foreign_item(this, item);
+                        intravisit::walk_foreign_item(this, item);
                     })
                 }
                 hir::ForeignItemStatic(..) => {
-                    visit::walk_foreign_item(this, item);
+                    intravisit::walk_foreign_item(this, item);
                 }
             }
         });
@@ -174,20 +173,20 @@ fn visit_foreign_item(&mut self, item: &hir::ForeignItem) {
     }
 
     fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
-                b: &'v hir::Block, s: Span, _: ast::NodeId) {
+                b: &'v hir::Block, s: Span, fn_id: ast::NodeId) {
         match fk {
             FnKind::ItemFn(_, generics, _, _, _, _) => {
                 self.visit_early_late(subst::FnSpace, generics, |this| {
-                    this.walk_fn(fk, fd, b, s)
+                    this.add_scope_and_walk_fn(fk, fd, b, s, fn_id)
                 })
             }
             FnKind::Method(_, sig, _) => {
                 self.visit_early_late(subst::FnSpace, &sig.generics, |this| {
-                    this.walk_fn(fk, fd, b, s)
+                    this.add_scope_and_walk_fn(fk, fd, b, s, fn_id)
                 })
             }
-            FnKind::Closure(..) => {
-                self.walk_fn(fk, fd, b, s)
+            FnKind::Closure => {
+                self.add_scope_and_walk_fn(fk, fd, b, s, fn_id)
             }
         }
     }
@@ -199,7 +198,7 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
                     // a bare fn has no bounds, so everything
                     // contained within is scoped within its binder.
                     this.check_lifetime_defs(old_scope, &c.lifetimes);
-                    visit::walk_ty(this, ty);
+                    intravisit::walk_ty(this, ty);
                 });
             }
             hir::TyPath(None, ref path) => {
@@ -212,12 +211,12 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
                         });
                     }
                     _ => {
-                        visit::walk_ty(self, ty);
+                        intravisit::walk_ty(self, ty);
                     }
                 }
             }
             _ => {
-                visit::walk_ty(self, ty)
+                intravisit::walk_ty(self, ty)
             }
         }
     }
@@ -230,20 +229,14 @@ fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
         if let hir::MethodTraitItem(ref sig, None) = trait_item.node {
             self.visit_early_late(
                 subst::FnSpace, &sig.generics,
-                |this| visit::walk_trait_item(this, trait_item))
+                |this| intravisit::walk_trait_item(this, trait_item))
         } else {
-            visit::walk_trait_item(self, trait_item);
+            intravisit::walk_trait_item(self, trait_item);
         }
 
         replace(&mut self.labels_in_fn, saved);
     }
 
-    fn visit_block(&mut self, b: &hir::Block) {
-        self.with(BlockScope(region::DestructionScopeData::new(b.id),
-                             self.scope),
-                  |_, this| visit::walk_block(this, b));
-    }
-
     fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) {
         if lifetime_ref.name == special_idents::static_lifetime.name {
             self.insert_lifetime(lifetime_ref, DefStaticRegion);
@@ -317,7 +310,7 @@ fn visit_poly_trait_ref(&mut self,
                 for lifetime in &trait_ref.bound_lifetimes {
                     this.visit_lifetime_def(lifetime);
                 }
-                visit::walk_path(this, &trait_ref.trait_ref.path)
+                intravisit::walk_path(this, &trait_ref.trait_ref.path)
             })
         } else {
             self.visit_trait_ref(&trait_ref.trait_ref)
@@ -417,7 +410,7 @@ fn visit_expr(&mut self, ex: &'v hir::Expr) {
 
                 self.labels_in_fn.push((label, ex.span));
             }
-            visit::walk_expr(self, ex)
+            intravisit::walk_expr(self, ex)
         }
 
         fn visit_item(&mut self, _: &hir::Item) {
@@ -428,7 +421,7 @@ fn visit_item(&mut self, _: &hir::Item) {
     fn expression_label(ex: &hir::Expr) -> Option<ast::Name> {
         match ex.node {
             hir::ExprWhile(_, _, Some(label)) |
-            hir::ExprLoop(_, Some(label)) => Some(label.name),
+            hir::ExprLoop(_, Some(label)) => Some(label.unhygienic_name),
             _ => None,
         }
     }
@@ -439,7 +432,7 @@ fn check_if_label_shadows_lifetime<'a>(sess: &'a Session,
                                            label_span: Span) {
         loop {
             match *scope {
-                BlockScope(_, s) => { scope = s; }
+                FnScope { s, .. } => { scope = s; }
                 RootScope => { return; }
 
                 EarlyScope(_, lifetimes, s) |
@@ -463,26 +456,25 @@ fn check_if_label_shadows_lifetime<'a>(sess: &'a Session,
 }
 
 impl<'a> LifetimeContext<'a> {
-    // This is just like visit::walk_fn, except that it extracts the
-    // labels of the function body and swaps them in before visiting
-    // the function body itself.
-    fn walk_fn<'b>(&mut self,
-                   fk: FnKind,
-                   fd: &hir::FnDecl,
-                   fb: &'b hir::Block,
-                   _span: Span) {
+    fn add_scope_and_walk_fn<'b>(&mut self,
+                                 fk: FnKind,
+                                 fd: &hir::FnDecl,
+                                 fb: &'b hir::Block,
+                                 _span: Span,
+                                 fn_id: ast::NodeId) {
+
         match fk {
             FnKind::ItemFn(_, generics, _, _, _, _) => {
-                visit::walk_fn_decl(self, fd);
+                intravisit::walk_fn_decl(self, fd);
                 self.visit_generics(generics);
             }
             FnKind::Method(_, sig, _) => {
-                visit::walk_fn_decl(self, fd);
+                intravisit::walk_fn_decl(self, fd);
                 self.visit_generics(&sig.generics);
                 self.visit_explicit_self(&sig.explicit_self);
             }
-            FnKind::Closure(..) => {
-                visit::walk_fn_decl(self, fd);
+            FnKind::Closure => {
+                intravisit::walk_fn_decl(self, fd);
             }
         }
 
@@ -490,7 +482,8 @@ fn walk_fn<'b>(&mut self,
         // `self.labels_in_fn`.
         extract_labels(self, fb);
 
-        self.visit_block(fb);
+        self.with(FnScope { fn_id: fn_id, body_id: fb.id, s: self.scope },
+                  |_old_scope, this| this.visit_block(fb))
     }
 
     fn with<F>(&mut self, wrap_scope: ScopeChain, f: F) where
@@ -561,8 +554,11 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) {
         let mut scope = self.scope;
         loop {
             match *scope {
-                BlockScope(blk_scope, s) => {
-                    return self.resolve_free_lifetime_ref(blk_scope, lifetime_ref, s);
+                FnScope {fn_id, body_id, s } => {
+                    return self.resolve_free_lifetime_ref(
+                        region::CallSiteScopeData { fn_id: fn_id, body_id: body_id },
+                        lifetime_ref,
+                        s);
                 }
 
                 RootScope => {
@@ -606,7 +602,7 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) {
     }
 
     fn resolve_free_lifetime_ref(&mut self,
-                                 scope_data: region::DestructionScopeData,
+                                 scope_data: region::CallSiteScopeData,
                                  lifetime_ref: &hir::Lifetime,
                                  scope: Scope) {
         debug!("resolve_free_lifetime_ref \
@@ -624,8 +620,10 @@ fn resolve_free_lifetime_ref(&mut self,
                     scope_data: {:?} scope: {:?} search_result: {:?}",
                    scope_data, scope, search_result);
             match *scope {
-                BlockScope(blk_scope_data, s) => {
-                    scope_data = blk_scope_data;
+                FnScope { fn_id, body_id, s } => {
+                    scope_data = region::CallSiteScopeData {
+                        fn_id: fn_id, body_id: body_id
+                    };
                     scope = s;
                 }
 
@@ -713,7 +711,7 @@ fn check_lifetime_def_for_shadowing(&self,
 
         loop {
             match *old_scope {
-                BlockScope(_, s) => {
+                FnScope { s, .. } => {
                     old_scope = s;
                 }
 
@@ -866,7 +864,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             EarlyScope(space, defs, _) => write!(fmt, "EarlyScope({:?}, {:?})", space, defs),
             LateScope(defs, _) => write!(fmt, "LateScope({:?})", defs),
-            BlockScope(id, _) => write!(fmt, "BlockScope({:?})", id),
+            FnScope { fn_id, body_id, s: _ } => write!(fmt, "FnScope({:?}, {:?})", fn_id, body_id),
             RootScope => write!(fmt, "RootScope"),
         }
     }