Skip to content

Commit b3a482c

Browse files
committed
move the FreeRegionMap into TypeckTables
1 parent e1cb9ba commit b3a482c

File tree

7 files changed

+75
-57
lines changed

7 files changed

+75
-57
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 & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ pub struct TypeckTables<'tcx> {
248248
/// If any errors occurred while type-checking this body,
249249
/// this field will be set to `true`.
250250
pub tainted_by_errors: bool,
251+
252+
/// Stores the free-region relationships that were deduced from
253+
/// its where clauses and parameter types. These are then
254+
/// read-again by borrowck.
255+
pub free_region_map: FreeRegionMap,
251256
}
252257

253258
impl<'tcx> TypeckTables<'tcx> {
@@ -267,6 +272,7 @@ impl<'tcx> TypeckTables<'tcx> {
267272
lints: lint::LintTable::new(),
268273
used_trait_imports: DefIdSet(),
269274
tainted_by_errors: false,
275+
free_region_map: FreeRegionMap::new(),
270276
}
271277
}
272278

@@ -414,13 +420,6 @@ pub struct GlobalCtxt<'tcx> {
414420

415421
pub region_maps: RegionMaps,
416422

417-
// For each fn declared in the local crate, type check stores the
418-
// free-region relationships that were deduced from its where
419-
// clauses and parameter types. These are then read-again by
420-
// borrowck. (They are not used during trans, and hence are not
421-
// serialized or needed for cross-crate fns.)
422-
free_region_maps: RefCell<NodeMap<FreeRegionMap>>,
423-
424423
pub hir: hir_map::Map<'tcx>,
425424
pub maps: maps::Maps<'tcx>,
426425

@@ -645,16 +644,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
645644
interned
646645
}
647646

648-
pub fn store_free_region_map(self, id: NodeId, map: FreeRegionMap) {
649-
if self.free_region_maps.borrow_mut().insert(id, map).is_some() {
650-
bug!("Tried to overwrite interned FreeRegionMap for NodeId {:?}", id)
651-
}
652-
}
653-
654-
pub fn free_region_map(self, id: NodeId) -> FreeRegionMap {
655-
self.free_region_maps.borrow()[&id].clone()
656-
}
657-
658647
pub fn lift<T: ?Sized + Lift<'tcx>>(self, value: &T) -> Option<T::Lifted> {
659648
value.lift_to_tcx(self)
660649
}
@@ -707,7 +696,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
707696
types: common_types,
708697
named_region_map: named_region_map,
709698
region_maps: region_maps,
710-
free_region_maps: RefCell::new(FxHashMap()),
711699
variance_computed: Cell::new(false),
712700
trait_map: resolutions.trait_map,
713701
fulfilled_predicates: RefCell::new(fulfilled_predicates),

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
@@ -120,6 +120,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
120120
rcx.visit_region_obligations(id);
121121
}
122122
rcx.resolve_regions_and_report_errors();
123+
124+
assert!(self.tables.borrow().free_region_map.is_empty());
125+
self.tables.borrow_mut().free_region_map = rcx.free_region_map;
123126
}
124127

125128
/// Region checking during the WF phase for items. `wf_tys` are the
@@ -154,10 +157,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
154157

155158
rcx.resolve_regions_and_report_errors();
156159

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

src/librustc_typeck/check/writeback.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5050
wbcx.visit_type_nodes();
5151
wbcx.visit_cast_types();
5252
wbcx.visit_lints();
53+
wbcx.visit_free_region_map();
5354

5455
let used_trait_imports = mem::replace(&mut self.tables.borrow_mut().used_trait_imports,
5556
DefIdSet());
@@ -274,6 +275,10 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
274275
self.fcx.tables.borrow_mut().lints.transfer(&mut self.tables.lints);
275276
}
276277

278+
fn visit_free_region_map(&mut self) {
279+
self.tables.free_region_map = self.fcx.tables.borrow().free_region_map.clone();
280+
}
281+
277282
fn visit_anon_types(&mut self) {
278283
let gcx = self.tcx().global_tcx();
279284
for (&node_id, &concrete_ty) in self.fcx.anon_types.borrow().iter() {

0 commit comments

Comments
 (0)