Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transition borrowck to visit all **bodies** and not item-likes #39927

Merged
merged 16 commits into from
Mar 3, 2017
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
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> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have at least two, if not three, reimplementations of this, seems so obvious in retrospect!

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
11 changes: 11 additions & 0 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2613,6 +2613,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
5 changes: 3 additions & 2 deletions src/librustc_borrowck/borrowck/fragments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use rustc::middle::mem_categorization as mc;
use std::mem;
use std::rc::Rc;
use syntax::ast;
use syntax_pos::{Span, DUMMY_SP};
use syntax_pos::DUMMY_SP;

#[derive(PartialEq, Eq, PartialOrd, Ord)]
enum Fragment {
Expand Down Expand Up @@ -200,14 +200,15 @@ impl FragmentSets {

pub fn instrument_move_fragments<'a, 'tcx>(this: &MoveData<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
sp: Span,
id: ast::NodeId) {
let span_err = tcx.hir.attrs(id).iter()
.any(|a| a.check_name("rustc_move_fragments"));
let print = tcx.sess.opts.debugging_opts.print_move_fragments;

if !span_err && !print { return; }

let sp = tcx.hir.span(id);

let instrument_all_paths = |kind, vec_rc: &Vec<MovePathIndex>| {
for (i, mpi) in vec_rc.iter().enumerate() {
let lp = || this.path_loan_path(*mpi);
Expand Down
Loading