Skip to content

Commit

Permalink
Auto merge of #39927 - nikomatsakis:incr-comp-skip-borrowck-2, r=eddyb
Browse files Browse the repository at this point in the history
transition borrowck to visit all **bodies** and not item-likes

This is a better structure for incremental compilation and also more compatible with the eventual borrowck mir. It also fixes #38520 as a drive-by fix.

r? @eddyb
  • Loading branch information
bors committed Mar 3, 2017
2 parents c0b7112 + d572aa2 commit 06c63f6
Show file tree
Hide file tree
Showing 34 changed files with 266 additions and 401 deletions.
20 changes: 6 additions & 14 deletions src/librustc/cfg/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ struct LoopScope {
}

pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
body: &hir::Expr) -> CFG {
body: &hir::Body) -> CFG {
let mut graph = graph::Graph::new();
let entry = graph.add_node(CFGNodeData::Entry);

Expand All @@ -43,26 +43,18 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let fn_exit = graph.add_node(CFGNodeData::Exit);
let body_exit;

// Find the function this expression is from.
let mut node_id = body.id;
loop {
let node = tcx.hir.get(node_id);
if hir::map::blocks::FnLikeNode::from_node(node).is_some() {
break;
}
let parent = tcx.hir.get_parent_node(node_id);
assert!(node_id != parent);
node_id = parent;
}
// Find the tables for this body.
let owner_def_id = tcx.hir.local_def_id(tcx.hir.body_owner(body.id()));
let tables = tcx.item_tables(owner_def_id);

let mut cfg_builder = CFGBuilder {
tcx: tcx,
tables: tcx.item_tables(tcx.hir.local_def_id(node_id)),
tables: tables,
graph: graph,
fn_exit: fn_exit,
loop_scopes: Vec::new()
};
body_exit = cfg_builder.expr(body, entry);
body_exit = cfg_builder.expr(&body.value, entry);
cfg_builder.add_contained_edge(body_exit, fn_exit);
let CFGBuilder {graph, ..} = cfg_builder;
CFG {graph: graph,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/cfg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub type CFGEdge = graph::Edge<CFGEdgeData>;

impl CFG {
pub fn new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
body: &hir::Expr) -> CFG {
body: &hir::Body) -> CFG {
construct::construct(tcx, body)
}

Expand Down
6 changes: 6 additions & 0 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,10 @@ pub enum DepNode<D: Clone + Debug> {

// Represents the MIR for a fn; also used as the task node for
// things read/modify that MIR.
MirKrate,
Mir(D),

BorrowCheckKrate,
BorrowCheck(D),
RvalueCheck(D),
Reachability,
Expand All @@ -114,6 +116,7 @@ pub enum DepNode<D: Clone + Debug> {
SizedConstraint(D),
AssociatedItemDefIds(D),
InherentImpls(D),
TypeckBodiesKrate,
TypeckTables(D),
UsedTraitImports(D),
MonomorphicConstEval(D),
Expand Down Expand Up @@ -209,6 +212,9 @@ impl<D: Clone + Debug> DepNode<D> {

match *self {
Krate => Some(Krate),
BorrowCheckKrate => Some(BorrowCheckKrate),
MirKrate => Some(MirKrate),
TypeckBodiesKrate => Some(TypeckBodiesKrate),
CollectLanguageItems => Some(CollectLanguageItems),
CheckStaticRecursion => Some(CheckStaticRecursion),
ResolveLifetimes => Some(ResolveLifetimes),
Expand Down
1 change: 1 addition & 0 deletions src/librustc/dep_graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ pub use self::dep_node::WorkProductId;
pub use self::graph::DepGraph;
pub use self::graph::WorkProduct;
pub use self::query::DepGraphQuery;
pub use self::visit::visit_all_bodies_in_krate;
pub use self::visit::visit_all_item_likes_in_krate;
pub use self::raii::DepTask;
10 changes: 10 additions & 0 deletions src/librustc/dep_graph/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,13 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>
};
krate.visit_all_item_likes(&mut tracking_visitor)
}

pub fn visit_all_bodies_in_krate<'a, 'tcx, C>(tcx: TyCtxt<'a, 'tcx, 'tcx>, callback: C)
where C: Fn(/* body_owner */ DefId, /* body id */ hir::BodyId),
{
let krate = tcx.hir.krate();
for &body_id in &krate.body_ids {
let body_owner_def_id = tcx.hir.body_owner_def_id(body_id);
callback(body_owner_def_id, body_id);
}
}
16 changes: 13 additions & 3 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ use hir::map::definitions::DefPathData;
use hir::def_id::{DefIndex, DefId};
use hir::def::{Def, PathResolution};
use session::Session;
use util::nodemap::{DefIdMap, NodeMap, FxHashMap};
use util::nodemap::{DefIdMap, NodeMap};

use std::collections::BTreeMap;
use std::iter;
Expand Down Expand Up @@ -78,7 +78,7 @@ pub struct LoweringContext<'a> {

trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem>,
impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
bodies: FxHashMap<hir::BodyId, hir::Body>,
bodies: BTreeMap<hir::BodyId, hir::Body>,

trait_impls: BTreeMap<DefId, Vec<NodeId>>,
trait_default_impl: BTreeMap<DefId, NodeId>,
Expand Down Expand Up @@ -118,7 +118,7 @@ pub fn lower_crate(sess: &Session,
items: BTreeMap::new(),
trait_items: BTreeMap::new(),
impl_items: BTreeMap::new(),
bodies: FxHashMap(),
bodies: BTreeMap::new(),
trait_impls: BTreeMap::new(),
trait_default_impl: BTreeMap::new(),
loop_scopes: Vec::new(),
Expand Down Expand Up @@ -196,6 +196,7 @@ impl<'a> LoweringContext<'a> {
let module = self.lower_mod(&c.module);
let attrs = self.lower_attrs(&c.attrs);
let exported_macros = c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect();
let body_ids = body_ids(&self.bodies);

hir::Crate {
module: module,
Expand All @@ -206,6 +207,7 @@ impl<'a> LoweringContext<'a> {
trait_items: self.trait_items,
impl_items: self.impl_items,
bodies: self.bodies,
body_ids: body_ids,
trait_impls: self.trait_impls,
trait_default_impl: self.trait_default_impl,
}
Expand Down Expand Up @@ -2524,3 +2526,11 @@ impl<'a> LoweringContext<'a> {
}
}
}

fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body>) -> Vec<hir::BodyId> {
// Sorting by span ensures that we get things in order within a
// file, and also puts the files in a sensible order.
let mut body_ids: Vec<_> = bodies.keys().cloned().collect();
body_ids.sort_by_key(|b| bodies[b].value.span);
body_ids
}
1 change: 1 addition & 0 deletions src/librustc/hir/map/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
TyKind::ImplTrait(..) => {
self.create_def(ty.id, DefPathData::ImplTrait);
}
TyKind::Typeof(ref expr) => self.visit_ast_const_integer(expr),
_ => {}
}
visit::walk_ty(self, ty);
Expand Down
8 changes: 6 additions & 2 deletions src/librustc/hir/map/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,9 @@ pub enum DefPathData {
/// Pattern binding
Binding(InternedString),
/// An `impl Trait` type node.
ImplTrait
ImplTrait,
/// A `typeof` type node.
Typeof,
}

impl Definitions {
Expand Down Expand Up @@ -387,7 +389,8 @@ impl DefPathData {
ClosureExpr |
StructCtor |
Initializer |
ImplTrait => None
ImplTrait |
Typeof => None
}
}

Expand Down Expand Up @@ -415,6 +418,7 @@ impl DefPathData {
StructCtor => "{{constructor}}",
Initializer => "{{initializer}}",
ImplTrait => "{{impl-Trait}}",
Typeof => "{{typeof}}",
};

Symbol::intern(s).as_str()
Expand Down
29 changes: 17 additions & 12 deletions src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,43 +168,48 @@ impl<'hir> MapEntry<'hir> {
})
}

fn is_body_owner(self, node_id: NodeId) -> bool {
fn associated_body(self) -> Option<BodyId> {
match self {
EntryItem(_, item) => {
match item.node {
ItemConst(_, body) |
ItemStatic(.., body) |
ItemFn(_, _, _, _, _, body) => body.node_id == node_id,
_ => false
ItemFn(_, _, _, _, _, body) => Some(body),
_ => None,
}
}

EntryTraitItem(_, item) => {
match item.node {
TraitItemKind::Const(_, Some(body)) |
TraitItemKind::Method(_, TraitMethod::Provided(body)) => {
body.node_id == node_id
}
_ => false
TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body),
_ => None
}
}

EntryImplItem(_, item) => {
match item.node {
ImplItemKind::Const(_, body) |
ImplItemKind::Method(_, body) => body.node_id == node_id,
_ => false
ImplItemKind::Method(_, body) => Some(body),
_ => None,
}
}

EntryExpr(_, expr) => {
match expr.node {
ExprClosure(.., body, _) => body.node_id == node_id,
_ => false
ExprClosure(.., body, _) => Some(body),
_ => None,
}
}

_ => false
_ => None
}
}

fn is_body_owner(self, node_id: NodeId) -> bool {
match self.associated_body() {
Some(b) => b.node_id == node_id,
None => false,
}
}
}
Expand Down
11 changes: 8 additions & 3 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub use self::PathParameters::*;

use hir::def::Def;
use hir::def_id::DefId;
use util::nodemap::{NodeMap, FxHashMap, FxHashSet};
use util::nodemap::{NodeMap, FxHashSet};

use syntax_pos::{Span, ExpnId, DUMMY_SP};
use syntax::codemap::{self, Spanned};
Expand Down Expand Up @@ -409,10 +409,15 @@ pub struct Crate {

pub trait_items: BTreeMap<TraitItemId, TraitItem>,
pub impl_items: BTreeMap<ImplItemId, ImplItem>,
pub bodies: FxHashMap<BodyId, Body>,

pub bodies: BTreeMap<BodyId, Body>,
pub trait_impls: BTreeMap<DefId, Vec<NodeId>>,
pub trait_default_impl: BTreeMap<DefId, NodeId>,

/// A list of the body ids written out in the order in which they
/// appear in the crate. If you're going to process all the bodies
/// in the crate, you should iterate over this list rather than the keys
/// of bodies.
pub body_ids: Vec<BodyId>,
}

impl Crate {
Expand Down
6 changes: 5 additions & 1 deletion src/librustc/middle/free_region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use ty::{self, TyCtxt, FreeRegion, Region};
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>
Expand All @@ -30,6 +30,10 @@ impl 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>])
{
Expand Down
24 changes: 6 additions & 18 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand All @@ -267,6 +272,7 @@ impl<'tcx> TypeckTables<'tcx> {
lints: lint::LintTable::new(),
used_trait_imports: DefIdSet(),
tainted_by_errors: false,
free_region_map: FreeRegionMap::new(),
}
}

Expand Down Expand Up @@ -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>,

Expand Down Expand Up @@ -645,16 +644,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
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)
}
Expand Down Expand Up @@ -707,7 +696,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
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),
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/ty/item_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
data @ DefPathData::MacroDef(..) |
data @ DefPathData::ClosureExpr |
data @ DefPathData::Binding(..) |
data @ DefPathData::ImplTrait => {
data @ DefPathData::ImplTrait |
data @ DefPathData::Typeof => {
let parent_def_id = self.parent_def_id(def_id).unwrap();
self.push_item_path(buffer, parent_def_id);
buffer.push(&data.as_interned_str());
Expand Down
11 changes: 11 additions & 0 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2602,6 +2602,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
dep_graph::visit_all_item_likes_in_krate(self.global_tcx(), dep_node_fn, visitor);
}

/// Invokes `callback` for each body in the krate. This will
/// create a read edge from `DepNode::Krate` to the current task;
/// it is meant to be run in the context of some global task like
/// `BorrowckCrate`. The callback would then create a task like
/// `BorrowckBody(DefId)` to process each individual item.
pub fn visit_all_bodies_in_krate<C>(self, callback: C)
where C: Fn(/* body_owner */ DefId, /* body id */ hir::BodyId),
{
dep_graph::visit_all_bodies_in_krate(self.global_tcx(), callback)
}

/// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err`
/// with the name of the crate containing the impl.
pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> {
Expand Down
Loading

0 comments on commit 06c63f6

Please sign in to comment.