]> git.lizzy.rs Git - rust.git/commitdiff
move the `FreeRegionMap` into `TypeckTables`
authorNiko Matsakis <niko@alum.mit.edu>
Thu, 16 Feb 2017 17:46:44 +0000 (12:46 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Tue, 28 Feb 2017 13:43:47 +0000 (08:43 -0500)
src/librustc/middle/free_region.rs
src/librustc/ty/context.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_data_structures/lib.rs
src/librustc_data_structures/transitive_relation.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/writeback.rs

index bd35bfc9829a5c08541a83d35585a706f7f873ce..cdb081ab40098655ab325fec2aa5bc29a0c2a3d2 100644 (file)
@@ -19,7 +19,7 @@
 use ty::wf::ImpliedBound;
 use rustc_data_structures::transitive_relation::TransitiveRelation;
 
-#[derive(Clone)]
+#[derive(Clone, RustcEncodable, RustcDecodable)]
 pub struct FreeRegionMap {
     // Stores the relation `a < b`, where `a` and `b` are regions.
     relation: TransitiveRelation<Region>
@@ -30,6 +30,10 @@ pub fn new() -> FreeRegionMap {
         FreeRegionMap { relation: TransitiveRelation::new() }
     }
 
+    pub fn is_empty(&self) -> bool {
+        self.relation.is_empty()
+    }
+
     pub fn relate_free_regions_from_implied_bounds<'tcx>(&mut self,
                                                         implied_bounds: &[ImpliedBound<'tcx>])
     {
index 6961e0da362a5f7835ca0decce0e93c9c603fe9e..a0aeb4107c156c17dd4c19cea5762942fc517a9d 100644 (file)
@@ -248,6 +248,11 @@ pub struct TypeckTables<'tcx> {
     /// If any errors occurred while type-checking this body,
     /// this field will be set to `true`.
     pub tainted_by_errors: bool,
+
+    /// Stores the free-region relationships that were deduced from
+    /// its where clauses and parameter types. These are then
+    /// read-again by borrowck.
+    pub free_region_map: FreeRegionMap,
 }
 
 impl<'tcx> TypeckTables<'tcx> {
@@ -267,6 +272,7 @@ pub fn empty() -> TypeckTables<'tcx> {
             lints: lint::LintTable::new(),
             used_trait_imports: DefIdSet(),
             tainted_by_errors: false,
+            free_region_map: FreeRegionMap::new(),
         }
     }
 
@@ -414,13 +420,6 @@ pub struct GlobalCtxt<'tcx> {
 
     pub region_maps: RegionMaps,
 
-    // For each fn declared in the local crate, type check stores the
-    // free-region relationships that were deduced from its where
-    // clauses and parameter types. These are then read-again by
-    // borrowck. (They are not used during trans, and hence are not
-    // serialized or needed for cross-crate fns.)
-    free_region_maps: RefCell<NodeMap<FreeRegionMap>>,
-
     pub hir: hir_map::Map<'tcx>,
     pub maps: maps::Maps<'tcx>,
 
@@ -645,16 +644,6 @@ pub fn intern_layout(self, layout: Layout) -> &'gcx Layout {
         interned
     }
 
-    pub fn store_free_region_map(self, id: NodeId, map: FreeRegionMap) {
-        if self.free_region_maps.borrow_mut().insert(id, map).is_some() {
-            bug!("Tried to overwrite interned FreeRegionMap for NodeId {:?}", id)
-        }
-    }
-
-    pub fn free_region_map(self, id: NodeId) -> FreeRegionMap {
-        self.free_region_maps.borrow()[&id].clone()
-    }
-
     pub fn lift<T: ?Sized + Lift<'tcx>>(self, value: &T) -> Option<T::Lifted> {
         value.lift_to_tcx(self)
     }
@@ -707,7 +696,6 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             types: common_types,
             named_region_map: named_region_map,
             region_maps: region_maps,
-            free_region_maps: RefCell::new(FxHashMap()),
             variance_computed: Cell::new(false),
             trait_map: resolutions.trait_map,
             fulfilled_predicates: RefCell::new(fulfilled_predicates),
index 46179b31d5cb45bc2c212baad7a898355109e9e0..06133de07576e506affb3eb7892538b9bbe571ee 100644 (file)
 use rustc::middle::dataflow::KillFrom;
 use rustc::hir::def_id::DefId;
 use rustc::middle::expr_use_visitor as euv;
-use rustc::middle::free_region::FreeRegionMap;
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::mem_categorization::Categorization;
 use rustc::middle::region;
 use rustc::ty::{self, TyCtxt};
 
 use std::fmt;
-use std::mem;
 use std::rc::Rc;
 use std::hash::{Hash, Hasher};
 use syntax::ast;
@@ -72,9 +70,7 @@ fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
         match fk {
             FnKind::ItemFn(..) |
             FnKind::Method(..) => {
-                self.with_temp_region_map(id, |this| {
-                    borrowck_fn(this, fk, fd, b, s, id, fk.attrs())
-                });
+                borrowck_fn(self, fk, fd, b, s, id, fk.attrs())
             }
 
             FnKind::Closure(..) => {
@@ -105,7 +101,7 @@ fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let mut bccx = BorrowckCtxt {
         tcx: tcx,
-        free_region_map: FreeRegionMap::new(),
+        tables: None,
         stats: BorrowStats {
             loaned_paths_same: 0,
             loaned_paths_imm: 0,
@@ -167,12 +163,15 @@ fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
                          attributes: &[ast::Attribute]) {
     debug!("borrowck_fn(id={})", id);
 
+    assert!(this.tables.is_none());
+    let owner_def_id = this.tcx.hir.local_def_id(this.tcx.hir.body_owner(body_id));
+    let tables = this.tcx.item_tables(owner_def_id);
+    this.tables = Some(tables);
+
     let body = this.tcx.hir.body(body_id);
 
     if attributes.iter().any(|item| item.check_name("rustc_mir_borrowck")) {
-        this.with_temp_region_map(id, |this| {
-            mir::borrowck_mir(this, id, attributes)
-        });
+        mir::borrowck_mir(this, id, attributes);
     }
 
     let cfg = cfg::CFG::new(this.tcx, &body.value);
@@ -191,6 +190,8 @@ fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
 
     check_loans::check_loans(this, &loan_dfcx, &flowed_moves, &all_loans[..], body);
 
+    this.tables = None;
+
     intravisit::walk_fn(this, fk, decl, body_id, sp, id);
 }
 
@@ -248,7 +249,7 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>(
 
     let mut bccx = BorrowckCtxt {
         tcx: tcx,
-        free_region_map: FreeRegionMap::new(),
+        tables: None,
         stats: BorrowStats {
             loaned_paths_same: 0,
             loaned_paths_imm: 0,
@@ -267,17 +268,9 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>(
 pub struct BorrowckCtxt<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
-    // Hacky. As we visit various fns, we have to load up the
-    // free-region map for each one. This map is computed by during
-    // typeck for each fn item and stored -- closures just use the map
-    // from the fn item that encloses them. Since we walk the fns in
-    // order, we basically just overwrite this field as we enter a fn
-    // item and restore it afterwards in a stack-like fashion. Then
-    // the borrow checking code can assume that `free_region_map` is
-    // always the correct map for the current fn. Feels like it'd be
-    // better to just recompute this, rather than store it, but it's a
-    // bit of a pain to factor that code out at the moment.
-    free_region_map: FreeRegionMap,
+    // tables for the current thing we are checking; set to
+    // Some in `borrowck_fn` and cleared later
+    tables: Option<&'a ty::TypeckTables<'tcx>>,
 
     // Statistics:
     stats: BorrowStats
@@ -574,19 +567,13 @@ pub enum MovedValueUseKind {
 // Misc
 
 impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
-    fn with_temp_region_map<F>(&mut self, id: ast::NodeId, f: F)
-        where F: for <'b> FnOnce(&'b mut BorrowckCtxt<'a, 'tcx>)
-    {
-        let new_free_region_map = self.tcx.free_region_map(id);
-        let old_free_region_map = mem::replace(&mut self.free_region_map, new_free_region_map);
-        f(self);
-        self.free_region_map = old_free_region_map;
-    }
-
-    pub fn is_subregion_of(&self, r_sub: &'tcx ty::Region, r_sup: &'tcx ty::Region)
+    pub fn is_subregion_of(&self,
+                           r_sub: &'tcx ty::Region,
+                           r_sup: &'tcx ty::Region)
                            -> bool
     {
-        self.free_region_map.is_subregion_of(self.tcx, r_sub, r_sup)
+        self.tables.unwrap().free_region_map
+                            .is_subregion_of(self.tcx, r_sub, r_sup)
     }
 
     pub fn report(&self, err: BckError<'tcx>) {
index cf6bf1cf1d4834bb00087658b565b58995f2ce17..3dce4398f3b91838a6eec3ef2a3ae3d93ca02c81 100644 (file)
@@ -28,6 +28,7 @@
 #![feature(shared)]
 #![feature(collections_range)]
 #![feature(collections_bound)]
+#![cfg_attr(stage0,feature(field_init_shorthand))]
 #![feature(nonzero)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
index e09e260afc8d99c0e0fddc6d0c3b6a85f26deb49..2bce7faf08cec45b91c9654ed4244b0d64383ef3 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use bitvec::BitMatrix;
+use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
 use std::cell::RefCell;
 use std::fmt::Debug;
 use std::mem;
@@ -36,10 +37,10 @@ pub struct TransitiveRelation<T: Debug + PartialEq> {
     closure: RefCell<Option<BitMatrix>>,
 }
 
-#[derive(Clone, PartialEq, PartialOrd)]
+#[derive(Clone, PartialEq, PartialOrd, RustcEncodable, RustcDecodable)]
 struct Index(usize);
 
-#[derive(Clone, PartialEq)]
+#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
 struct Edge {
     source: Index,
     target: Index,
@@ -54,6 +55,10 @@ pub fn new() -> TransitiveRelation<T> {
         }
     }
 
+    pub fn is_empty(&self) -> bool {
+        self.edges.is_empty()
+    }
+
     fn index(&self, a: &T) -> Option<Index> {
         self.elements.iter().position(|e| *e == *a).map(Index)
     }
@@ -305,6 +310,30 @@ fn pare_down(candidates: &mut Vec<usize>, closure: &BitMatrix) {
     }
 }
 
+impl<T> Encodable for TransitiveRelation<T>
+    where T: Encodable + Debug + PartialEq
+{
+    fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
+        s.emit_struct("TransitiveRelation", 2, |s| {
+            s.emit_struct_field("elements", 0, |s| self.elements.encode(s))?;
+            s.emit_struct_field("edges", 1, |s| self.edges.encode(s))?;
+            Ok(())
+        })
+    }
+}
+
+impl<T> Decodable for TransitiveRelation<T>
+    where T: Decodable + Debug + PartialEq
+{
+    fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
+        d.read_struct("TransitiveRelation", 2, |d| {
+            let elements = d.read_struct_field("elements", 0, |d| Decodable::decode(d))?;
+            let edges = d.read_struct_field("edges", 1, |d| Decodable::decode(d))?;
+            Ok(TransitiveRelation { elements, edges, closure: RefCell::new(None) })
+        })
+    }
+}
+
 #[test]
 fn test_one_step() {
     let mut relation = TransitiveRelation::new();
index e1067d299fa01b8d3f387e367f65c7435e4c996c..8bfb390bd2a5514d76727cc528c2c6b968c4dec8 100644 (file)
@@ -120,6 +120,9 @@ pub fn regionck_expr(&self, body: &'gcx hir::Body) {
             rcx.visit_region_obligations(id);
         }
         rcx.resolve_regions_and_report_errors();
+
+        assert!(self.tables.borrow().free_region_map.is_empty());
+        self.tables.borrow_mut().free_region_map = rcx.free_region_map;
     }
 
     /// Region checking during the WF phase for items. `wf_tys` are the
@@ -154,10 +157,11 @@ pub fn regionck_fn(&self,
 
         rcx.resolve_regions_and_report_errors();
 
-        // For the top-level fn, store the free-region-map. We don't store
-        // any map for closures; they just share the same map as the
-        // function that created them.
-        self.tcx.store_free_region_map(fn_id, rcx.free_region_map);
+        // In this mode, we also copy the free-region-map into the
+        // tables of the enclosing fcx. In the other regionck modes
+        // (e.g., `regionck_item`), we don't have an enclosing tables.
+        assert!(self.tables.borrow().free_region_map.is_empty());
+        self.tables.borrow_mut().free_region_map = rcx.free_region_map;
     }
 }
 
index 1382ab34ca52048b7ba419a5800913f12649b214..7fffbd14e216056b71596c1a95ec092d9c31a1a7 100644 (file)
@@ -50,6 +50,7 @@ pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body)
         wbcx.visit_type_nodes();
         wbcx.visit_cast_types();
         wbcx.visit_lints();
+        wbcx.visit_free_region_map();
 
         let used_trait_imports = mem::replace(&mut self.tables.borrow_mut().used_trait_imports,
                                               DefIdSet());
@@ -274,6 +275,10 @@ fn visit_lints(&mut self) {
         self.fcx.tables.borrow_mut().lints.transfer(&mut self.tables.lints);
     }
 
+    fn visit_free_region_map(&mut self) {
+        self.tables.free_region_map = self.fcx.tables.borrow().free_region_map.clone();
+    }
+
     fn visit_anon_types(&mut self) {
         let gcx = self.tcx().global_tcx();
         for (&node_id, &concrete_ty) in self.fcx.anon_types.borrow().iter() {