Skip to content

Commit 22f91ca

Browse files
committed
move the FreeRegionMap into TypeckTables
1 parent 9f1762a commit 22f91ca

File tree

7 files changed

+79
-58
lines changed

7 files changed

+79
-58
lines changed

src/librustc/middle/free_region.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use ty::{self, TyCtxt, FreeRegion, Region};
1919
use ty::wf::ImpliedBound;
2020
use rustc_data_structures::transitive_relation::TransitiveRelation;
2121

22-
#[derive(Clone)]
22+
#[derive(Clone, RustcEncodable, RustcDecodable)]
2323
pub struct FreeRegionMap {
2424
// Stores the relation `a < b`, where `a` and `b` are regions.
2525
relation: TransitiveRelation<Region>
@@ -30,6 +30,10 @@ impl FreeRegionMap {
3030
FreeRegionMap { relation: TransitiveRelation::new() }
3131
}
3232

33+
pub fn is_empty(&self) -> bool {
34+
self.relation.is_empty()
35+
}
36+
3337
pub fn relate_free_regions_from_implied_bounds<'tcx>(&mut self,
3438
implied_bounds: &[ImpliedBound<'tcx>])
3539
{

src/librustc/ty/context.rs

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,11 @@ pub struct TypeckTables<'tcx> {
242242

243243
/// Lints for the body of this fn generated by typeck.
244244
pub lints: lint::LintTable,
245+
246+
/// Stores the free-region relationships that were deduced from
247+
/// its where clauses and parameter types. These are then
248+
/// read-again by borrowck.
249+
pub free_region_map: FreeRegionMap,
245250
}
246251

247252
impl<'tcx> TypeckTables<'tcx> {
@@ -259,6 +264,7 @@ impl<'tcx> TypeckTables<'tcx> {
259264
fru_field_types: NodeMap(),
260265
cast_kinds: NodeMap(),
261266
lints: lint::LintTable::new(),
267+
free_region_map: FreeRegionMap::new(),
262268
}
263269
}
264270

@@ -406,14 +412,6 @@ pub struct GlobalCtxt<'tcx> {
406412

407413
pub region_maps: RegionMaps,
408414

409-
// For each fn declared in the local crate, type check stores the
410-
// free-region relationships that were deduced from its where
411-
// clauses and parameter types. These are then read-again by
412-
// borrowck. (They are not used during trans, and hence are not
413-
// serialized or needed for cross-crate fns.)
414-
free_region_maps: RefCell<NodeMap<FreeRegionMap>>,
415-
// FIXME: jroesch make this a refcell
416-
417415
pub tables: RefCell<DepTrackingMap<maps::TypeckTables<'tcx>>>,
418416

419417
/// Maps from a trait item to the trait item "descriptor"
@@ -706,16 +704,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
706704
interned
707705
}
708706

709-
pub fn store_free_region_map(self, id: NodeId, map: FreeRegionMap) {
710-
if self.free_region_maps.borrow_mut().insert(id, map).is_some() {
711-
bug!("Tried to overwrite interned FreeRegionMap for NodeId {:?}", id)
712-
}
713-
}
714-
715-
pub fn free_region_map(self, id: NodeId) -> FreeRegionMap {
716-
self.free_region_maps.borrow()[&id].clone()
717-
}
718-
719707
pub fn lift<T: ?Sized + Lift<'tcx>>(self, value: &T) -> Option<T::Lifted> {
720708
value.lift_to_tcx(self)
721709
}
@@ -762,7 +750,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
762750
types: common_types,
763751
named_region_map: named_region_map,
764752
region_maps: region_maps,
765-
free_region_maps: RefCell::new(FxHashMap()),
766753
item_variance_map: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
767754
variance_computed: Cell::new(false),
768755
sess: s,

src/librustc_borrowck/borrowck/mod.rs

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,12 @@ use rustc::middle::dataflow::DataFlowOperator;
3232
use rustc::middle::dataflow::KillFrom;
3333
use rustc::hir::def_id::DefId;
3434
use rustc::middle::expr_use_visitor as euv;
35-
use rustc::middle::free_region::FreeRegionMap;
3635
use rustc::middle::mem_categorization as mc;
3736
use rustc::middle::mem_categorization::Categorization;
3837
use rustc::middle::region;
3938
use rustc::ty::{self, TyCtxt};
4039

4140
use std::fmt;
42-
use std::mem;
4341
use std::rc::Rc;
4442
use std::hash::{Hash, Hasher};
4543
use syntax::ast;
@@ -72,9 +70,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BorrowckCtxt<'a, 'tcx> {
7270
match fk {
7371
FnKind::ItemFn(..) |
7472
FnKind::Method(..) => {
75-
self.with_temp_region_map(id, |this| {
76-
borrowck_fn(this, fk, fd, b, s, id, fk.attrs())
77-
});
73+
borrowck_fn(self, fk, fd, b, s, id, fk.attrs())
7874
}
7975

8076
FnKind::Closure(..) => {
@@ -105,7 +101,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BorrowckCtxt<'a, 'tcx> {
105101
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
106102
let mut bccx = BorrowckCtxt {
107103
tcx: tcx,
108-
free_region_map: FreeRegionMap::new(),
104+
tables: None,
109105
stats: BorrowStats {
110106
loaned_paths_same: 0,
111107
loaned_paths_imm: 0,
@@ -167,12 +163,15 @@ fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
167163
attributes: &[ast::Attribute]) {
168164
debug!("borrowck_fn(id={})", id);
169165

166+
assert!(this.tables.is_none());
167+
let owner_def_id = this.tcx.hir.local_def_id(this.tcx.hir.body_owner(body_id));
168+
let tables = this.tcx.item_tables(owner_def_id);
169+
this.tables = Some(tables);
170+
170171
let body = this.tcx.hir.body(body_id);
171172

172173
if attributes.iter().any(|item| item.check_name("rustc_mir_borrowck")) {
173-
this.with_temp_region_map(id, |this| {
174-
mir::borrowck_mir(this, id, attributes)
175-
});
174+
mir::borrowck_mir(this, id, attributes);
176175
}
177176

178177
let cfg = cfg::CFG::new(this.tcx, &body.value);
@@ -191,6 +190,8 @@ fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
191190

192191
check_loans::check_loans(this, &loan_dfcx, &flowed_moves, &all_loans[..], body);
193192

193+
this.tables = None;
194+
194195
intravisit::walk_fn(this, fk, decl, body_id, sp, id);
195196
}
196197

@@ -248,7 +249,7 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>(
248249

249250
let mut bccx = BorrowckCtxt {
250251
tcx: tcx,
251-
free_region_map: FreeRegionMap::new(),
252+
tables: None,
252253
stats: BorrowStats {
253254
loaned_paths_same: 0,
254255
loaned_paths_imm: 0,
@@ -267,17 +268,9 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>(
267268
pub struct BorrowckCtxt<'a, 'tcx: 'a> {
268269
tcx: TyCtxt<'a, 'tcx, 'tcx>,
269270

270-
// Hacky. As we visit various fns, we have to load up the
271-
// free-region map for each one. This map is computed by during
272-
// typeck for each fn item and stored -- closures just use the map
273-
// from the fn item that encloses them. Since we walk the fns in
274-
// order, we basically just overwrite this field as we enter a fn
275-
// item and restore it afterwards in a stack-like fashion. Then
276-
// the borrow checking code can assume that `free_region_map` is
277-
// always the correct map for the current fn. Feels like it'd be
278-
// better to just recompute this, rather than store it, but it's a
279-
// bit of a pain to factor that code out at the moment.
280-
free_region_map: FreeRegionMap,
271+
// tables for the current thing we are checking; set to
272+
// Some in `borrowck_fn` and cleared later
273+
tables: Option<&'a ty::TypeckTables<'tcx>>,
281274

282275
// Statistics:
283276
stats: BorrowStats
@@ -574,19 +567,13 @@ pub enum MovedValueUseKind {
574567
// Misc
575568

576569
impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
577-
fn with_temp_region_map<F>(&mut self, id: ast::NodeId, f: F)
578-
where F: for <'b> FnOnce(&'b mut BorrowckCtxt<'a, 'tcx>)
579-
{
580-
let new_free_region_map = self.tcx.free_region_map(id);
581-
let old_free_region_map = mem::replace(&mut self.free_region_map, new_free_region_map);
582-
f(self);
583-
self.free_region_map = old_free_region_map;
584-
}
585-
586-
pub fn is_subregion_of(&self, r_sub: &'tcx ty::Region, r_sup: &'tcx ty::Region)
570+
pub fn is_subregion_of(&self,
571+
r_sub: &'tcx ty::Region,
572+
r_sup: &'tcx ty::Region)
587573
-> bool
588574
{
589-
self.free_region_map.is_subregion_of(self.tcx, r_sub, r_sup)
575+
self.tables.unwrap().free_region_map
576+
.is_subregion_of(self.tcx, r_sub, r_sup)
590577
}
591578

592579
pub fn report(&self, err: BckError<'tcx>) {

src/librustc_data_structures/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#![feature(shared)]
2929
#![feature(collections_range)]
3030
#![feature(collections_bound)]
31+
#![cfg_attr(stage0,feature(field_init_shorthand))]
3132
#![feature(nonzero)]
3233
#![feature(rustc_private)]
3334
#![feature(staged_api)]

src/librustc_data_structures/transitive_relation.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
use bitvec::BitMatrix;
12+
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
1213
use std::cell::RefCell;
1314
use std::fmt::Debug;
1415
use std::mem;
@@ -36,10 +37,10 @@ pub struct TransitiveRelation<T: Debug + PartialEq> {
3637
closure: RefCell<Option<BitMatrix>>,
3738
}
3839

39-
#[derive(Clone, PartialEq, PartialOrd)]
40+
#[derive(Clone, PartialEq, PartialOrd, RustcEncodable, RustcDecodable)]
4041
struct Index(usize);
4142

42-
#[derive(Clone, PartialEq)]
43+
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
4344
struct Edge {
4445
source: Index,
4546
target: Index,
@@ -54,6 +55,10 @@ impl<T: Debug + PartialEq> TransitiveRelation<T> {
5455
}
5556
}
5657

58+
pub fn is_empty(&self) -> bool {
59+
self.edges.is_empty()
60+
}
61+
5762
fn index(&self, a: &T) -> Option<Index> {
5863
self.elements.iter().position(|e| *e == *a).map(Index)
5964
}
@@ -305,6 +310,30 @@ fn pare_down(candidates: &mut Vec<usize>, closure: &BitMatrix) {
305310
}
306311
}
307312

313+
impl<T> Encodable for TransitiveRelation<T>
314+
where T: Encodable + Debug + PartialEq
315+
{
316+
fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
317+
s.emit_struct("TransitiveRelation", 2, |s| {
318+
s.emit_struct_field("elements", 0, |s| self.elements.encode(s))?;
319+
s.emit_struct_field("edges", 1, |s| self.edges.encode(s))?;
320+
Ok(())
321+
})
322+
}
323+
}
324+
325+
impl<T> Decodable for TransitiveRelation<T>
326+
where T: Decodable + Debug + PartialEq
327+
{
328+
fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
329+
d.read_struct("TransitiveRelation", 2, |d| {
330+
let elements = d.read_struct_field("elements", 0, |d| Decodable::decode(d))?;
331+
let edges = d.read_struct_field("edges", 1, |d| Decodable::decode(d))?;
332+
Ok(TransitiveRelation { elements, edges, closure: RefCell::new(None) })
333+
})
334+
}
335+
}
336+
308337
#[test]
309338
fn test_one_step() {
310339
let mut relation = TransitiveRelation::new();

src/librustc_typeck/check/regionck.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
122122
rcx.visit_region_obligations(id);
123123
}
124124
rcx.resolve_regions_and_report_errors();
125+
126+
assert!(self.tables.borrow().free_region_map.is_empty());
127+
self.tables.borrow_mut().free_region_map = rcx.free_region_map;
125128
}
126129

127130
/// Region checking during the WF phase for items. `wf_tys` are the
@@ -156,10 +159,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
156159

157160
rcx.resolve_regions_and_report_errors();
158161

159-
// For the top-level fn, store the free-region-map. We don't store
160-
// any map for closures; they just share the same map as the
161-
// function that created them.
162-
self.tcx.store_free_region_map(fn_id, rcx.free_region_map);
162+
// In this mode, we also copy the free-region-map into the
163+
// tables of the enclosing fcx. In the other regionck modes
164+
// (e.g., `regionck_item`), we don't have an enclosing tables.
165+
assert!(self.tables.borrow().free_region_map.is_empty());
166+
self.tables.borrow_mut().free_region_map = rcx.free_region_map;
163167
}
164168
}
165169

src/librustc_typeck/check/writeback.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5454
wbcx.visit_type_nodes();
5555
wbcx.visit_cast_types();
5656
wbcx.visit_lints();
57+
wbcx.visit_free_region_map();
5758

5859
let tables = self.tcx.alloc_tables(wbcx.tables);
5960
self.tcx.tables.borrow_mut().insert(item_def_id, tables);
@@ -316,6 +317,14 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
316317
self.fcx.tables.borrow_mut().lints.transfer(&mut self.tables.lints);
317318
}
318319

320+
fn visit_free_region_map(&mut self) {
321+
if self.fcx.writeback_errors.get() {
322+
return
323+
}
324+
325+
self.tables.free_region_map = self.fcx.tables.borrow().free_region_map.clone();
326+
}
327+
319328
fn visit_anon_types(&self) {
320329
if self.fcx.writeback_errors.get() {
321330
return

0 commit comments

Comments
 (0)