Skip to content

Use hir::ItemLocalId instead of ast::NodeId in rustc::middle::region::CodeExtent. #44171

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

Merged
merged 3 commits into from
Sep 1, 2017
Merged
Changes from all 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
93 changes: 47 additions & 46 deletions src/librustc/cfg/construct.rs
Original file line number Diff line number Diff line change
@@ -12,7 +12,6 @@ use rustc_data_structures::graph;
use cfg::*;
use middle::region::CodeExtent;
use ty::{self, TyCtxt};
use syntax::ast;
use syntax::ptr::P;

use hir::{self, PatKind};
@@ -30,13 +29,13 @@ struct CFGBuilder<'a, 'tcx: 'a> {

#[derive(Copy, Clone)]
struct BlockScope {
block_expr_id: ast::NodeId, // id of breakable block expr node
block_expr_id: hir::ItemLocalId, // id of breakable block expr node
break_index: CFGIndex, // where to go on `break`
}

#[derive(Copy, Clone)]
struct LoopScope {
loop_id: ast::NodeId, // id of loop/while node
loop_id: hir::ItemLocalId, // id of loop/while node
continue_index: CFGIndex, // where to go on a `loop`
break_index: CFGIndex, // where to go on a `break`
}
@@ -70,6 +69,7 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
cfg_builder.add_contained_edge(body_exit, fn_exit);
let CFGBuilder { graph, .. } = cfg_builder;
CFG {
owner_def_id,
graph,
entry,
exit: fn_exit,
@@ -79,10 +79,10 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
fn block(&mut self, blk: &hir::Block, pred: CFGIndex) -> CFGIndex {
if blk.targeted_by_break {
let expr_exit = self.add_ast_node(blk.id, &[]);
let expr_exit = self.add_ast_node(blk.hir_id.local_id, &[]);

self.breakable_block_scopes.push(BlockScope {
block_expr_id: blk.id,
block_expr_id: blk.hir_id.local_id,
break_index: expr_exit,
});

@@ -104,21 +104,22 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {

let expr_exit = self.opt_expr(&blk.expr, stmts_exit);

self.add_ast_node(blk.id, &[expr_exit])
self.add_ast_node(blk.hir_id.local_id, &[expr_exit])
}
}

fn stmt(&mut self, stmt: &hir::Stmt, pred: CFGIndex) -> CFGIndex {
let hir_id = self.tcx.hir.node_to_hir_id(stmt.node.id());
match stmt.node {
hir::StmtDecl(ref decl, id) => {
hir::StmtDecl(ref decl, _) => {
let exit = self.decl(&decl, pred);
self.add_ast_node(id, &[exit])
self.add_ast_node(hir_id.local_id, &[exit])
}

hir::StmtExpr(ref expr, id) |
hir::StmtSemi(ref expr, id) => {
hir::StmtExpr(ref expr, _) |
hir::StmtSemi(ref expr, _) => {
let exit = self.expr(&expr, pred);
self.add_ast_node(id, &[exit])
self.add_ast_node(hir_id.local_id, &[exit])
}
}
}
@@ -140,31 +141,31 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
PatKind::Path(_) |
PatKind::Lit(..) |
PatKind::Range(..) |
PatKind::Wild => self.add_ast_node(pat.id, &[pred]),
PatKind::Wild => self.add_ast_node(pat.hir_id.local_id, &[pred]),

PatKind::Box(ref subpat) |
PatKind::Ref(ref subpat, _) |
PatKind::Binding(.., Some(ref subpat)) => {
let subpat_exit = self.pat(&subpat, pred);
self.add_ast_node(pat.id, &[subpat_exit])
self.add_ast_node(pat.hir_id.local_id, &[subpat_exit])
}

PatKind::TupleStruct(_, ref subpats, _) |
PatKind::Tuple(ref subpats, _) => {
let pats_exit = self.pats_all(subpats.iter(), pred);
self.add_ast_node(pat.id, &[pats_exit])
self.add_ast_node(pat.hir_id.local_id, &[pats_exit])
}

PatKind::Struct(_, ref subpats, _) => {
let pats_exit = self.pats_all(subpats.iter().map(|f| &f.node.pat), pred);
self.add_ast_node(pat.id, &[pats_exit])
self.add_ast_node(pat.hir_id.local_id, &[pats_exit])
}

PatKind::Slice(ref pre, ref vec, ref post) => {
let pre_exit = self.pats_all(pre.iter(), pred);
let vec_exit = self.pats_all(vec.iter(), pre_exit);
let post_exit = self.pats_all(post.iter(), vec_exit);
self.add_ast_node(pat.id, &[post_exit])
self.add_ast_node(pat.hir_id.local_id, &[post_exit])
}
}
}
@@ -180,7 +181,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
match expr.node {
hir::ExprBlock(ref blk) => {
let blk_exit = self.block(&blk, pred);
self.add_ast_node(expr.id, &[blk_exit])
self.add_ast_node(expr.hir_id.local_id, &[blk_exit])
}

hir::ExprIf(ref cond, ref then, None) => {
@@ -200,7 +201,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
//
let cond_exit = self.expr(&cond, pred); // 1
let then_exit = self.expr(&then, cond_exit); // 2
self.add_ast_node(expr.id, &[cond_exit, then_exit]) // 3,4
self.add_ast_node(expr.hir_id.local_id, &[cond_exit, then_exit]) // 3,4
}

hir::ExprIf(ref cond, ref then, Some(ref otherwise)) => {
@@ -221,7 +222,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
let cond_exit = self.expr(&cond, pred); // 1
let then_exit = self.expr(&then, cond_exit); // 2
let else_exit = self.expr(&otherwise, cond_exit); // 3
self.add_ast_node(expr.id, &[then_exit, else_exit]) // 4, 5
self.add_ast_node(expr.hir_id.local_id, &[then_exit, else_exit]) // 4, 5
}

hir::ExprWhile(ref cond, ref body, _) => {
@@ -245,12 +246,12 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
let loopback = self.add_dummy_node(&[pred]); // 1

// Create expr_exit without pred (cond_exit)
let expr_exit = self.add_ast_node(expr.id, &[]); // 3
let expr_exit = self.add_ast_node(expr.hir_id.local_id, &[]); // 3

// The LoopScope needs to be on the loop_scopes stack while evaluating the
// condition and the body of the loop (both can break out of the loop)
self.loop_scopes.push(LoopScope {
loop_id: expr.id,
loop_id: expr.hir_id.local_id,
continue_index: loopback,
break_index: expr_exit
});
@@ -282,9 +283,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
// may cause additional edges.

let loopback = self.add_dummy_node(&[pred]); // 1
let expr_exit = self.add_ast_node(expr.id, &[]); // 2
let expr_exit = self.add_ast_node(expr.hir_id.local_id, &[]); // 2
self.loop_scopes.push(LoopScope {
loop_id: expr.id,
loop_id: expr.hir_id.local_id,
continue_index: loopback,
break_index: expr_exit,
});
@@ -295,7 +296,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
}

hir::ExprMatch(ref discr, ref arms, _) => {
self.match_(expr.id, &discr, &arms, pred)
self.match_(expr.hir_id.local_id, &discr, &arms, pred)
}

hir::ExprBinary(op, ref l, ref r) if op.node.is_lazy() => {
@@ -315,30 +316,30 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
//
let l_exit = self.expr(&l, pred); // 1
let r_exit = self.expr(&r, l_exit); // 2
self.add_ast_node(expr.id, &[l_exit, r_exit]) // 3,4
self.add_ast_node(expr.hir_id.local_id, &[l_exit, r_exit]) // 3,4
}

hir::ExprRet(ref v) => {
let v_exit = self.opt_expr(v, pred);
let b = self.add_ast_node(expr.id, &[v_exit]);
let b = self.add_ast_node(expr.hir_id.local_id, &[v_exit]);
self.add_returning_edge(expr, b);
self.add_unreachable_node()
}

hir::ExprBreak(destination, ref opt_expr) => {
let v = self.opt_expr(opt_expr, pred);
let (scope_id, break_dest) =
let (target_scope, break_dest) =
self.find_scope_edge(expr, destination, ScopeCfKind::Break);
let b = self.add_ast_node(expr.id, &[v]);
self.add_exiting_edge(expr, b, scope_id, break_dest);
let b = self.add_ast_node(expr.hir_id.local_id, &[v]);
self.add_exiting_edge(expr, b, target_scope, break_dest);
self.add_unreachable_node()
}

hir::ExprAgain(destination) => {
let (scope_id, cont_dest) =
let (target_scope, cont_dest) =
self.find_scope_edge(expr, destination, ScopeCfKind::Continue);
let a = self.add_ast_node(expr.id, &[pred]);
self.add_exiting_edge(expr, a, scope_id, cont_dest);
let a = self.add_ast_node(expr.hir_id.local_id, &[pred]);
self.add_exiting_edge(expr, a, target_scope, cont_dest);
self.add_unreachable_node()
}

@@ -397,7 +398,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
hir::ExprInlineAsm(_, ref outputs, ref inputs) => {
let post_outputs = self.exprs(outputs.iter().map(|e| &*e), pred);
let post_inputs = self.exprs(inputs.iter().map(|e| &*e), post_outputs);
self.add_ast_node(expr.id, &[post_inputs])
self.add_ast_node(expr.hir_id.local_id, &[post_inputs])
}

hir::ExprClosure(..) |
@@ -444,10 +445,10 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
//! Handles case of an expression that evaluates `subexprs` in order
let subexprs_exit = self.exprs(subexprs, pred);
self.add_ast_node(expr.id, &[subexprs_exit])
self.add_ast_node(expr.hir_id.local_id, &[subexprs_exit])
}

fn match_(&mut self, id: ast::NodeId, discr: &hir::Expr,
fn match_(&mut self, id: hir::ItemLocalId, discr: &hir::Expr,
arms: &[hir::Arm], pred: CFGIndex) -> CFGIndex {
// The CFG for match expression is quite complex, so no ASCII
// art for it (yet).
@@ -552,8 +553,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
self.add_node(CFGNodeData::Dummy, preds)
}

fn add_ast_node(&mut self, id: ast::NodeId, preds: &[CFGIndex]) -> CFGIndex {
assert!(id != ast::DUMMY_NODE_ID);
fn add_ast_node(&mut self, id: hir::ItemLocalId, preds: &[CFGIndex]) -> CFGIndex {
self.add_node(CFGNodeData::AST(id), preds)
}

@@ -579,14 +579,13 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
fn add_exiting_edge(&mut self,
from_expr: &hir::Expr,
from_index: CFGIndex,
scope_id: ast::NodeId,
target_scope: CodeExtent,
to_index: CFGIndex) {
let mut data = CFGEdgeData { exiting_scopes: vec![] };
let mut scope = CodeExtent::Misc(from_expr.id);
let target_scope = CodeExtent::Misc(scope_id);
let mut scope = CodeExtent::Misc(from_expr.hir_id.local_id);
let region_maps = self.tcx.region_maps(self.owner_def_id);
while scope != target_scope {
data.exiting_scopes.push(scope.node_id());
data.exiting_scopes.push(scope.item_local_id());
scope = region_maps.encl_scope(scope);
}
self.graph.add_edge(from_index, to_index, data);
@@ -607,13 +606,14 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
fn find_scope_edge(&self,
expr: &hir::Expr,
destination: hir::Destination,
scope_cf_kind: ScopeCfKind) -> (ast::NodeId, CFGIndex) {
scope_cf_kind: ScopeCfKind) -> (CodeExtent, CFGIndex) {

match destination.target_id {
hir::ScopeTarget::Block(block_expr_id) => {
for b in &self.breakable_block_scopes {
if b.block_expr_id == block_expr_id {
return (block_expr_id, match scope_cf_kind {
if b.block_expr_id == self.tcx.hir.node_to_hir_id(block_expr_id).local_id {
let scope_id = self.tcx.hir.node_to_hir_id(block_expr_id).local_id;
return (CodeExtent::Misc(scope_id), match scope_cf_kind {
ScopeCfKind::Break => b.break_index,
ScopeCfKind::Continue => bug!("can't continue to block"),
});
@@ -623,8 +623,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
}
hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(loop_id)) => {
for l in &self.loop_scopes {
if l.loop_id == loop_id {
return (loop_id, match scope_cf_kind {
if l.loop_id == self.tcx.hir.node_to_hir_id(loop_id).local_id {
let scope_id = self.tcx.hir.node_to_hir_id(loop_id).local_id;
return (CodeExtent::Misc(scope_id), match scope_cf_kind {
ScopeCfKind::Break => l.break_index,
ScopeCfKind::Continue => l.continue_index,
});
64 changes: 34 additions & 30 deletions src/librustc/cfg/graphviz.rs
Original file line number Diff line number Diff line change
@@ -15,40 +15,48 @@
use graphviz as dot;
use graphviz::IntoCow;

use syntax::ast;

use hir::map as hir_map;
use cfg;
use hir;
use ty::TyCtxt;

pub type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode);
pub type Edge<'a> = &'a cfg::CFGEdge;

pub struct LabelledCFG<'a, 'hir: 'a> {
pub hir_map: &'a hir_map::Map<'hir>,
pub struct LabelledCFG<'a, 'tcx: 'a> {
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
pub cfg: &'a cfg::CFG,
pub name: String,
/// `labelled_edges` controls whether we emit labels on the edges
pub labelled_edges: bool,
}

fn replace_newline_with_backslash_l(s: String) -> String {
// Replacing newlines with \\l causes each line to be left-aligned,
// improving presentation of (long) pretty-printed expressions.
if s.contains("\n") {
let mut s = s.replace("\n", "\\l");
// Apparently left-alignment applies to the line that precedes
// \l, not the line that follows; so, add \l at end of string
// if not already present, ensuring last line gets left-aligned
// as well.
let mut last_two: Vec<_> =
s.chars().rev().take(2).collect();
last_two.reverse();
if last_two != ['\\', 'l'] {
s.push_str("\\l");
impl<'a, 'tcx> LabelledCFG<'a, 'tcx> {
fn local_id_to_string(&self, local_id: hir::ItemLocalId) -> String {
assert!(self.cfg.owner_def_id.is_local());
let node_id = self.tcx.hir.hir_to_node_id(hir::HirId {
owner: self.tcx.hir.def_index_to_hir_id(self.cfg.owner_def_id.index).owner,
local_id
});
let s = self.tcx.hir.node_to_string(node_id);

// Replacing newlines with \\l causes each line to be left-aligned,
// improving presentation of (long) pretty-printed expressions.
if s.contains("\n") {
let mut s = s.replace("\n", "\\l");
// Apparently left-alignment applies to the line that precedes
// \l, not the line that follows; so, add \l at end of string
// if not already present, ensuring last line gets left-aligned
// as well.
let mut last_two: Vec<_> =
s.chars().rev().take(2).collect();
last_two.reverse();
if last_two != ['\\', 'l'] {
s.push_str("\\l");
}
s
} else {
s
}
s
} else {
s
}
}

@@ -66,12 +74,10 @@ impl<'a, 'hir> dot::Labeller<'a> for LabelledCFG<'a, 'hir> {
dot::LabelText::LabelStr("entry".into_cow())
} else if i == self.cfg.exit {
dot::LabelText::LabelStr("exit".into_cow())
} else if n.data.id() == ast::DUMMY_NODE_ID {
} else if n.data.id() == hir::DUMMY_ITEM_LOCAL_ID {
dot::LabelText::LabelStr("(dummy_node)".into_cow())
} else {
let s = self.hir_map.node_to_string(n.data.id());
// left-aligns the lines
let s = replace_newline_with_backslash_l(s);
let s = self.local_id_to_string(n.data.id());
dot::LabelText::EscStr(s.into_cow())
}
}
@@ -82,15 +88,13 @@ impl<'a, 'hir> dot::Labeller<'a> for LabelledCFG<'a, 'hir> {
return dot::LabelText::EscStr(label.into_cow());
}
let mut put_one = false;
for (i, &node_id) in e.data.exiting_scopes.iter().enumerate() {
for (i, &id) in e.data.exiting_scopes.iter().enumerate() {
if put_one {
label.push_str(",\\l");
} else {
put_one = true;
}
let s = self.hir_map.node_to_string(node_id);
// left-aligns the lines
let s = replace_newline_with_backslash_l(s);
let s = self.local_id_to_string(id);
label.push_str(&format!("exiting scope_{} {}",
i,
&s[..]));
Loading