]> git.lizzy.rs Git - rust.git/commitdiff
Refactored new CodeExtent type for improved abstraction.
authorFelix S. Klock II <pnkfelix@pnkfx.org>
Tue, 18 Nov 2014 13:22:59 +0000 (14:22 +0100)
committerFelix S. Klock II <pnkfelix@pnkfx.org>
Thu, 20 Nov 2014 12:10:03 +0000 (13:10 +0100)
(Previously, statically identifiable scopes/regions were solely
identified with NodeId's; this refactoring prepares for a future
where that 1:1 correspondence does not hold.)

25 files changed:
src/librustc/metadata/tydecode.rs
src/librustc/metadata/tyencode.rs
src/librustc/middle/astencode.rs
src/librustc/middle/borrowck/check_loans.rs
src/librustc/middle/borrowck/gather_loans/lifetime.rs
src/librustc/middle/borrowck/gather_loans/mod.rs
src/librustc/middle/borrowck/mod.rs
src/librustc/middle/borrowck/move_data.rs
src/librustc/middle/cfg/construct.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/region.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/ty.rs
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/check/regionck.rs
src/librustc/middle/typeck/check/wf.rs
src/librustc/middle/typeck/collect.rs
src/librustc/middle/typeck/infer/error_reporting.rs
src/librustc/middle/typeck/infer/region_inference/mod.rs
src/librustc/util/ppaux.rs
src/librustc_trans/test.rs
src/librustc_trans/trans/cleanup.rs
src/librustc_trans/trans/common.rs

index 34b57c5b437ed3e26bdbcb60d905683cd39464f9..00d12ad6a382db814994f847996be223336d20bc 100644 (file)
@@ -18,6 +18,7 @@
 
 pub use self::DefIdSource::*;
 
+use middle::region;
 use middle::subst;
 use middle::subst::VecPerParamSpace;
 use middle::ty::{mod, Ty};
@@ -315,17 +316,17 @@ fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region {
       }
       'f' => {
         assert_eq!(next(st), '[');
-        let id = parse_uint(st) as ast::NodeId;
+        let scope = parse_scope(st);
         assert_eq!(next(st), '|');
         let br = parse_bound_region(st, |x,y| conv(x,y));
         assert_eq!(next(st), ']');
-        ty::ReFree(ty::FreeRegion {scope_id: id,
+        ty::ReFree(ty::FreeRegion { scope: scope,
                                     bound_region: br})
       }
       's' => {
-        let id = parse_uint(st) as ast::NodeId;
+        let scope = parse_scope(st);
         assert_eq!(next(st), '|');
-        ty::ReScope(id)
+        ty::ReScope(scope)
       }
       't' => {
         ty::ReStatic
@@ -337,6 +338,16 @@ fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region {
     }
 }
 
+fn parse_scope(st: &mut PState) -> region::CodeExtent {
+    match next(st) {
+        'M' => {
+            let node_id = parse_uint(st) as ast::NodeId;
+            region::CodeExtent::Misc(node_id)
+        }
+        _ => panic!("parse_scope: bad input")
+    }
+}
+
 fn parse_opt<'a, 'tcx, T>(st: &mut PState<'a, 'tcx>, f: |&mut PState<'a, 'tcx>| -> T)
                           -> Option<T> {
     match next(st) {
index ea778d07e1c9d2b75b07258640ec1a0ddc7c8572..bbb2faaae0691619eb283587f7771df97e735c42 100644 (file)
@@ -15,6 +15,7 @@
 
 use std::cell::RefCell;
 
+use middle::region;
 use middle::subst;
 use middle::subst::VecPerParamSpace;
 use middle::ty::ParamTy;
@@ -143,12 +144,16 @@ pub fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) {
                      token::get_name(name));
         }
         ty::ReFree(ref fr) => {
-            mywrite!(w, "f[{}|", fr.scope_id);
+            mywrite!(w, "f[");
+            enc_scope(w, cx, fr.scope);
+            mywrite!(w, "|");
             enc_bound_region(w, cx, fr.bound_region);
             mywrite!(w, "]");
         }
-        ty::ReScope(nid) => {
-            mywrite!(w, "s{}|", nid);
+        ty::ReScope(scope) => {
+            mywrite!(w, "s");
+            enc_scope(w, cx, scope);
+            mywrite!(w, "|");
         }
         ty::ReStatic => {
             mywrite!(w, "t");
@@ -163,6 +168,12 @@ pub fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) {
     }
 }
 
+fn enc_scope(w: &mut SeekableMemWriter, _cx: &ctxt, scope: region::CodeExtent) {
+    match scope {
+        region::CodeExtent::Misc(node_id) => mywrite!(w, "M{}", node_id)
+    }
+}
+
 fn enc_bound_region(w: &mut SeekableMemWriter, cx: &ctxt, br: ty::BoundRegion) {
     match br {
         ty::BrAnon(idx) => {
index 3cebb7236b64001e2d80c80e5b65f426c99db9df..7986a526b23b16188b9af78a43ff8ddce5851a6b 100644 (file)
@@ -489,20 +489,32 @@ fn tr(&self, dcx: &DecodeContext) -> ty::Region {
             ty::ReEarlyBound(id, space, index, ident) => {
                 ty::ReEarlyBound(dcx.tr_id(id), space, index, ident)
             }
-            ty::ReScope(id) => {
-                ty::ReScope(dcx.tr_id(id))
+            ty::ReScope(scope) => {
+                ty::ReScope(scope.tr(dcx))
             }
             ty::ReEmpty | ty::ReStatic | ty::ReInfer(..) => {
                 *self
             }
             ty::ReFree(ref fr) => {
-                ty::ReFree(ty::FreeRegion {scope_id: dcx.tr_id(fr.scope_id),
-                                            bound_region: fr.bound_region.tr(dcx)})
+                ty::ReFree(fr.tr(dcx))
             }
         }
     }
 }
 
+impl tr for ty::FreeRegion {
+    fn tr(&self, dcx: &DecodeContext) -> ty::FreeRegion {
+        ty::FreeRegion { scope: self.scope.tr(dcx),
+                         bound_region: self.bound_region.tr(dcx) }
+    }
+}
+
+impl tr for region::CodeExtent {
+    fn tr(&self, dcx: &DecodeContext) -> region::CodeExtent {
+        self.map_id(|id| dcx.tr_id(id))
+    }
+}
+
 impl tr for ty::BoundRegion {
     fn tr(&self, dcx: &DecodeContext) -> ty::BoundRegion {
         match *self {
index d91d666511dd5fe40fe82cd49d44cbf17b881f7a..238a4ca7bd69eb4798217ac2de5cc57eb7c6ccc0 100644 (file)
@@ -21,6 +21,7 @@
 use middle::borrowck::*;
 use middle::expr_use_visitor as euv;
 use middle::mem_categorization as mc;
+use middle::region;
 use middle::ty;
 use syntax::ast;
 use syntax::codemap::Span;
@@ -134,7 +135,7 @@ fn borrow(&mut self,
             None => { }
         }
 
-        self.check_for_conflicting_loans(borrow_id);
+        self.check_for_conflicting_loans(region::CodeExtent::from_node_id(borrow_id));
     }
 
     fn mutate(&mut self,
@@ -215,30 +216,30 @@ fn compatible_borrow_kinds(borrow_kind1: ty::BorrowKind,
 impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
     pub fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.bccx.tcx }
 
-    pub fn each_issued_loan(&self, scope_id: ast::NodeId, op: |&Loan| -> bool)
+    pub fn each_issued_loan(&self, scope: region::CodeExtent, op: |&Loan| -> bool)
                             -> bool {
         //! Iterates over each loan that has been issued
-        //! on entrance to `scope_id`, regardless of whether it is
+        //! on entrance to `scope`, regardless of whether it is
         //! actually *in scope* at that point.  Sometimes loans
         //! are issued for future scopes and thus they may have been
         //! *issued* but not yet be in effect.
 
-        self.dfcx_loans.each_bit_on_entry(scope_id, |loan_index| {
+        self.dfcx_loans.each_bit_on_entry(scope.node_id(), |loan_index| {
             let loan = &self.all_loans[loan_index];
             op(loan)
         })
     }
 
     pub fn each_in_scope_loan(&self,
-                              scope_id: ast::NodeId,
+                              scope: region::CodeExtent,
                               op: |&Loan| -> bool)
                               -> bool {
         //! Like `each_issued_loan()`, but only considers loans that are
         //! currently in scope.
 
         let tcx = self.tcx();
-        self.each_issued_loan(scope_id, |loan| {
-            if tcx.region_maps.is_subscope_of(scope_id, loan.kill_scope) {
+        self.each_issued_loan(scope, |loan| {
+            if tcx.region_maps.is_subscope_of(scope, loan.kill_scope) {
                 op(loan)
             } else {
                 true
@@ -247,7 +248,7 @@ pub fn each_in_scope_loan(&self,
     }
 
     fn each_in_scope_loan_affecting_path(&self,
-                                         scope_id: ast::NodeId,
+                                         scope: region::CodeExtent,
                                          loan_path: &LoanPath,
                                          op: |&Loan| -> bool)
                                          -> bool {
@@ -262,7 +263,7 @@ fn each_in_scope_loan_affecting_path(&self,
         //     let y = a;          // Conflicts with restriction
 
         let loan_path = owned_ptr_base_path(loan_path);
-        let cont = self.each_in_scope_loan(scope_id, |loan| {
+        let cont = self.each_in_scope_loan(scope, |loan| {
             let mut ret = true;
             for restr_path in loan.restricted_paths.iter() {
                 if **restr_path == *loan_path {
@@ -302,7 +303,7 @@ fn each_in_scope_loan_affecting_path(&self,
                 }
             }
 
-            let cont = self.each_in_scope_loan(scope_id, |loan| {
+            let cont = self.each_in_scope_loan(scope, |loan| {
                 if *loan.loan_path == *loan_path {
                     op(loan)
                 } else {
@@ -318,30 +319,33 @@ fn each_in_scope_loan_affecting_path(&self,
         return true;
     }
 
-    pub fn loans_generated_by(&self, scope_id: ast::NodeId) -> Vec<uint> {
+    pub fn loans_generated_by(&self, scope: region::CodeExtent) -> Vec<uint> {
         //! Returns a vector of the loans that are generated as
-        //! we encounter `scope_id`.
+        //! we enter `scope`.
 
         let mut result = Vec::new();
-        self.dfcx_loans.each_gen_bit(scope_id, |loan_index| {
+        self.dfcx_loans.each_gen_bit(scope.node_id(), |loan_index| {
             result.push(loan_index);
             true
         });
         return result;
     }
 
-    pub fn check_for_conflicting_loans(&self, scope_id: ast::NodeId) {
+    pub fn check_for_conflicting_loans(&self, scope: region::CodeExtent) {
         //! Checks to see whether any of the loans that are issued
-        //! by `scope_id` conflict with loans that have already been
-        //! issued when we enter `scope_id` (for example, we do not
+        //! on entrance to `scope` conflict with loans that have already been
+        //! issued when we enter `scope` (for example, we do not
         //! permit two `&mut` borrows of the same variable).
+        //!
+        //! (Note that some loans can be *issued* without necessarily
+        //! taking effect yet.)
 
-        debug!("check_for_conflicting_loans(scope_id={})", scope_id);
+        debug!("check_for_conflicting_loans(scope={})", scope);
 
-        let new_loan_indices = self.loans_generated_by(scope_id);
+        let new_loan_indices = self.loans_generated_by(scope);
         debug!("new_loan_indices = {}", new_loan_indices);
 
-        self.each_issued_loan(scope_id, |issued_loan| {
+        self.each_issued_loan(scope, |issued_loan| {
             for &new_loan_index in new_loan_indices.iter() {
                 let new_loan = &self.all_loans[new_loan_index];
                 self.report_error_if_loans_conflict(issued_loan, new_loan);
@@ -535,7 +539,7 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
                 old_loan.span,
                 format!("{}; {}", borrow_summary, rule_summary).as_slice());
 
-            let old_loan_span = self.tcx().map.span(old_loan.kill_scope);
+            let old_loan_span = self.tcx().map.span(old_loan.kill_scope.node_id());
             self.bccx.span_end_note(old_loan_span,
                                     "previous borrow ends here");
 
@@ -657,7 +661,8 @@ pub fn analyze_restrictions_on_use(&self,
 
         let mut ret = UseOk;
 
-        self.each_in_scope_loan_affecting_path(expr_id, use_path, |loan| {
+        self.each_in_scope_loan_affecting_path(
+            region::CodeExtent::from_node_id(expr_id), use_path, |loan| {
             if !compatible_borrow_kinds(loan.kind, borrow_kind) {
                 ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span);
                 false
@@ -924,7 +929,8 @@ fn check_for_assignment_to_borrowed_path(
                 None => { return; /* no loan path, can't be any loans */ }
             };
 
-            this.each_in_scope_loan_affecting_path(assignment_id, &*loan_path, |loan| {
+            let scope = region::CodeExtent::from_node_id(assignment_id);
+            this.each_in_scope_loan_affecting_path(scope, &*loan_path, |loan| {
                 this.report_illegal_mutation(assignment_span, &*loan_path, loan);
                 false
             });
index 99795fb3009021720934c7caef47718835430df5..5b8cb0608b39ce0487a65542b3934bc1a7beeecf 100644 (file)
@@ -16,6 +16,7 @@
 use middle::borrowck::*;
 use middle::expr_use_visitor as euv;
 use middle::mem_categorization as mc;
+use middle::region;
 use middle::ty;
 use util::ppaux::Repr;
 use syntax::ast;
 type R = Result<(),()>;
 
 pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
-                                    item_scope_id: ast::NodeId,
+                                    item_scope: region::CodeExtent,
                                     span: Span,
                                     cause: euv::LoanCause,
                                     cmt: mc::cmt<'tcx>,
                                     loan_region: ty::Region,
                                     _: ty::BorrowKind)
                                     -> Result<(),()> {
+    //! Reports error if `loan_region` is larger than S
+    //! where S is `item_scope` if `cmt` is an upvar,
+    //! and is scope of `cmt` otherwise.
     debug!("guarantee_lifetime(cmt={}, loan_region={})",
            cmt.repr(bccx.tcx), loan_region.repr(bccx.tcx));
     let ctxt = GuaranteeLifetimeContext {bccx: bccx,
-                                         item_scope_id: item_scope_id,
+                                         item_scope: item_scope,
                                          span: span,
                                          cause: cause,
                                          loan_region: loan_region,
@@ -48,8 +52,8 @@ pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
 struct GuaranteeLifetimeContext<'a, 'tcx: 'a> {
     bccx: &'a BorrowckCtxt<'a, 'tcx>,
 
-    // the node id of the function body for the enclosing item
-    item_scope_id: ast::NodeId,
+    // the scope of the function body for the enclosing item
+    item_scope: region::CodeExtent,
 
     span: Span,
     cause: euv::LoanCause,
@@ -60,7 +64,9 @@ struct GuaranteeLifetimeContext<'a, 'tcx: 'a> {
 impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
 
     fn check(&self, cmt: &mc::cmt<'tcx>, discr_scope: Option<ast::NodeId>) -> R {
-        //! Main routine. Walks down `cmt` until we find the "guarantor".
+        //! Main routine. Walks down `cmt` until we find the
+        //! "guarantor".  Reports an error if `self.loan_region` is
+        //! larger than scope of `cmt`.
         debug!("guarantee_lifetime.check(cmt={}, loan_region={})",
                cmt.repr(self.bccx.tcx),
                self.loan_region.repr(self.bccx.tcx));
@@ -88,7 +94,7 @@ fn check(&self, cmt: &mc::cmt<'tcx>, discr_scope: Option<ast::NodeId>) -> R {
     }
 
     fn check_scope(&self, max_scope: ty::Region) -> R {
-        //! Reports an error if `loan_region` is larger than `valid_scope`
+        //! Reports an error if `loan_region` is larger than `max_scope`
 
         if !self.bccx.is_subregion_of(self.loan_region, max_scope) {
             Err(self.report_error(err_out_of_scope(max_scope, self.loan_region)))
@@ -109,7 +115,7 @@ fn scope(&self, cmt: &mc::cmt) -> ty::Region {
                 temp_scope
             }
             mc::cat_upvar(..) => {
-                ty::ReScope(self.item_scope_id)
+                ty::ReScope(self.item_scope)
             }
             mc::cat_static_item => {
                 ty::ReStatic
index 6bb511b2077c9659334036b271060ffa9c8a2bd6..c36a466919b456dd516dc064c41885a9695e1e74 100644 (file)
@@ -20,6 +20,7 @@
 use middle::borrowck::move_data::MoveData;
 use middle::expr_use_visitor as euv;
 use middle::mem_categorization as mc;
+use middle::region;
 use middle::ty;
 use util::ppaux::{Repr};
 
@@ -42,7 +43,7 @@ pub fn gather_loans_in_fn(bccx: &BorrowckCtxt,
     let mut glcx = GatherLoanCtxt {
         bccx: bccx,
         all_loans: Vec::new(),
-        item_ub: body.id,
+        item_ub: region::CodeExtent::from_node_id(body.id),
         move_data: MoveData::new(),
         move_error_collector: move_error::MoveErrorCollector::new(),
     };
@@ -62,7 +63,9 @@ struct GatherLoanCtxt<'a, 'tcx: 'a> {
     move_data: move_data::MoveData,
     move_error_collector: move_error::MoveErrorCollector<'tcx>,
     all_loans: Vec<Loan>,
-    item_ub: ast::NodeId,
+    /// `item_ub` is used as an upper-bound on the lifetime whenever we
+    /// ask for the scope of an expression categorized as an upvar.
+    item_ub: region::CodeExtent,
 }
 
 impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
@@ -266,8 +269,9 @@ fn guarantee_valid(&mut self,
 
             restrictions::SafeIf(loan_path, restricted_paths) => {
                 let loan_scope = match loan_region {
-                    ty::ReScope(id) => id,
-                    ty::ReFree(ref fr) => fr.scope_id,
+                    ty::ReScope(scope) => scope,
+
+                    ty::ReFree(ref fr) => fr.scope,
 
                     ty::ReStatic => {
                         // If we get here, an error must have been
@@ -293,7 +297,8 @@ fn guarantee_valid(&mut self,
                 };
                 debug!("loan_scope = {}", loan_scope);
 
-                let gen_scope = self.compute_gen_scope(borrow_id, loan_scope);
+                let borrow_scope = region::CodeExtent::from_node_id(borrow_id);
+                let gen_scope = self.compute_gen_scope(borrow_scope, loan_scope);
                 debug!("gen_scope = {}", gen_scope);
 
                 let kill_scope = self.compute_kill_scope(loan_scope, &*loan_path);
@@ -406,23 +411,23 @@ pub fn mark_loan_path_as_mutated(&self, loan_path: &LoanPath) {
     }
 
     pub fn compute_gen_scope(&self,
-                             borrow_id: ast::NodeId,
-                             loan_scope: ast::NodeId)
-                             -> ast::NodeId {
+                             borrow_scope: region::CodeExtent,
+                             loan_scope: region::CodeExtent)
+                             -> region::CodeExtent {
         //! Determine when to introduce the loan. Typically the loan
         //! is introduced at the point of the borrow, but in some cases,
         //! notably method arguments, the loan may be introduced only
         //! later, once it comes into scope.
 
-        if self.bccx.tcx.region_maps.is_subscope_of(borrow_id, loan_scope) {
-            borrow_id
+        if self.bccx.tcx.region_maps.is_subscope_of(borrow_scope, loan_scope) {
+            borrow_scope
         } else {
             loan_scope
         }
     }
 
-    pub fn compute_kill_scope(&self, loan_scope: ast::NodeId, lp: &LoanPath)
-                              -> ast::NodeId {
+    pub fn compute_kill_scope(&self, loan_scope: region::CodeExtent, lp: &LoanPath)
+                              -> region::CodeExtent {
         //! Determine when the loan restrictions go out of scope.
         //! This is either when the lifetime expires or when the
         //! local variable which roots the loan-path goes out of scope,
index 1ab9baa1ac401fabf2d60766f240bc78e4df033c..5271a6191418ac4139e86dcd4762c37617f91bd5 100644 (file)
@@ -24,6 +24,7 @@
 use middle::dataflow::DataFlowOperator;
 use middle::expr_use_visitor as euv;
 use middle::mem_categorization as mc;
+use middle::region;
 use middle::ty::{mod, Ty};
 use util::ppaux::{note_and_explain_region, Repr, UserString};
 
@@ -169,8 +170,8 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
                              id_range,
                              all_loans.len());
     for (loan_idx, loan) in all_loans.iter().enumerate() {
-        loan_dfcx.add_gen(loan.gen_scope, loan_idx);
-        loan_dfcx.add_kill(loan.kill_scope, loan_idx);
+        loan_dfcx.add_gen(loan.gen_scope.node_id(), loan_idx);
+        loan_dfcx.add_kill(loan.kill_scope.node_id(), loan_idx);
     }
     loan_dfcx.add_kills_from_flow_exits(cfg);
     loan_dfcx.propagate(cfg, body);
@@ -258,8 +259,19 @@ pub struct Loan {
     loan_path: Rc<LoanPath>,
     kind: ty::BorrowKind,
     restricted_paths: Vec<Rc<LoanPath>>,
-    gen_scope: ast::NodeId,
-    kill_scope: ast::NodeId,
+
+    /// gen_scope indicates where loan is introduced. Typically the
+    /// loan is introduced at the point of the borrow, but in some
+    /// cases, notably method arguments, the loan may be introduced
+    /// only later, once it comes into scope.  See also
+    /// `GatherLoanCtxt::compute_gen_scope`.
+    gen_scope: region::CodeExtent,
+
+    /// kill_scope indicates when the loan goes out of scope.  This is
+    /// either when the lifetime expires or when the local variable
+    /// which roots the loan-path goes out of scope, whichever happens
+    /// faster. See also `GatherLoanCtxt::compute_kill_scope`.
+    kill_scope: region::CodeExtent,
     span: Span,
     cause: euv::LoanCause,
 }
@@ -297,11 +309,13 @@ pub fn closure_to_block(closure_id: ast::NodeId,
 }
 
 impl LoanPath {
-    pub fn kill_scope(&self, tcx: &ty::ctxt) -> ast::NodeId {
+    pub fn kill_scope(&self, tcx: &ty::ctxt) -> region::CodeExtent {
         match *self {
             LpVar(local_id) => tcx.region_maps.var_scope(local_id),
-            LpUpvar(upvar_id) =>
-                closure_to_block(upvar_id.closure_expr_id, tcx),
+            LpUpvar(upvar_id) => {
+                let block_id = closure_to_block(upvar_id.closure_expr_id, tcx);
+                region::CodeExtent::from_node_id(block_id)
+            }
             LpExtend(ref base, _, _) => base.kill_scope(tcx),
         }
     }
@@ -901,8 +915,8 @@ pub fn cmt_to_string(&self, cmt: &mc::cmt_<'tcx>) -> String {
 
 fn is_statement_scope(tcx: &ty::ctxt, region: ty::Region) -> bool {
      match region {
-         ty::ReScope(node_id) => {
-             match tcx.map.find(node_id) {
+         ty::ReScope(scope) => {
+             match tcx.map.find(scope.node_id()) {
                  Some(ast_map::NodeStmt(_)) => true,
                  _ => false
              }
index b28d963371e851206ea072627b7ba7a0c35260cc..ab4c7787fe8fbc9bf4d2d4185a72202123c05447 100644 (file)
@@ -435,9 +435,9 @@ fn add_gen_kills(&self,
         for path in self.paths.borrow().iter() {
             match *path.loan_path {
                 LpVar(id) => {
-                    let kill_id = tcx.region_maps.var_scope(id);
+                    let kill_scope = tcx.region_maps.var_scope(id);
                     let path = (*self.path_map.borrow())[path.loan_path];
-                    self.kill_moves(path, kill_id, dfcx_moves);
+                    self.kill_moves(path, kill_scope.node_id(), dfcx_moves);
                 }
                 LpUpvar(ty::UpvarId { var_id: _, closure_expr_id }) => {
                     let kill_id = closure_to_block(closure_expr_id, tcx);
@@ -453,8 +453,8 @@ fn add_gen_kills(&self,
                 self.var_assignments.borrow().iter().enumerate() {
             match *self.path_loan_path(assignment.path) {
                 LpVar(id) => {
-                    let kill_id = tcx.region_maps.var_scope(id);
-                    dfcx_assign.add_kill(kill_id, assignment_index);
+                    let kill_scope = tcx.region_maps.var_scope(id);
+                    dfcx_assign.add_kill(kill_scope.node_id(), assignment_index);
                 }
                 LpUpvar(ty::UpvarId { var_id: _, closure_expr_id }) => {
                     let kill_id = closure_to_block(closure_expr_id, tcx);
index e84e70e2cd994c3fb1f2c5fa888be96b89d29914..b4557021b69fc57949b7f5817dbbbc1051652550 100644 (file)
@@ -11,6 +11,7 @@
 use middle::cfg::*;
 use middle::def;
 use middle::graph;
+use middle::region::CodeExtent;
 use middle::typeck;
 use middle::ty;
 use syntax::ast;
@@ -580,11 +581,12 @@ fn add_exiting_edge(&mut self,
                         to_loop: LoopScope,
                         to_index: CFGIndex) {
         let mut data = CFGEdgeData {exiting_scopes: vec!() };
-        let mut scope_id = from_expr.id;
-        while scope_id != to_loop.loop_id {
+        let mut scope = CodeExtent::from_node_id(from_expr.id);
+        let target_scope = CodeExtent::from_node_id(to_loop.loop_id);
+        while scope != target_scope {
 
-            data.exiting_scopes.push(scope_id);
-            scope_id = self.tcx.region_maps.encl_scope(scope_id);
+            data.exiting_scopes.push(scope.node_id());
+            scope = self.tcx.region_maps.encl_scope(scope);
         }
         self.graph.add_edge(from_index, to_index, data);
     }
index f4c22c571639001b2dd89b338202d6d9e49bef59..3215b5e8fe9af1bdba1387c408dc82f1d1898262 100644 (file)
@@ -23,6 +23,7 @@
 use middle::mem_categorization as mc;
 use middle::def;
 use middle::mem_categorization::Typer;
+use middle::region;
 use middle::pat_util;
 use middle::ty::{mod, Ty};
 use middle::typeck::{MethodCall, MethodObject, MethodTraitObject};
@@ -245,10 +246,11 @@ fn walk_arg_patterns(&mut self,
         for arg in decl.inputs.iter() {
             let arg_ty = return_if_err!(self.typer.node_ty(arg.pat.id));
 
+            let fn_body_scope = region::CodeExtent::from_node_id(body.id);
             let arg_cmt = self.mc.cat_rvalue(
                 arg.id,
                 arg.pat.span,
-                ty::ReScope(body.id), // Args live only as long as the fn body.
+                ty::ReScope(fn_body_scope), // Args live only as long as the fn body.
                 arg_ty);
 
             self.walk_pat(arg_cmt, &*arg.pat);
@@ -443,9 +445,10 @@ pub fn walk_expr(&mut self, expr: &ast::Expr) {
                 // Fetch the type of the value that the iteration yields to
                 // produce the pattern's categorized mutable type.
                 let pattern_type = return_if_err!(self.typer.node_ty(pat.id));
+                let blk_scope = region::CodeExtent::from_node_id(blk.id);
                 let pat_cmt = self.mc.cat_rvalue(pat.id,
                                                  pat.span,
-                                                 ty::ReScope(blk.id),
+                                                 ty::ReScope(blk_scope),
                                                  pattern_type);
                 self.walk_pat(pat_cmt, &**pat);
 
@@ -519,6 +522,7 @@ fn walk_callee(&mut self, call: &ast::Expr, callee: &ast::Expr) {
         let callee_ty = ty::expr_ty_adjusted(self.tcx(), callee);
         debug!("walk_callee: callee={} callee_ty={}",
                callee.repr(self.tcx()), callee_ty.repr(self.tcx()));
+        let call_scope = region::CodeExtent::from_node_id(call.id);
         match callee_ty.sty {
             ty::ty_bare_fn(..) => {
                 self.consume_expr(callee);
@@ -527,7 +531,7 @@ fn walk_callee(&mut self, call: &ast::Expr, callee: &ast::Expr) {
                 match f.onceness {
                     ast::Many => {
                         self.borrow_expr(callee,
-                                         ty::ReScope(call.id),
+                                         ty::ReScope(call_scope),
                                          ty::UniqueImmBorrow,
                                          ClosureInvocation);
                     }
@@ -557,13 +561,13 @@ fn walk_callee(&mut self, call: &ast::Expr, callee: &ast::Expr) {
                 match overloaded_call_type {
                     FnMutOverloadedCall => {
                         self.borrow_expr(callee,
-                                         ty::ReScope(call.id),
+                                         ty::ReScope(call_scope),
                                          ty::MutBorrow,
                                          ClosureInvocation);
                     }
                     FnOverloadedCall => {
                         self.borrow_expr(callee,
-                                         ty::ReScope(call.id),
+                                         ty::ReScope(call_scope),
                                          ty::ImmBorrow,
                                          ClosureInvocation);
                     }
@@ -814,7 +818,7 @@ fn walk_overloaded_operator(&mut self,
         // methods are implicitly autoref'd which sadly does not use
         // adjustments, so we must hardcode the borrow here.
 
-        let r = ty::ReScope(expr.id);
+        let r = ty::ReScope(region::CodeExtent::from_node_id(expr.id));
         let bk = ty::ImmBorrow;
 
         for &arg in rhs.iter() {
index 93c2e8f0d9933e9bc557a56eefec09737cf65d35..bb5af2f4297edc4eed5edb5dc82ec3bb252058ef 100644 (file)
@@ -74,6 +74,7 @@
 pub use self::categorization::*;
 
 use middle::def;
+use middle::region;
 use middle::ty::{mod, Ty};
 use middle::typeck;
 use util::nodemap::{DefIdMap, NodeMap};
@@ -289,7 +290,7 @@ pub trait Typer<'tcx> {
     fn node_method_ty(&self, method_call: typeck::MethodCall) -> Option<Ty<'tcx>>;
     fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>;
     fn is_method_call(&self, id: ast::NodeId) -> bool;
-    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId>;
+    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent>;
     fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow;
     fn capture_mode(&self, closure_expr_id: ast::NodeId)
                     -> ast::CaptureClause;
@@ -702,7 +703,7 @@ fn cat_upvar(&self,
 
             // Region of environment pointer
             let env_region = ty::ReFree(ty::FreeRegion {
-                scope_id: fn_body_id,
+                scope: region::CodeExtent::from_node_id(fn_body_id),
                 bound_region: ty::BrEnv
             });
 
index 0c0861eda3e7a997128152d8655cdbedc41f8328..8a50cb4ed4e1b41601d2bf557fde1c689483771b 100644 (file)
 use session::Session;
 use middle::ty::{FreeRegion};
 use middle::ty::{mod, Ty};
-use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
+use util::nodemap::{FnvHashMap, FnvHashSet, NodeMap};
 use util::common::can_reach;
 
 use std::cell::RefCell;
+use std::hash::{Hash};
 use syntax::codemap::Span;
 use syntax::{ast, visit};
 use syntax::ast::{Block, Item, FnDecl, NodeId, Arm, Pat, Stmt, Expr, Local};
 use syntax::ptr::P;
 use syntax::visit::{Visitor, FnKind};
 
+/// CodeExtent represents a statically-describable extent that can be
+/// used to bound the lifetime/region for values.
+///
+/// FIXME (pnkfelix): This currently derives `PartialOrd` and `Ord` to
+/// placate the same deriving in `ty::FreeRegion`, but we may want to
+/// actually attach a more meaningful ordering to scopes than the one
+/// generated via deriving here.
+#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Encodable, Decodable, Show)]
+pub enum CodeExtent {
+    Misc(ast::NodeId)
+}
+
+impl CodeExtent {
+    /// Creates a scope that represents the dynamic extent associated
+    /// with `node_id`.
+    pub fn from_node_id(node_id: ast::NodeId) -> CodeExtent {
+        CodeExtent::Misc(node_id)
+    }
+
+    /// Returns a node id associated with this scope.
+    ///
+    /// NB: likely to be replaced as API is refined; e.g. pnkfelix
+    /// anticipates `fn entry_node_id` and `fn each_exit_node_id`.
+    pub fn node_id(&self) -> ast::NodeId {
+        match *self {
+            CodeExtent::Misc(node_id) => node_id,
+        }
+    }
+
+    /// Maps this scope to a potentially new one according to the
+    /// NodeId transformer `f_id`.
+    pub fn map_id(&self, f_id: |ast::NodeId| -> ast::NodeId) -> CodeExtent {
+        match *self {
+            CodeExtent::Misc(node_id) => CodeExtent::Misc(f_id(node_id)),
+        }
+    }
+}
+
 /**
 The region maps encode information about region relationships.
 
   for dynamic checks and/or arbitrary amounts of stack space.
 */
 pub struct RegionMaps {
-    scope_map: RefCell<NodeMap<ast::NodeId>>,
-    var_map: RefCell<NodeMap<ast::NodeId>>,
+    scope_map: RefCell<FnvHashMap<CodeExtent, CodeExtent>>,
+    var_map: RefCell<NodeMap<CodeExtent>>,
     free_region_map: RefCell<FnvHashMap<FreeRegion, Vec<FreeRegion>>>,
-    rvalue_scopes: RefCell<NodeMap<ast::NodeId>>,
-    terminating_scopes: RefCell<NodeSet>,
+    rvalue_scopes: RefCell<NodeMap<CodeExtent>>,
+    terminating_scopes: RefCell<FnvHashSet<CodeExtent>>,
 }
 
 pub struct Context {
@@ -116,25 +155,25 @@ pub fn relate_free_regions(&self, sub: FreeRegion, sup: FreeRegion) {
         self.free_region_map.borrow_mut().insert(sub, vec!(sup));
     }
 
-    pub fn record_encl_scope(&self, sub: ast::NodeId, sup: ast::NodeId) {
+    pub fn record_encl_scope(&self, sub: CodeExtent, sup: CodeExtent) {
         debug!("record_encl_scope(sub={}, sup={})", sub, sup);
         assert!(sub != sup);
         self.scope_map.borrow_mut().insert(sub, sup);
     }
 
-    pub fn record_var_scope(&self, var: ast::NodeId, lifetime: ast::NodeId) {
+    pub fn record_var_scope(&self, var: ast::NodeId, lifetime: CodeExtent) {
         debug!("record_var_scope(sub={}, sup={})", var, lifetime);
-        assert!(var != lifetime);
+        assert!(var != lifetime.node_id());
         self.var_map.borrow_mut().insert(var, lifetime);
     }
 
-    pub fn record_rvalue_scope(&self, var: ast::NodeId, lifetime: ast::NodeId) {
+    pub fn record_rvalue_scope(&self, var: ast::NodeId, lifetime: CodeExtent) {
         debug!("record_rvalue_scope(sub={}, sup={})", var, lifetime);
-        assert!(var != lifetime);
+        assert!(var != lifetime.node_id());
         self.rvalue_scopes.borrow_mut().insert(var, lifetime);
     }
 
-    pub fn mark_as_terminating_scope(&self, scope_id: ast::NodeId) {
+    pub fn mark_as_terminating_scope(&self, scope_id: CodeExtent) {
         /*!
          * Records that a scope is a TERMINATING SCOPE. Whenever we
          * create automatic temporaries -- e.g. by an
@@ -146,13 +185,13 @@ pub fn mark_as_terminating_scope(&self, scope_id: ast::NodeId) {
         self.terminating_scopes.borrow_mut().insert(scope_id);
     }
 
-    pub fn opt_encl_scope(&self, id: ast::NodeId) -> Option<ast::NodeId> {
+    pub fn opt_encl_scope(&self, id: CodeExtent) -> Option<CodeExtent> {
         //! Returns the narrowest scope that encloses `id`, if any.
         self.scope_map.borrow().get(&id).map(|x| *x)
     }
 
     #[allow(dead_code)] // used in middle::cfg
-    pub fn encl_scope(&self, id: ast::NodeId) -> ast::NodeId {
+    pub fn encl_scope(&self, id: CodeExtent) -> CodeExtent {
         //! Returns the narrowest scope that encloses `id`, if any.
         match self.scope_map.borrow().get(&id) {
             Some(&r) => r,
@@ -160,7 +199,7 @@ pub fn encl_scope(&self, id: ast::NodeId) -> ast::NodeId {
         }
     }
 
-    pub fn var_scope(&self, var_id: ast::NodeId) -> ast::NodeId {
+    pub fn var_scope(&self, var_id: ast::NodeId) -> CodeExtent {
         /*!
          * Returns the lifetime of the local variable `var_id`
          */
@@ -170,7 +209,7 @@ pub fn var_scope(&self, var_id: ast::NodeId) -> ast::NodeId {
         }
     }
 
-    pub fn temporary_scope(&self, expr_id: ast::NodeId) -> Option<ast::NodeId> {
+    pub fn temporary_scope(&self, expr_id: ast::NodeId) -> Option<CodeExtent> {
         //! Returns the scope when temp created by expr_id will be cleaned up
 
         // check for a designated rvalue scope
@@ -186,7 +225,7 @@ pub fn temporary_scope(&self, expr_id: ast::NodeId) -> Option<ast::NodeId> {
         // if there's one. Static items, for instance, won't
         // have an enclosing scope, hence no scope will be
         // returned.
-        let mut id = match self.opt_encl_scope(expr_id) {
+        let mut id = match self.opt_encl_scope(CodeExtent::from_node_id(expr_id)) {
             Some(i) => i,
             None => { return None; }
         };
@@ -214,15 +253,15 @@ pub fn var_region(&self, id: ast::NodeId) -> ty::Region {
         scope
     }
 
-    pub fn scopes_intersect(&self, scope1: ast::NodeId, scope2: ast::NodeId)
+    pub fn scopes_intersect(&self, scope1: CodeExtent, scope2: CodeExtent)
                             -> bool {
         self.is_subscope_of(scope1, scope2) ||
         self.is_subscope_of(scope2, scope1)
     }
 
     pub fn is_subscope_of(&self,
-                          subscope: ast::NodeId,
-                          superscope: ast::NodeId)
+                          subscope: CodeExtent,
+                          superscope: CodeExtent)
                           -> bool {
         /*!
          * Returns true if `subscope` is equal to or is lexically
@@ -284,7 +323,7 @@ pub fn is_subregion_of(&self,
                 }
 
                 (ty::ReScope(sub_scope), ty::ReFree(ref fr)) => {
-                    self.is_subscope_of(sub_scope, fr.scope_id)
+                    self.is_subscope_of(sub_scope, fr.scope)
                 }
 
                 (ty::ReFree(sub_fr), ty::ReFree(super_fr)) => {
@@ -309,9 +348,9 @@ pub fn is_subregion_of(&self,
     }
 
     pub fn nearest_common_ancestor(&self,
-                                   scope_a: ast::NodeId,
-                                   scope_b: ast::NodeId)
-                                   -> Option<ast::NodeId> {
+                                   scope_a: CodeExtent,
+                                   scope_b: CodeExtent)
+                                   -> Option<CodeExtent> {
         /*!
          * Finds the nearest common ancestor (if any) of two scopes.  That
          * is, finds the smallest scope which is greater than or equal to
@@ -349,8 +388,8 @@ pub fn nearest_common_ancestor(&self,
             }
         }
 
-        fn ancestors_of(this: &RegionMaps, scope: ast::NodeId)
-            -> Vec<ast::NodeId> {
+        fn ancestors_of(this: &RegionMaps, scope: CodeExtent)
+            -> Vec<CodeExtent> {
             // debug!("ancestors_of(scope={})", scope);
             let mut result = vec!(scope);
             let mut scope = scope;
@@ -374,7 +413,9 @@ fn record_superlifetime(visitor: &mut RegionResolutionVisitor,
                         _sp: Span) {
     match visitor.cx.parent {
         Some(parent_id) => {
-            visitor.region_maps.record_encl_scope(child_id, parent_id);
+            let child_scope = CodeExtent::from_node_id(child_id);
+            let parent_scope = CodeExtent::from_node_id(parent_id);
+            visitor.region_maps.record_encl_scope(child_scope, parent_scope);
         }
         None => {}
     }
@@ -386,7 +427,8 @@ fn record_var_lifetime(visitor: &mut RegionResolutionVisitor,
                        _sp: Span) {
     match visitor.cx.var_parent {
         Some(parent_id) => {
-            visitor.region_maps.record_var_scope(var_id, parent_id);
+            let parent_scope = CodeExtent::from_node_id(parent_id);
+            visitor.region_maps.record_var_scope(var_id, parent_scope);
         }
         None => {
             // this can happen in extern fn declarations like
@@ -418,11 +460,13 @@ fn resolve_block(visitor: &mut RegionResolutionVisitor, blk: &ast::Block) {
 }
 
 fn resolve_arm(visitor: &mut RegionResolutionVisitor, arm: &ast::Arm) {
-    visitor.region_maps.mark_as_terminating_scope(arm.body.id);
+    let arm_body_scope = CodeExtent::from_node_id(arm.body.id);
+    visitor.region_maps.mark_as_terminating_scope(arm_body_scope);
 
     match arm.guard {
         Some(ref expr) => {
-            visitor.region_maps.mark_as_terminating_scope(expr.id);
+            let guard_scope = CodeExtent::from_node_id(expr.id);
+            visitor.region_maps.mark_as_terminating_scope(guard_scope);
         }
         None => { }
     }
@@ -449,7 +493,8 @@ fn resolve_stmt(visitor: &mut RegionResolutionVisitor, stmt: &ast::Stmt) {
     let stmt_id = stmt_id(stmt);
     debug!("resolve_stmt(stmt.id={})", stmt_id);
 
-    visitor.region_maps.mark_as_terminating_scope(stmt_id);
+    let stmt_scope = CodeExtent::from_node_id(stmt_id);
+    visitor.region_maps.mark_as_terminating_scope(stmt_scope);
     record_superlifetime(visitor, stmt_id, stmt.span);
 
     let prev_parent = visitor.cx.parent;
@@ -465,73 +510,80 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr) {
 
     let prev_cx = visitor.cx;
     visitor.cx.parent = Some(expr.id);
-    match expr.node {
-        // Conditional or repeating scopes are always terminating
-        // scopes, meaning that temporaries cannot outlive them.
-        // This ensures fixed size stacks.
-
-        ast::ExprBinary(ast::BiAnd, _, ref r) |
-        ast::ExprBinary(ast::BiOr, _, ref r) => {
-            // For shortcircuiting operators, mark the RHS as a terminating
-            // scope since it only executes conditionally.
-            visitor.region_maps.mark_as_terminating_scope(r.id);
-        }
+    {
+        let region_maps = &mut visitor.region_maps;
+        let terminating = |id| {
+            let scope = CodeExtent::from_node_id(id);
+            region_maps.mark_as_terminating_scope(scope)
+        };
+        match expr.node {
+            // Conditional or repeating scopes are always terminating
+            // scopes, meaning that temporaries cannot outlive them.
+            // This ensures fixed size stacks.
+
+            ast::ExprBinary(ast::BiAnd, _, ref r) |
+            ast::ExprBinary(ast::BiOr, _, ref r) => {
+                // For shortcircuiting operators, mark the RHS as a terminating
+                // scope since it only executes conditionally.
+                terminating(r.id);
+            }
 
-        ast::ExprIf(_, ref then, Some(ref otherwise)) => {
-            visitor.region_maps.mark_as_terminating_scope(then.id);
-            visitor.region_maps.mark_as_terminating_scope(otherwise.id);
-        }
+            ast::ExprIf(_, ref then, Some(ref otherwise)) => {
+                terminating(then.id);
+                terminating(otherwise.id);
+            }
 
-        ast::ExprIf(ref expr, ref then, None) => {
-            visitor.region_maps.mark_as_terminating_scope(expr.id);
-            visitor.region_maps.mark_as_terminating_scope(then.id);
-        }
+            ast::ExprIf(ref expr, ref then, None) => {
+                terminating(expr.id);
+                terminating(then.id);
+            }
 
-        ast::ExprLoop(ref body, _) => {
-            visitor.region_maps.mark_as_terminating_scope(body.id);
-        }
+            ast::ExprLoop(ref body, _) => {
+                terminating(body.id);
+            }
 
-        ast::ExprWhile(ref expr, ref body, _) => {
-            visitor.region_maps.mark_as_terminating_scope(expr.id);
-            visitor.region_maps.mark_as_terminating_scope(body.id);
-        }
+            ast::ExprWhile(ref expr, ref body, _) => {
+                terminating(expr.id);
+                terminating(body.id);
+            }
 
-        ast::ExprForLoop(ref _pat, ref _head, ref body, _) => {
-            visitor.region_maps.mark_as_terminating_scope(body.id);
+            ast::ExprForLoop(ref _pat, ref _head, ref body, _) => {
+                terminating(body.id);
 
-            // The variable parent of everything inside (most importantly, the
-            // pattern) is the body.
-            visitor.cx.var_parent = Some(body.id);
-        }
+                // The variable parent of everything inside (most importantly, the
+                // pattern) is the body.
+                visitor.cx.var_parent = Some(body.id);
+            }
 
-        ast::ExprMatch(..) => {
-            visitor.cx.var_parent = Some(expr.id);
-        }
+            ast::ExprMatch(..) => {
+                visitor.cx.var_parent = Some(expr.id);
+            }
 
-        ast::ExprAssignOp(..) | ast::ExprIndex(..) |
-        ast::ExprUnary(..) | ast::ExprCall(..) | ast::ExprMethodCall(..) => {
-            // FIXME(#6268) Nested method calls
-            //
-            // The lifetimes for a call or method call look as follows:
-            //
-            // call.id
-            // - arg0.id
-            // - ...
-            // - argN.id
-            // - call.callee_id
-            //
-            // The idea is that call.callee_id represents *the time when
-            // the invoked function is actually running* and call.id
-            // represents *the time to prepare the arguments and make the
-            // call*.  See the section "Borrows in Calls" borrowck/doc.rs
-            // for an extended explanation of why this distinction is
-            // important.
-            //
-            // record_superlifetime(new_cx, expr.callee_id);
-        }
+            ast::ExprAssignOp(..) | ast::ExprIndex(..) |
+            ast::ExprUnary(..) | ast::ExprCall(..) | ast::ExprMethodCall(..) => {
+                // FIXME(#6268) Nested method calls
+                //
+                // The lifetimes for a call or method call look as follows:
+                //
+                // call.id
+                // - arg0.id
+                // - ...
+                // - argN.id
+                // - call.callee_id
+                //
+                // The idea is that call.callee_id represents *the time when
+                // the invoked function is actually running* and call.id
+                // represents *the time to prepare the arguments and make the
+                // call*.  See the section "Borrows in Calls" borrowck/doc.rs
+                // for an extended explanation of why this distinction is
+                // important.
+                //
+                // record_superlifetime(new_cx, expr.callee_id);
+            }
 
-        _ => {}
-    };
+            _ => {}
+        }
+    }
 
     visit::walk_expr(visitor, expr);
     visitor.cx = prev_cx;
@@ -553,7 +605,8 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) {
     // For convenience in trans, associate with the local-id the var
     // scope that will be used for any bindings declared in this
     // pattern.
-    visitor.region_maps.record_var_scope(local.id, blk_id);
+    let blk_scope = CodeExtent::from_node_id(blk_id);
+    visitor.region_maps.record_var_scope(local.id, blk_scope);
 
     // As an exception to the normal rules governing temporary
     // lifetimes, initializers in a let have a temporary lifetime
@@ -618,10 +671,10 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) {
 
     match local.init {
         Some(ref expr) => {
-            record_rvalue_scope_if_borrow_expr(visitor, &**expr, blk_id);
+            record_rvalue_scope_if_borrow_expr(visitor, &**expr, blk_scope);
 
             if is_binding_pat(&*local.pat) || is_borrowed_ty(&*local.ty) {
-                record_rvalue_scope(visitor, &**expr, blk_id);
+                record_rvalue_scope(visitor, &**expr, blk_scope);
             }
         }
 
@@ -682,7 +735,7 @@ fn is_borrowed_ty(ty: &ast::Ty) -> bool {
 
     fn record_rvalue_scope_if_borrow_expr(visitor: &mut RegionResolutionVisitor,
                                           expr: &ast::Expr,
-                                          blk_id: ast::NodeId) {
+                                          blk_id: CodeExtent) {
         /*!
          * If `expr` matches the `E&` grammar, then records an extended
          * rvalue scope as appropriate:
@@ -738,7 +791,7 @@ fn record_rvalue_scope_if_borrow_expr(visitor: &mut RegionResolutionVisitor,
 
     fn record_rvalue_scope<'a>(visitor: &mut RegionResolutionVisitor,
                                expr: &'a ast::Expr,
-                               blk_id: ast::NodeId) {
+                               blk_scope: CodeExtent) {
         /*!
          * Applied to an expression `expr` if `expr` -- or something
          * owned or partially owned by `expr` -- is going to be
@@ -766,7 +819,7 @@ fn record_rvalue_scope<'a>(visitor: &mut RegionResolutionVisitor,
             // because in trans if we must compile e.g. `*rvalue()`
             // into a temporary, we request the temporary scope of the
             // outer expression.
-            visitor.region_maps.record_rvalue_scope(expr.id, blk_id);
+            visitor.region_maps.record_rvalue_scope(expr.id, blk_scope);
 
             match expr.node {
                 ast::ExprAddrOf(_, ref subexpr) |
@@ -809,7 +862,8 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor,
            body.id,
            visitor.cx.parent);
 
-    visitor.region_maps.mark_as_terminating_scope(body.id);
+    let body_scope = CodeExtent::from_node_id(body.id);
+    visitor.region_maps.mark_as_terminating_scope(body_scope);
 
     let outer_cx = visitor.cx;
 
@@ -873,11 +927,11 @@ fn visit_local(&mut self, l: &Local) {
 
 pub fn resolve_crate(sess: &Session, krate: &ast::Crate) -> RegionMaps {
     let maps = RegionMaps {
-        scope_map: RefCell::new(NodeMap::new()),
+        scope_map: RefCell::new(FnvHashMap::new()),
         var_map: RefCell::new(NodeMap::new()),
         free_region_map: RefCell::new(FnvHashMap::new()),
         rvalue_scopes: RefCell::new(NodeMap::new()),
-        terminating_scopes: RefCell::new(NodeSet::new()),
+        terminating_scopes: RefCell::new(FnvHashSet::new()),
     };
     {
         let mut visitor = RegionResolutionVisitor {
index 3fc92a84194243d08ad631a4250c65ec363dd2af..fae64ff924274c41ead2ebec5de88ab53b8bf9e1 100644 (file)
@@ -22,6 +22,7 @@
 
 use session::Session;
 use middle::def;
+use middle::region;
 use middle::resolve::DefMap;
 use middle::subst;
 use middle::ty;
@@ -43,7 +44,7 @@ pub enum DefRegion {
                         /* lifetime decl */ ast::NodeId),
     DefLateBoundRegion(ty::DebruijnIndex,
                        /* lifetime decl */ ast::NodeId),
-    DefFreeRegion(/* block scope */ ast::NodeId,
+    DefFreeRegion(/* block scope */ region::CodeExtent,
                   /* lifetime decl */ ast::NodeId),
 }
 
@@ -67,7 +68,7 @@ enum ScopeChain<'a> {
     LateScope(&'a Vec<ast::LifetimeDef>, Scope<'a>),
     /// lifetimes introduced by items within a code block are scoped
     /// to that block.
-    BlockScope(ast::NodeId, Scope<'a>),
+    BlockScope(region::CodeExtent, Scope<'a>),
     RootScope
 }
 
@@ -195,7 +196,8 @@ fn visit_ty_method(&mut self, m: &ast::TypeMethod) {
     }
 
     fn visit_block(&mut self, b: &ast::Block) {
-        self.with(BlockScope(b.id, self.scope), |this| visit::walk_block(this, b));
+        self.with(BlockScope(region::CodeExtent::from_node_id(b.id), self.scope),
+                  |this| visit::walk_block(this, b));
     }
 
     fn visit_lifetime_ref(&mut self, lifetime_ref: &ast::Lifetime) {
@@ -307,8 +309,8 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &ast::Lifetime) {
         let mut scope = self.scope;
         loop {
             match *scope {
-                BlockScope(id, s) => {
-                    return self.resolve_free_lifetime_ref(id, lifetime_ref, s);
+                BlockScope(blk_scope, s) => {
+                    return self.resolve_free_lifetime_ref(blk_scope, lifetime_ref, s);
                 }
 
                 RootScope => {
@@ -350,19 +352,19 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &ast::Lifetime) {
     }
 
     fn resolve_free_lifetime_ref(&mut self,
-                                 scope_id: ast::NodeId,
+                                 scope_data: region::CodeExtent,
                                  lifetime_ref: &ast::Lifetime,
                                  scope: Scope) {
         // Walk up the scope chain, tracking the outermost free scope,
         // until we encounter a scope that contains the named lifetime
         // or we run out of scopes.
-        let mut scope_id = scope_id;
+        let mut scope_data = scope_data;
         let mut scope = scope;
         let mut search_result = None;
         loop {
             match *scope {
-                BlockScope(id, s) => {
-                    scope_id = id;
+                BlockScope(blk_scope_data, s) => {
+                    scope_data = blk_scope_data;
                     scope = s;
                 }
 
@@ -383,7 +385,7 @@ fn resolve_free_lifetime_ref(&mut self,
 
         match search_result {
             Some((_depth, decl_id)) => {
-                let def = DefFreeRegion(scope_id, decl_id);
+                let def = DefFreeRegion(scope_data, decl_id);
                 self.insert_lifetime(lifetime_ref, def);
             }
 
index 15c292a6b2078e01c5b017f0824549999f7ea7c2..11badf7d1900e4027876ea77f0c7d640d844be82 100644 (file)
@@ -46,6 +46,7 @@
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
 use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem};
 use middle::mem_categorization as mc;
+use middle::region;
 use middle::resolve;
 use middle::resolve_lifetime;
 use middle::stability;
@@ -837,7 +838,7 @@ pub enum Region {
     ReFree(FreeRegion),
 
     /// A concrete region naming some expression within the current function.
-    ReScope(NodeId),
+    ReScope(region::CodeExtent),
 
     /// Static data that has an "infinite" lifetime. Top in the region lattice.
     ReStatic,
@@ -987,8 +988,10 @@ pub fn escapes_depth(&self, depth: uint) -> bool {
 }
 
 #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Encodable, Decodable, Show)]
+/// A "free" region `fr` can be interpreted as "some region
+/// at least as big as the scope `fr.scope`".
 pub struct FreeRegion {
-    pub scope_id: NodeId,
+    pub scope: region::CodeExtent,
     pub bound_region: BoundRegion
 }
 
@@ -3564,7 +3567,7 @@ pub fn ty_region(tcx: &ctxt,
 pub fn free_region_from_def(free_id: ast::NodeId, def: &RegionParameterDef)
     -> ty::Region
 {
-    ty::ReFree(ty::FreeRegion { scope_id: free_id,
+    ty::ReFree(ty::FreeRegion { scope: region::CodeExtent::from_node_id(free_id),
                                 bound_region: ty::BrNamed(def.def_id,
                                                           def.name) })
 }
@@ -5629,12 +5632,14 @@ pub fn construct_parameter_environment<'tcx>(
         regions: subst::NonerasedRegions(regions)
     };
 
+    let free_id_scope = region::CodeExtent::from_node_id(free_id);
+
     //
     // Compute the bounds on Self and the type parameters.
     //
 
     let bounds = generics.to_bounds(tcx, &free_substs);
-    let bounds = liberate_late_bound_regions(tcx, free_id, &bind(bounds)).value;
+    let bounds = liberate_late_bound_regions(tcx, free_id_scope, &bind(bounds)).value;
     let obligations = traits::obligations_for_generics(tcx,
                                                        traits::ObligationCause::misc(span),
                                                        &bounds,
@@ -5662,7 +5667,7 @@ pub fn construct_parameter_environment<'tcx>(
     return ty::ParameterEnvironment {
         free_substs: free_substs,
         bounds: bounds.types,
-        implicit_region_bound: ty::ReScope(free_id),
+        implicit_region_bound: ty::ReScope(free_id_scope),
         caller_obligations: obligations,
         selection_cache: traits::SelectionCache::new(),
     };
@@ -5781,7 +5786,7 @@ fn is_method_call(&self, id: ast::NodeId) -> bool {
         self.method_map.borrow().contains_key(&typeck::MethodCall::expr(id))
     }
 
-    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId> {
+    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent> {
         self.region_maps.temporary_scope(rvalue_id)
     }
 
@@ -5906,7 +5911,7 @@ pub fn is_identity(&self) -> bool {
 
 pub fn liberate_late_bound_regions<'tcx, HR>(
     tcx: &ty::ctxt<'tcx>,
-    scope_id: ast::NodeId,
+    scope: region::CodeExtent,
     value: &HR)
     -> HR
     where HR : HigherRankedFoldable<'tcx>
@@ -5918,7 +5923,7 @@ pub fn liberate_late_bound_regions<'tcx, HR>(
 
     replace_late_bound_regions(
         tcx, value,
-        |br, _| ty::ReFree(ty::FreeRegion{scope_id: scope_id, bound_region: br})).0
+        |br, _| ty::ReFree(ty::FreeRegion{scope: scope, bound_region: br})).0
 }
 
 pub fn erase_late_bound_regions<'tcx, HR>(
index 637c1f58157e20c29170d6682f0c27e925f3d3ee..9190c8bf115b7e73234adea5af60ca8afd5fdf9d 100644 (file)
@@ -113,9 +113,9 @@ pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
             ty::ReEarlyBound(id, space, index, lifetime.name)
         }
 
-        Some(&rl::DefFreeRegion(scope_id, id)) => {
+        Some(&rl::DefFreeRegion(scope, id)) => {
             ty::ReFree(ty::FreeRegion {
-                    scope_id: scope_id,
+                    scope: scope,
                     bound_region: ty::BrNamed(ast_util::local_def(id),
                                               lifetime.name)
                 })
index 553d80852c28fb959117ebcb0465096c8f20f56d..b7e33f60147b6b1d3db662190eac995b64e7e86e 100644 (file)
@@ -90,6 +90,7 @@
 use middle::mem_categorization;
 use middle::pat_util::pat_id_map;
 use middle::pat_util;
+use middle::region::CodeExtent;
 use middle::subst;
 use middle::subst::{Subst, Substs, VecPerParamSpace, ParamSpace};
 use middle::traits;
@@ -308,7 +309,7 @@ fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
     fn is_method_call(&self, id: ast::NodeId) -> bool {
         self.inh.method_map.borrow().contains_key(&typeck::MethodCall::expr(id))
     }
-    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId> {
+    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
         self.tcx().temporary_scope(rvalue_id)
     }
     fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
@@ -529,7 +530,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
 
     // First, we have to replace any bound regions in the fn type with free ones.
     // The free region references will be bound the node_id of the body block.
-    let fn_sig = liberate_late_bound_regions(tcx, body.id, fn_sig);
+    let fn_sig = liberate_late_bound_regions(tcx, CodeExtent::from_node_id(body.id), fn_sig);
 
     let arg_tys = fn_sig.inputs.as_slice();
     let ret_ty = fn_sig.output;
@@ -742,7 +743,8 @@ fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     debug!("fty (raw): {}", fty.repr(ccx.tcx));
 
     let body_id = method.pe_body().id;
-    let fty = liberate_late_bound_regions(ccx.tcx, body_id, &ty::bind(fty)).value;
+    let fty = liberate_late_bound_regions(
+        ccx.tcx, CodeExtent::from_node_id(body_id), &ty::bind(fty)).value;
     debug!("fty (liberated): {}", fty.repr(ccx.tcx));
 
     check_bare_fn(ccx,
@@ -937,6 +939,8 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     debug!("compare_impl_method(impl_trait_ref={})",
            impl_trait_ref.repr(tcx));
 
+    let impl_m_body_scope = CodeExtent::from_node_id(impl_m_body_id);
+
     // The impl's trait ref may bind late-bound regions from the impl.
     // Liberate them and assign them the scope of the method body.
     //
@@ -954,7 +958,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     //     Foo<&'A T>
     //
     // where `'A` is the `ReFree` version of `'a`.
-    let impl_trait_ref = liberate_late_bound_regions(tcx, impl_m_body_id, impl_trait_ref);
+    let impl_trait_ref = liberate_late_bound_regions(tcx, impl_m_body_scope, impl_trait_ref);
 
     debug!("impl_trait_ref (liberated) = {}",
            impl_trait_ref.repr(tcx));
@@ -1097,7 +1101,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     if !check_region_bounds_on_impl_method(tcx,
                                            impl_m_span,
                                            impl_m,
-                                           impl_m_body_id,
+                                           impl_m_body_scope,
                                            &trait_m.generics,
                                            &impl_m.generics,
                                            &trait_to_skol_substs,
@@ -1139,7 +1143,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
         .map(|impl_param_def|
              liberate_late_bound_regions(
                  tcx,
-                 impl_m_body_id,
+                 impl_m_body_scope,
                  &ty::bind(ty::bind(impl_param_def.bounds.clone()))).value.value);
     for (i, (trait_param_bounds, impl_param_bounds)) in
         trait_bounds.zip(impl_bounds).enumerate()
@@ -1205,7 +1209,8 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     // that we must liberate the late-bound regions from the impl.
     let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
     let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
-    let impl_fty = liberate_late_bound_regions(tcx, impl_m_body_id, &ty::bind(impl_fty)).value;
+    let impl_fty = liberate_late_bound_regions(
+        tcx, impl_m_body_scope, &ty::bind(impl_fty)).value;
     let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
     let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
 
@@ -1240,7 +1245,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     fn check_region_bounds_on_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
                                                 span: Span,
                                                 impl_m: &ty::Method<'tcx>,
-                                                impl_m_body_id: ast::NodeId,
+                                                impl_m_body_scope: CodeExtent,
                                                 trait_generics: &ty::Generics<'tcx>,
                                                 impl_generics: &ty::Generics<'tcx>,
                                                 trait_to_skol_substs: &Substs<'tcx>,
@@ -1331,9 +1336,7 @@ fn method2<'b>() { .. case 2, could be ok .. }
             // impl, and the method.
             let impl_bounds =
                 ty::liberate_late_bound_regions(
-                    tcx,
-                    impl_m_body_id,
-                    &ty::bind(ty::bind(impl_bounds))).value.value;
+                    tcx, impl_m_body_scope, &ty::bind(ty::bind(impl_bounds))).value.value;
 
             debug!("check_region_bounds_on_impl_method: \
                    trait_param={} \
@@ -1881,7 +1884,7 @@ pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
 
         let mut bounds_checker = wf::BoundsChecker::new(self,
                                                         ast_t.span,
-                                                        self.body_id,
+                                                        CodeExtent::from_node_id(self.body_id),
                                                         None);
         bounds_checker.check_ty(t);
 
@@ -2055,7 +2058,7 @@ pub fn add_default_region_param_bounds(&self,
                                            expr: &ast::Expr)
     {
         for &ty in substs.types.iter() {
-            let default_bound = ty::ReScope(expr.id);
+            let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
             let origin = infer::RelateDefaultParamBound(expr.span, ty);
             self.register_region_obligation(origin, ty, default_bound);
         }
index 44c11318038d39c244c78072b8f5cc8f1abeadc5..d59088454229864d69a9c1f9848832555cc08cb7 100644 (file)
@@ -120,6 +120,7 @@ fn get_i(x: &'a Bar) -> &'a int {
 
 use middle::def;
 use middle::mem_categorization as mc;
+use middle::region::CodeExtent;
 use middle::traits;
 use middle::ty::{ReScope};
 use middle::ty::{mod, Ty};
@@ -253,7 +254,7 @@ fn region_of_def(fcx: &FnCtxt, def: def::Def) -> ty::Region {
             if body_id == ast::DUMMY_NODE_ID {
                 tcx.region_maps.var_region(node_id)
             } else {
-                ReScope(body_id)
+                ReScope(CodeExtent::from_node_id(body_id))
             }
         }
         _ => {
@@ -408,7 +409,8 @@ fn relate_free_regions(&mut self,
         for &ty in fn_sig_tys.iter() {
             let ty = self.resolve_type(ty);
             debug!("relate_free_regions(t={})", ty.repr(tcx));
-            let body_scope = ty::ReScope(body_id);
+            let body_scope = CodeExtent::from_node_id(body_id);
+            let body_scope = ty::ReScope(body_scope);
             let constraints =
                 regionmanip::region_wf_constraints(
                     tcx,
@@ -474,7 +476,7 @@ fn is_method_call(&self, id: ast::NodeId) -> bool {
         self.fcx.inh.method_map.borrow().contains_key(&MethodCall::expr(id))
     }
 
-    fn temporary_scope(&self, id: ast::NodeId) -> Option<ast::NodeId> {
+    fn temporary_scope(&self, id: ast::NodeId) -> Option<CodeExtent> {
         self.tcx().region_maps.temporary_scope(id)
     }
 
@@ -587,7 +589,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
     let expr_ty = rcx.resolve_node_type(expr.id);
 
     type_must_outlive(rcx, infer::ExprTypeIsNotInScope(expr_ty, expr.span),
-                      expr_ty, ty::ReScope(expr.id));
+                      expr_ty, ty::ReScope(CodeExtent::from_node_id(expr.id)));
 
     let method_call = MethodCall::expr(expr.id);
     let has_method_map = rcx.fcx.inh.method_map.borrow().contains_key(&method_call);
@@ -608,7 +610,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
                     // FIXME(#6268) remove to support nested method calls
                     type_of_node_must_outlive(
                         rcx, infer::AutoBorrow(expr.span),
-                        expr.id, ty::ReScope(expr.id));
+                        expr.id, ty::ReScope(CodeExtent::from_node_id(expr.id)));
                 }
             }
             /*
@@ -695,8 +697,8 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             };
             match base_ty.sty {
                 ty::ty_rptr(r_ptr, _) => {
-                    mk_subregion_due_to_dereference(rcx, expr.span,
-                                                    ty::ReScope(expr.id), r_ptr);
+                    mk_subregion_due_to_dereference(
+                        rcx, expr.span, ty::ReScope(CodeExtent::from_node_id(expr.id)), r_ptr);
                 }
                 _ => {}
             }
@@ -732,7 +734,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             // FIXME(#6268) nested method calls requires that this rule change
             let ty0 = rcx.resolve_node_type(expr.id);
             type_must_outlive(rcx, infer::AddrOf(expr.span),
-                              ty0, ty::ReScope(expr.id));
+                              ty0, ty::ReScope(CodeExtent::from_node_id(expr.id)));
             visit::walk_expr(rcx, expr);
         }
 
@@ -772,7 +774,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
                 let pat_ty = rcx.resolve_node_type(pat.id);
                 let pat_cmt = mc.cat_rvalue(pat.id,
                                             pat.span,
-                                            ty::ReScope(body.id),
+                                            ty::ReScope(CodeExtent::from_node_id(body.id)),
                                             pat_ty);
                 link_pattern(rcx, mc, pat_cmt, &**pat);
             }
@@ -781,7 +783,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             type_of_node_must_outlive(rcx,
                                       infer::AddrOf(expr.span),
                                       head.id,
-                                      ty::ReScope(expr.id));
+                                      ty::ReScope(CodeExtent::from_node_id(expr.id)));
 
             let repeating_scope = rcx.set_repeating_scope(body.id);
             rcx.visit_block(&**body);
@@ -866,7 +868,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
                     // outlive the appropriate temporary scope.
                     let s = rcx.repeating_scope;
                     rcx.fcx.mk_subr(infer::InfStackClosure(expr.span),
-                                    bounds.region_bound, ty::ReScope(s));
+                                    bounds.region_bound, ty::ReScope(CodeExtent::from_node_id(s)));
                 }
             });
         }
@@ -1089,7 +1091,7 @@ fn constrain_callee(rcx: &mut Rcx,
                     callee_id: ast::NodeId,
                     call_expr: &ast::Expr,
                     callee_expr: &ast::Expr) {
-    let call_region = ty::ReScope(call_expr.id);
+    let call_region = ty::ReScope(CodeExtent::from_node_id(call_expr.id));
 
     let callee_ty = rcx.resolve_node_type(callee_id);
     match callee_ty.sty {
@@ -1147,7 +1149,7 @@ fn constrain_call<'a, I: Iterator<&'a ast::Expr>>(rcx: &mut Rcx,
     // call occurs.
     //
     // FIXME(#6268) to support nested method calls, should be callee_id
-    let callee_scope = call_expr.id;
+    let callee_scope = CodeExtent::from_node_id(call_expr.id);
     let callee_region = ty::ReScope(callee_scope);
 
     debug!("callee_region={}", callee_region.repr(tcx));
@@ -1191,7 +1193,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
      * this is a region pointer being dereferenced, the lifetime of
      * the pointer includes the deref expr.
      */
-    let r_deref_expr = ty::ReScope(deref_expr.id);
+    let r_deref_expr = ty::ReScope(CodeExtent::from_node_id(deref_expr.id));
     for i in range(0u, derefs) {
         debug!("constrain_autoderefs(deref_expr=?, derefd_ty={}, derefs={}/{}",
                rcx.fcx.infcx().ty_to_string(derefd_ty),
@@ -1271,7 +1273,7 @@ fn constrain_index<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
     debug!("constrain_index(index_expr=?, indexed_ty={}",
            rcx.fcx.infcx().ty_to_string(indexed_ty));
 
-    let r_index_expr = ty::ReScope(index_expr.id);
+    let r_index_expr = ty::ReScope(CodeExtent::from_node_id(index_expr.id));
     match indexed_ty.sty {
         ty::ty_rptr(r_ptr, mt) => match mt.ty.sty {
             ty::ty_vec(_, None) | ty::ty_str => {
@@ -1425,7 +1427,7 @@ fn link_autoref(rcx: &Rcx,
 
 fn link_by_ref(rcx: &Rcx,
                expr: &ast::Expr,
-               callee_scope: ast::NodeId) {
+               callee_scope: CodeExtent) {
     /*!
      * Computes the guarantor for cases where the `expr` is
      * being passed by implicit reference and must outlive
index 5cc619bba26ba48148dc85a4547de1dfd244abc7..d9c6c3cb6262ad7105a38071e2466821faf70437 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use middle::region;
 use middle::subst;
 use middle::subst::{Subst};
 use middle::traits;
@@ -118,8 +119,10 @@ fn check_type_defn(&mut self,
 
         self.with_fcx(item, |this, fcx| {
             let variants = lookup_fields(fcx);
-            let mut bounds_checker = BoundsChecker::new(fcx, item.span,
-                                                        item.id, Some(&mut this.cache));
+            let mut bounds_checker = BoundsChecker::new(fcx,
+                                                        item.span,
+                                                        region::CodeExtent::from_node_id(item.id),
+                                                        Some(&mut this.cache));
             for variant in variants.iter() {
                 for field in variant.fields.iter() {
                     // Regions are checked below.
@@ -154,8 +157,10 @@ fn check_item_type(&mut self,
                        item: &ast::Item)
     {
         self.with_fcx(item, |this, fcx| {
-            let mut bounds_checker = BoundsChecker::new(fcx, item.span,
-                                                        item.id, Some(&mut this.cache));
+            let mut bounds_checker = BoundsChecker::new(fcx,
+                                                        item.span,
+                                                        region::CodeExtent::from_node_id(item.id),
+                                                        Some(&mut this.cache));
             let polytype = ty::lookup_item_type(fcx.tcx(), local_def(item.id));
             let item_ty = polytype.ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs);
             bounds_checker.check_traits_in_ty(item_ty);
@@ -166,8 +171,12 @@ fn check_impl(&mut self,
                   item: &ast::Item)
     {
         self.with_fcx(item, |this, fcx| {
-            let mut bounds_checker = BoundsChecker::new(fcx, item.span,
-                                                        item.id, Some(&mut this.cache));
+            let item_scope = region::CodeExtent::from_node_id(item.id);
+
+            let mut bounds_checker = BoundsChecker::new(fcx,
+                                                        item.span,
+                                                        item_scope,
+                                                        Some(&mut this.cache));
 
             // Find the impl self type as seen from the "inside" --
             // that is, with all type parameters converted from bound
@@ -175,7 +184,8 @@ fn check_impl(&mut self,
             // liberated.
             let self_ty = ty::node_id_to_type(fcx.tcx(), item.id);
             let self_ty = self_ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs);
-            let self_ty = liberate_late_bound_regions(fcx.tcx(), item.id, &ty::bind(self_ty)).value;
+            let self_ty = liberate_late_bound_regions(
+                fcx.tcx(), item_scope, &ty::bind(self_ty)).value;
 
             bounds_checker.check_traits_in_ty(self_ty);
 
@@ -186,7 +196,7 @@ fn check_impl(&mut self,
                 Some(t) => { t }
             };
             let trait_ref = (*trait_ref).subst(fcx.tcx(), &fcx.inh.param_env.free_substs);
-            let trait_ref = liberate_late_bound_regions(fcx.tcx(), item.id, &trait_ref);
+            let trait_ref = liberate_late_bound_regions(fcx.tcx(), item_scope, &trait_ref);
 
             // There are special rules that apply to drop.
             if
@@ -257,7 +267,7 @@ fn visit_item(&mut self, i: &ast::Item) {
 pub struct BoundsChecker<'cx,'tcx:'cx> {
     fcx: &'cx FnCtxt<'cx,'tcx>,
     span: Span,
-    scope_id: ast::NodeId,
+    scope: region::CodeExtent,
     binding_count: uint,
     cache: Option<&'cx mut HashSet<Ty<'tcx>>>,
 }
@@ -265,10 +275,10 @@ pub struct BoundsChecker<'cx,'tcx:'cx> {
 impl<'cx,'tcx> BoundsChecker<'cx,'tcx> {
     pub fn new(fcx: &'cx FnCtxt<'cx,'tcx>,
                span: Span,
-               scope_id: ast::NodeId,
+               scope: region::CodeExtent,
                cache: Option<&'cx mut HashSet<Ty<'tcx>>>)
                -> BoundsChecker<'cx,'tcx> {
-        BoundsChecker { fcx: fcx, span: span, scope_id: scope_id,
+        BoundsChecker { fcx: fcx, span: span, scope: scope,
                         cache: cache, binding_count: 0 }
     }
 
@@ -383,7 +393,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             ty::ty_closure(box ty::ClosureTy{sig: ref fn_sig, ..}) => {
                 self.binding_count += 1;
 
-                let fn_sig = liberate_late_bound_regions(self.fcx.tcx(), self.scope_id, fn_sig);
+                let fn_sig = liberate_late_bound_regions(self.fcx.tcx(), self.scope, fn_sig);
 
                 debug!("late-bound regions replaced: {}",
                        fn_sig.repr(self.tcx()));
index 90ad0d2f3e5e223d3537e2cc7a2eba022d92e830..13a0bf0bdcb522000a9a737cdb52a37446cc4826 100644 (file)
@@ -35,6 +35,7 @@
 use metadata::csearch;
 use middle::def;
 use middle::lang_items::SizedTraitLangItem;
+use middle::region;
 use middle::resolve_lifetime;
 use middle::subst;
 use middle::subst::{Substs};
@@ -2161,6 +2162,8 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
                 _ => typ,
             };
 
+            let body_scope = region::CodeExtent::from_node_id(body_id);
+
             // "Required type" comes from the trait definition. It may
             // contain late-bound regions from the method, but not the
             // trait (since traits only have early-bound region
@@ -2168,22 +2171,16 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
             assert!(!ty::type_escapes_depth(required_type, 1));
             let required_type_free =
                 ty::liberate_late_bound_regions(
-                    crate_context.tcx,
-                    body_id,
-                    &ty::bind(required_type)).value;
+                    crate_context.tcx, body_scope, &ty::bind(required_type)).value;
 
             // The "base type" comes from the impl. It may have late-bound
             // regions from the impl or the method.
             let base_type_free = // liberate impl regions:
                 ty::liberate_late_bound_regions(
-                    crate_context.tcx,
-                    body_id,
-                    &ty::bind(ty::bind(base_type))).value.value;
+                    crate_context.tcx, body_scope, &ty::bind(ty::bind(base_type))).value.value;
             let base_type_free = // liberate method regions:
                 ty::liberate_late_bound_regions(
-                    crate_context.tcx,
-                    body_id,
-                    &ty::bind(base_type_free)).value;
+                    crate_context.tcx, body_scope, &ty::bind(base_type_free)).value;
 
             debug!("required_type={} required_type_free={} \
                     base_type={} base_type_free={}",
index 7a7a7c796740aa646feab24154e764124edb56e3..bc36a2bd801b46765e0db98fb094163f421f845d 100644 (file)
@@ -301,11 +301,11 @@ fn free_regions_from_same_fn(tcx: &ty::ctxt,
             debug!("free_regions_from_same_fn(sub={}, sup={})", sub, sup);
             let (scope_id, fr1, fr2) = match (sub, sup) {
                 (ReFree(fr1), ReFree(fr2)) => {
-                    if fr1.scope_id != fr2.scope_id {
+                    if fr1.scope != fr2.scope {
                         return None
                     }
-                    assert!(fr1.scope_id == fr2.scope_id);
-                    (fr1.scope_id, fr1, fr2)
+                    assert!(fr1.scope == fr2.scope);
+                    (fr1.scope.node_id(), fr1, fr2)
                 },
                 _ => return None
             };
index 5452a99127fc47f643af5fca363e28d3daf00a14..6a447d467cfcec46b903fdd58ac7c5dce30e1853 100644 (file)
@@ -18,6 +18,7 @@
 pub use self::VarValue::*;
 use self::Classification::*;
 
+use middle::region;
 use middle::ty;
 use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid};
 use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound};
@@ -747,11 +748,11 @@ fn lub_concrete_regions(&self, a: Region, b: Region) -> Region {
             // A "free" region can be interpreted as "some region
             // at least as big as the block fr.scope_id".  So, we can
             // reasonably compare free regions and scopes:
-            match self.tcx.region_maps.nearest_common_ancestor(fr.scope_id, s_id) {
+            match self.tcx.region_maps.nearest_common_ancestor(fr.scope, s_id) {
               // if the free region's scope `fr.scope_id` is bigger than
               // the scope region `s_id`, then the LUB is the free
               // region itself:
-              Some(r_id) if r_id == fr.scope_id => f,
+              Some(r_id) if r_id == fr.scope => f,
 
               // otherwise, we don't know what the free region is,
               // so we must conservatively say the LUB is static:
@@ -856,8 +857,8 @@ fn glb_concrete_regions(&self,
                 // than the scope `s_id`, then we can say that the GLB
                 // is the scope `s_id`.  Otherwise, as we do not know
                 // big the free region is precisely, the GLB is undefined.
-                match self.tcx.region_maps.nearest_common_ancestor(fr.scope_id, s_id) {
-                    Some(r_id) if r_id == fr.scope_id => Ok(s),
+                match self.tcx.region_maps.nearest_common_ancestor(fr.scope, s_id) {
+                    Some(r_id) if r_id == fr.scope => Ok(s),
                     _ => Err(ty::terr_regions_no_overlap(b, a))
                 }
             }
@@ -909,7 +910,7 @@ fn helper<'a, 'tcx>(this: &RegionVarBindings<'a, 'tcx>,
                 Ok(ty::ReFree(*b))
             } else {
                 this.intersect_scopes(ty::ReFree(*a), ty::ReFree(*b),
-                                      a.scope_id, b.scope_id)
+                                      a.scope, b.scope)
             }
         }
     }
@@ -917,8 +918,8 @@ fn helper<'a, 'tcx>(this: &RegionVarBindings<'a, 'tcx>,
     fn intersect_scopes(&self,
                         region_a: ty::Region,
                         region_b: ty::Region,
-                        scope_a: ast::NodeId,
-                        scope_b: ast::NodeId) -> cres<'tcx, Region>
+                        scope_a: region::CodeExtent,
+                        scope_b: region::CodeExtent) -> cres<'tcx, Region>
     {
         // We want to generate the intersection of two
         // scopes or two free regions.  So, if one of
index 76055372a61491ca7dbe612008bbabaf24fe5f1e..761a1f66501ca597ad7694ee0c46a055d8a8df87 100644 (file)
@@ -84,8 +84,8 @@ fn item_scope_tag(item: &ast::Item) -> &'static str {
 pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
                             -> (String, Option<Span>) {
     return match region {
-      ReScope(node_id) => {
-        match cx.map.find(node_id) {
+      ReScope(scope) => {
+        match cx.map.find(scope.node_id()) {
           Some(ast_map::NodeBlock(ref blk)) => {
             explain_span(cx, "block", blk.span)
           }
@@ -112,7 +112,7 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
           }
           Some(_) | None => {
             // this really should not happen
-            (format!("unknown scope: {}.  Please report a bug.", node_id), None)
+            (format!("unknown scope: {}.  Please report a bug.", scope), None)
           }
         }
       }
@@ -129,7 +129,7 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
           }
         };
 
-        match cx.map.find(fr.scope_id) {
+        match cx.map.find(fr.scope.node_id()) {
           Some(ast_map::NodeBlock(ref blk)) => {
               let (msg, opt_span) = explain_span(cx, "block", blk.span);
               (format!("{} {}", prefix, msg), opt_span)
@@ -141,7 +141,7 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
           }
           Some(_) | None => {
               // this really should not happen
-              (format!("{} node {}", prefix, fr.scope_id), None)
+              (format!("{} unknown free region bounded by scope {}", prefix, fr.scope), None)
           }
         }
       }
@@ -879,7 +879,7 @@ fn user_string(&self, tcx: &ctxt) -> String {
 impl<'tcx> Repr<'tcx> for ty::FreeRegion {
     fn repr(&self, tcx: &ctxt) -> String {
         format!("ReFree({}, {})",
-                self.scope_id,
+                self.scope.node_id(),
                 self.bound_region.repr(tcx))
     }
 }
index 984c1f99720eae65a5d82ab36d3f9b45544a75c9..1e8c1fd14787d240f1a35f1991b43641710f6e4c 100644 (file)
@@ -18,7 +18,7 @@
 use driver::diagnostic::Emitter;
 use driver::driver;
 use middle::lang_items;
-use middle::region;
+use middle::region::{mod, CodeExtent};
 use middle::resolve;
 use middle::resolve_lifetime;
 use middle::stability;
@@ -149,7 +149,9 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
     pub fn create_region_hierarchy(&self, rh: &RH) {
         for child_rh in rh.sub.iter() {
             self.create_region_hierarchy(child_rh);
-            self.infcx.tcx.region_maps.record_encl_scope(child_rh.id, rh.id);
+            self.infcx.tcx.region_maps.record_encl_scope(
+                CodeExtent::from_node_id(child_rh.id),
+                CodeExtent::from_node_id(rh.id));
         }
     }
 
@@ -321,12 +323,12 @@ pub fn t_rptr_late_bound_with_debruijn(&self,
     }
 
     pub fn t_rptr_scope(&self, id: ast::NodeId) -> Ty<'tcx> {
-        ty::mk_imm_rptr(self.infcx.tcx, ty::ReScope(id), ty::mk_int())
+        ty::mk_imm_rptr(self.infcx.tcx, ty::ReScope(CodeExtent::from_node_id(id)), ty::mk_int())
     }
 
     pub fn re_free(&self, nid: ast::NodeId, id: uint) -> ty::Region {
-        ty::ReFree(ty::FreeRegion {scope_id: nid,
-                                   bound_region: ty::BrAnon(id)})
+        ty::ReFree(ty::FreeRegion { scope: CodeExtent::from_node_id(nid),
+                                    bound_region: ty::BrAnon(id)})
     }
 
     pub fn t_rptr_free(&self, nid: ast::NodeId, id: uint) -> Ty<'tcx> {
index d6124736586a5487af435361cfa845f01e29efe5..b0235be7497eae95dd301aee4e83c1409833ed44 100644 (file)
@@ -26,6 +26,7 @@
 use trans::common::{Block, FunctionContext, ExprId, NodeInfo};
 use trans::debuginfo;
 use trans::glue;
+use middle::region;
 use trans::type_::Type;
 use middle::ty::{mod, Ty};
 use std::fmt;
@@ -137,7 +138,8 @@ fn push_ast_cleanup_scope(&self, debug_loc: NodeInfo) {
             assert_eq!(self.ccx
                            .tcx()
                            .region_maps
-                           .opt_encl_scope(debug_loc.id),
+                           .opt_encl_scope(region::CodeExtent::from_node_id(debug_loc.id))
+                           .map(|s|s.node_id()),
                        top_scope);
         }
 
@@ -1096,7 +1098,7 @@ pub fn temporary_scope(tcx: &ty::ctxt,
                        -> ScopeId {
     match tcx.region_maps.temporary_scope(id) {
         Some(scope) => {
-            let r = AstScope(scope);
+            let r = AstScope(scope.node_id());
             debug!("temporary_scope({}) = {}", id, r);
             r
         }
@@ -1110,7 +1112,7 @@ pub fn temporary_scope(tcx: &ty::ctxt,
 pub fn var_scope(tcx: &ty::ctxt,
                  id: ast::NodeId)
                  -> ScopeId {
-    let r = AstScope(tcx.region_maps.var_scope(id));
+    let r = AstScope(tcx.region_maps.var_scope(id).node_id());
     debug!("var_scope({}) = {}", id, r);
     r
 }
index 9cd249f1e005dd106cd2114197899591de6696a8..235805a7c8308bf62e9e95cd805c6d9ea9ecd2f2 100644 (file)
@@ -21,6 +21,7 @@
 use middle::def;
 use middle::lang_items::LangItem;
 use middle::mem_categorization as mc;
+use middle::region;
 use middle::subst;
 use middle::subst::{Subst, Substs};
 use trans::base;
@@ -490,7 +491,7 @@ fn is_method_call(&self, id: ast::NodeId) -> bool {
         self.tcx().method_map.borrow().contains_key(&typeck::MethodCall::expr(id))
     }
 
-    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId> {
+    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent> {
         self.tcx().region_maps.temporary_scope(rvalue_id)
     }