diff options
Diffstat (limited to 'src/librustc')
| -rw-r--r-- | src/librustc/cfg/construct.rs | 533 | ||||
| -rw-r--r-- | src/librustc/cfg/graphviz.rs | 123 | ||||
| -rw-r--r-- | src/librustc/cfg/mod.rs | 60 | ||||
| -rw-r--r-- | src/librustc/lib.rs | 1 |
4 files changed, 0 insertions, 717 deletions
diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs deleted file mode 100644 index 0dad2dda837..00000000000 --- a/src/librustc/cfg/construct.rs +++ /dev/null @@ -1,533 +0,0 @@ -use crate::cfg::*; -use crate::middle::region; -use rustc_data_structures::graph::implementation as graph; -use crate::ty::{self, TyCtxt}; - -use crate::hir::{self, PatKind}; -use crate::hir::def_id::DefId; -use crate::hir::ptr::P; - -struct CFGBuilder<'a, 'tcx> { - tcx: TyCtxt<'tcx>, - owner_def_id: DefId, - tables: &'a ty::TypeckTables<'tcx>, - graph: CFGGraph, - fn_exit: CFGIndex, - loop_scopes: Vec<LoopScope>, - breakable_block_scopes: Vec<BlockScope>, -} - -#[derive(Copy, Clone)] -struct BlockScope { - 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: 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` -} - -pub fn construct(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG { - let mut graph = graph::Graph::new(); - let entry = graph.add_node(CFGNodeData::Entry); - - // `fn_exit` is target of return exprs, which lies somewhere - // outside input `body`. (Distinguishing `fn_exit` and `body_exit` - // also resolves chicken-and-egg problem that arises if you try to - // have return exprs jump to `body_exit` during construction.) - let fn_exit = graph.add_node(CFGNodeData::Exit); - let body_exit; - - // Find the tables for this body. - let owner_def_id = tcx.hir().body_owner_def_id(body.id()); - let tables = tcx.typeck_tables_of(owner_def_id); - - let mut cfg_builder = CFGBuilder { - tcx, - owner_def_id, - tables, - graph, - fn_exit, - loop_scopes: Vec::new(), - breakable_block_scopes: Vec::new(), - }; - body_exit = cfg_builder.expr(&body.value, entry); - cfg_builder.add_contained_edge(body_exit, fn_exit); - let CFGBuilder { graph, .. } = cfg_builder; - CFG { - owner_def_id, - graph, - entry, - exit: fn_exit, - } -} - -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.hir_id.local_id, &[]); - - self.breakable_block_scopes.push(BlockScope { - block_expr_id: blk.hir_id.local_id, - break_index: expr_exit, - }); - - let mut stmts_exit = pred; - for stmt in &blk.stmts { - stmts_exit = self.stmt(stmt, stmts_exit); - } - let blk_expr_exit = self.opt_expr(&blk.expr, stmts_exit); - self.add_contained_edge(blk_expr_exit, expr_exit); - - self.breakable_block_scopes.pop(); - - expr_exit - } else { - let mut stmts_exit = pred; - for stmt in &blk.stmts { - stmts_exit = self.stmt(stmt, stmts_exit); - } - - let expr_exit = self.opt_expr(&blk.expr, stmts_exit); - - self.add_ast_node(blk.hir_id.local_id, &[expr_exit]) - } - } - - fn stmt(&mut self, stmt: &hir::Stmt, pred: CFGIndex) -> CFGIndex { - let exit = match stmt.node { - hir::StmtKind::Local(ref local) => { - let init_exit = self.opt_expr(&local.init, pred); - self.pat(&local.pat, init_exit) - } - hir::StmtKind::Item(_) => { - pred - } - hir::StmtKind::Expr(ref expr) | - hir::StmtKind::Semi(ref expr) => { - self.expr(&expr, pred) - } - }; - self.add_ast_node(stmt.hir_id.local_id, &[exit]) - } - - fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex { - match pat.node { - PatKind::Binding(.., None) | - PatKind::Path(_) | - PatKind::Lit(..) | - PatKind::Range(..) | - 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.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.hir_id.local_id, &[pats_exit]) - } - - PatKind::Struct(_, ref subpats, _) => { - let pats_exit = self.pats_all(subpats.iter().map(|f| &f.pat), pred); - self.add_ast_node(pat.hir_id.local_id, &[pats_exit]) - } - - PatKind::Or(ref pats) => { - let branches: Vec<_> = pats.iter().map(|p| self.pat(p, pred)).collect(); - self.add_ast_node(pat.hir_id.local_id, &branches) - } - - 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.hir_id.local_id, &[post_exit]) - } - } - } - - fn pats_all<'b, I: Iterator<Item=&'b P<hir::Pat>>>( - &mut self, - pats: I, - pred: CFGIndex - ) -> CFGIndex { - //! Handles case where all of the patterns must match. - pats.fold(pred, |pred, pat| self.pat(&pat, pred)) - } - - fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex { - match expr.node { - hir::ExprKind::Block(ref blk, _) => { - let blk_exit = self.block(&blk, pred); - self.add_ast_node(expr.hir_id.local_id, &[blk_exit]) - } - - hir::ExprKind::Loop(ref body, _, _) => { - // - // [pred] - // | - // v 1 - // [loopback] <---+ - // | 4 | - // v 3 | - // [body] ------+ - // - // [expr] 2 - // - // Note that `break` and `loop` statements - // may cause additional edges. - - let loopback = self.add_dummy_node(&[pred]); // 1 - let expr_exit = self.add_ast_node(expr.hir_id.local_id, &[]); // 2 - self.loop_scopes.push(LoopScope { - loop_id: expr.hir_id.local_id, - continue_index: loopback, - break_index: expr_exit, - }); - let body_exit = self.block(&body, loopback); // 3 - self.add_contained_edge(body_exit, loopback); // 4 - self.loop_scopes.pop(); - expr_exit - } - - hir::ExprKind::Match(ref discr, ref arms, _) => { - self.match_(expr.hir_id.local_id, &discr, &arms, pred) - } - - hir::ExprKind::Binary(op, ref l, ref r) if op.node.is_lazy() => { - // - // [pred] - // | - // v 1 - // [l] - // | - // / \ - // / \ - // v 2 * - // [r] | - // | | - // v 3 v 4 - // [..exit..] - // - let l_exit = self.expr(&l, pred); // 1 - let r_exit = self.expr(&r, l_exit); // 2 - self.add_ast_node(expr.hir_id.local_id, &[l_exit, r_exit]) // 3,4 - } - - hir::ExprKind::Ret(ref v) => { - let v_exit = self.opt_expr(v, pred); - let b = self.add_ast_node(expr.hir_id.local_id, &[v_exit]); - self.add_returning_edge(expr, b); - self.add_unreachable_node() - } - - hir::ExprKind::Break(destination, ref opt_expr) => { - let v = self.opt_expr(opt_expr, pred); - let (target_scope, break_dest) = - self.find_scope_edge(expr, destination, ScopeCfKind::Break); - 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::ExprKind::Continue(destination) => { - let (target_scope, cont_dest) = - self.find_scope_edge(expr, destination, ScopeCfKind::Continue); - 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() - } - - hir::ExprKind::Array(ref elems) => { - self.straightline(expr, pred, elems.iter().map(|e| &*e)) - } - - hir::ExprKind::Call(ref func, ref args) => { - self.call(expr, pred, &func, args.iter().map(|e| &*e)) - } - - hir::ExprKind::MethodCall(.., ref args) => { - self.call(expr, pred, &args[0], args[1..].iter().map(|e| &*e)) - } - - hir::ExprKind::Index(ref l, ref r) | - hir::ExprKind::Binary(_, ref l, ref r) if self.tables.is_method_call(expr) => { - self.call(expr, pred, &l, Some(&**r).into_iter()) - } - - hir::ExprKind::Unary(_, ref e) if self.tables.is_method_call(expr) => { - self.call(expr, pred, &e, None::<hir::Expr>.iter()) - } - - hir::ExprKind::Tup(ref exprs) => { - self.straightline(expr, pred, exprs.iter().map(|e| &*e)) - } - - hir::ExprKind::Struct(_, ref fields, ref base) => { - let field_cfg = self.straightline(expr, pred, fields.iter().map(|f| &*f.expr)); - self.opt_expr(base, field_cfg) - } - - hir::ExprKind::Assign(ref l, ref r) | - hir::ExprKind::AssignOp(_, ref l, ref r) => { - self.straightline(expr, pred, [r, l].iter().map(|&e| &**e)) - } - - hir::ExprKind::Index(ref l, ref r) | - hir::ExprKind::Binary(_, ref l, ref r) => { // N.B., && and || handled earlier - self.straightline(expr, pred, [l, r].iter().map(|&e| &**e)) - } - - hir::ExprKind::Box(ref e) | - hir::ExprKind::AddrOf(_, ref e) | - hir::ExprKind::Cast(ref e, _) | - hir::ExprKind::Type(ref e, _) | - hir::ExprKind::DropTemps(ref e) | - hir::ExprKind::Unary(_, ref e) | - hir::ExprKind::Field(ref e, _) | - hir::ExprKind::Yield(ref e, _) | - hir::ExprKind::Repeat(ref e, _) => { - self.straightline(expr, pred, Some(&**e).into_iter()) - } - - hir::ExprKind::InlineAsm(_, 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.hir_id.local_id, &[post_inputs]) - } - - hir::ExprKind::Closure(..) | - hir::ExprKind::Lit(..) | - hir::ExprKind::Path(_) | - hir::ExprKind::Err => { - self.straightline(expr, pred, None::<hir::Expr>.iter()) - } - } - } - - fn call<'b, I: Iterator<Item=&'b hir::Expr>>(&mut self, - call_expr: &hir::Expr, - pred: CFGIndex, - func_or_rcvr: &hir::Expr, - args: I) -> CFGIndex { - let func_or_rcvr_exit = self.expr(func_or_rcvr, pred); - let ret = self.straightline(call_expr, func_or_rcvr_exit, args); - let m = self.tcx.hir().get_module_parent(call_expr.hir_id); - if self.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(call_expr)) { - self.add_unreachable_node() - } else { - ret - } - } - - fn exprs<'b, I: Iterator<Item=&'b hir::Expr>>(&mut self, - exprs: I, - pred: CFGIndex) -> CFGIndex { - //! Constructs graph for `exprs` evaluated in order - exprs.fold(pred, |p, e| self.expr(e, p)) - } - - fn opt_expr(&mut self, - opt_expr: &Option<P<hir::Expr>>, - pred: CFGIndex) -> CFGIndex { - //! Constructs graph for `opt_expr` evaluated, if Some - opt_expr.iter().fold(pred, |p, e| self.expr(&e, p)) - } - - fn straightline<'b, I: Iterator<Item=&'b hir::Expr>>(&mut self, - expr: &hir::Expr, - pred: CFGIndex, - subexprs: I) -> CFGIndex { - //! Handles case of an expression that evaluates `subexprs` in order - - let subexprs_exit = self.exprs(subexprs, pred); - self.add_ast_node(expr.hir_id.local_id, &[subexprs_exit]) - } - - 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). - // - // The CFG generated below matches roughly what MIR contains. - // Each pattern and guard is visited in parallel, with - // arms containing multiple patterns generating multiple nodes - // for the same guard expression. The guard expressions chain - // into each other from top to bottom, with a specific - // exception to allow some additional valid programs - // (explained below). MIR differs slightly in that the - // pattern matching may continue after a guard but the visible - // behaviour should be the same. - // - // What is going on is explained in further comments. - - // Visit the discriminant expression - let discr_exit = self.expr(discr, pred); - - // Add a node for the exit of the match expression as a whole. - let expr_exit = self.add_ast_node(id, &[]); - - // Keep track of the previous guard expressions - let mut prev_guard = None; - let match_scope = region::Scope { id, data: region::ScopeData::Node }; - - for arm in arms { - // Add an exit node for when we've visited all the - // patterns and the guard (if there is one) in the arm. - let bindings_exit = self.add_dummy_node(&[]); - - for pat in &arm.pats { - // Visit the pattern, coming from the discriminant exit - let mut pat_exit = self.pat(&pat, discr_exit); - - // If there is a guard expression, handle it here - if let Some(ref guard) = arm.guard { - // Add a dummy node for the previous guard - // expression to target - let guard_start = self.add_dummy_node(&[pat_exit]); - // Visit the guard expression - let guard_exit = match guard { - hir::Guard::If(ref e) => (&**e, self.expr(e, guard_start)), - }; - // #47295: We used to have very special case code - // here for when a pair of arms are both formed - // solely from constants, and if so, not add these - // edges. But this was not actually sound without - // other constraints that we stopped enforcing at - // some point. - if let Some((prev_guard, prev_index)) = prev_guard.take() { - self.add_exiting_edge(prev_guard, prev_index, match_scope, guard_start); - } - - // Push the guard onto the list of previous guards - prev_guard = Some(guard_exit); - - // Update the exit node for the pattern - pat_exit = guard_exit.1; - } - - // Add an edge from the exit of this pattern to the - // exit of the arm - self.add_contained_edge(pat_exit, bindings_exit); - } - - // Visit the body of this arm - let body_exit = self.expr(&arm.body, bindings_exit); - - let arm_exit = self.add_ast_node(arm.hir_id.local_id, &[body_exit]); - - // Link the body to the exit of the expression - self.add_contained_edge(arm_exit, expr_exit); - } - - expr_exit - } - - fn add_dummy_node(&mut self, preds: &[CFGIndex]) -> CFGIndex { - self.add_node(CFGNodeData::Dummy, preds) - } - - fn add_ast_node(&mut self, id: hir::ItemLocalId, preds: &[CFGIndex]) -> CFGIndex { - self.add_node(CFGNodeData::AST(id), preds) - } - - fn add_unreachable_node(&mut self) -> CFGIndex { - self.add_node(CFGNodeData::Unreachable, &[]) - } - - fn add_node(&mut self, data: CFGNodeData, preds: &[CFGIndex]) -> CFGIndex { - let node = self.graph.add_node(data); - for &pred in preds { - self.add_contained_edge(pred, node); - } - node - } - - fn add_contained_edge(&mut self, - source: CFGIndex, - target: CFGIndex) { - let data = CFGEdgeData {exiting_scopes: vec![] }; - self.graph.add_edge(source, target, data); - } - - fn add_exiting_edge(&mut self, - from_expr: &hir::Expr, - from_index: CFGIndex, - target_scope: region::Scope, - to_index: CFGIndex) { - let mut data = CFGEdgeData { exiting_scopes: vec![] }; - let mut scope = region::Scope { - id: from_expr.hir_id.local_id, - data: region::ScopeData::Node - }; - let region_scope_tree = self.tcx.region_scope_tree(self.owner_def_id); - while scope != target_scope { - data.exiting_scopes.push(scope.item_local_id()); - scope = region_scope_tree.encl_scope(scope); - } - self.graph.add_edge(from_index, to_index, data); - } - - fn add_returning_edge(&mut self, - _from_expr: &hir::Expr, - from_index: CFGIndex) { - let data = CFGEdgeData { - exiting_scopes: self.loop_scopes.iter() - .rev() - .map(|&LoopScope { loop_id: id, .. }| id) - .collect() - }; - self.graph.add_edge(from_index, self.fn_exit, data); - } - - fn find_scope_edge(&self, - expr: &hir::Expr, - destination: hir::Destination, - scope_cf_kind: ScopeCfKind) -> (region::Scope, CFGIndex) { - - match destination.target_id { - Ok(loop_id) => { - for b in &self.breakable_block_scopes { - if b.block_expr_id == loop_id.local_id { - let scope = region::Scope { - id: loop_id.local_id, - data: region::ScopeData::Node - }; - return (scope, match scope_cf_kind { - ScopeCfKind::Break => b.break_index, - ScopeCfKind::Continue => bug!("can't continue to block"), - }); - } - } - for l in &self.loop_scopes { - if l.loop_id == loop_id.local_id { - let scope = region::Scope { - id: loop_id.local_id, - data: region::ScopeData::Node - }; - return (scope, match scope_cf_kind { - ScopeCfKind::Break => l.break_index, - ScopeCfKind::Continue => l.continue_index, - }); - } - } - span_bug!(expr.span, "no scope for id {}", loop_id); - } - Err(err) => span_bug!(expr.span, "scope error: {}", err), - } - } -} - -#[derive(Copy, Clone, Eq, PartialEq)] -enum ScopeCfKind { - Break, - Continue, -} diff --git a/src/librustc/cfg/graphviz.rs b/src/librustc/cfg/graphviz.rs deleted file mode 100644 index 918120057d4..00000000000 --- a/src/librustc/cfg/graphviz.rs +++ /dev/null @@ -1,123 +0,0 @@ -/// This module provides linkage between rustc::middle::graph and -/// libgraphviz traits. - -// For clarity, rename the graphviz crate locally to dot. -use graphviz as dot; - -use crate::cfg; -use crate::hir; -use crate::ty::TyCtxt; - -pub type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode); -pub type Edge<'a> = &'a cfg::CFGEdge; - -pub struct LabelledCFG<'a, 'tcx> { - pub tcx: TyCtxt<'tcx>, - pub cfg: &'a cfg::CFG, - pub name: String, - /// `labelled_edges` controls whether we emit labels on the edges - pub labelled_edges: bool, -} - -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 hir_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(hir_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 - } - } -} - -impl<'a, 'hir> dot::Labeller<'a> for LabelledCFG<'a, 'hir> { - type Node = Node<'a>; - type Edge = Edge<'a>; - fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(&self.name[..]).unwrap() } - - fn node_id(&'a self, &(i,_): &Node<'a>) -> dot::Id<'a> { - dot::Id::new(format!("N{}", i.node_id())).unwrap() - } - - fn node_label(&'a self, &(i, n): &Node<'a>) -> dot::LabelText<'a> { - if i == self.cfg.entry { - dot::LabelText::LabelStr("entry".into()) - } else if i == self.cfg.exit { - dot::LabelText::LabelStr("exit".into()) - } else if n.data.id() == hir::DUMMY_ITEM_LOCAL_ID { - dot::LabelText::LabelStr("(dummy_node)".into()) - } else { - let s = self.local_id_to_string(n.data.id()); - dot::LabelText::EscStr(s.into()) - } - } - - fn edge_label(&self, e: &Edge<'a>) -> dot::LabelText<'a> { - let mut label = String::new(); - if !self.labelled_edges { - return dot::LabelText::EscStr(label.into()); - } - let mut put_one = false; - for (i, &id) in e.data.exiting_scopes.iter().enumerate() { - if put_one { - label.push_str(",\\l"); - } else { - put_one = true; - } - let s = self.local_id_to_string(id); - label.push_str(&format!("exiting scope_{} {}", - i, - &s[..])); - } - dot::LabelText::EscStr(label.into()) - } -} - -impl<'a> dot::GraphWalk<'a> for &'a cfg::CFG { - type Node = Node<'a>; - type Edge = Edge<'a>; - fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> { - let v: Vec<_> = self.graph.enumerated_nodes().collect(); - v.into() - } - fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> { - self.graph.all_edges().iter().collect() - } - fn source(&'a self, edge: &Edge<'a>) -> Node<'a> { - let i = edge.source(); - (i, self.graph.node(i)) - } - fn target(&'a self, edge: &Edge<'a>) -> Node<'a> { - let i = edge.target(); - (i, self.graph.node(i)) - } -} - -impl<'a, 'hir> dot::GraphWalk<'a> for LabelledCFG<'a, 'hir> -{ - type Node = Node<'a>; - type Edge = Edge<'a>; - fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> { self.cfg.nodes() } - fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> { self.cfg.edges() } - fn source(&'a self, edge: &Edge<'a>) -> Node<'a> { self.cfg.source(edge) } - fn target(&'a self, edge: &Edge<'a>) -> Node<'a> { self.cfg.target(edge) } -} diff --git a/src/librustc/cfg/mod.rs b/src/librustc/cfg/mod.rs deleted file mode 100644 index 88fc7fbfad5..00000000000 --- a/src/librustc/cfg/mod.rs +++ /dev/null @@ -1,60 +0,0 @@ -//! Module that constructs a control-flow graph representing an item. -//! Uses `Graph` as the underlying representation. - -use rustc_data_structures::graph::implementation as graph; -use crate::ty::TyCtxt; -use crate::hir; -use crate::hir::def_id::DefId; - -mod construct; -pub mod graphviz; - -pub struct CFG { - pub owner_def_id: DefId, - pub graph: CFGGraph, - pub entry: CFGIndex, - pub exit: CFGIndex, -} - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum CFGNodeData { - AST(hir::ItemLocalId), - Entry, - Exit, - Dummy, - Unreachable, -} - -impl CFGNodeData { - pub fn id(&self) -> hir::ItemLocalId { - if let CFGNodeData::AST(id) = *self { - id - } else { - hir::DUMMY_ITEM_LOCAL_ID - } - } -} - -#[derive(Debug)] -pub struct CFGEdgeData { - pub exiting_scopes: Vec<hir::ItemLocalId> -} - -pub type CFGIndex = graph::NodeIndex; - -pub type CFGGraph = graph::Graph<CFGNodeData, CFGEdgeData>; - -pub type CFGNode = graph::Node<CFGNodeData>; - -pub type CFGEdge = graph::Edge<CFGEdgeData>; - -impl CFG { - pub fn new(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG { - construct::construct(tcx, body) - } - - pub fn node_is_reachable(&self, id: hir::ItemLocalId) -> bool { - self.graph.depth_traverse(self.entry, graph::OUTGOING) - .any(|idx| self.graph.node_data(idx).id() == id) - } -} diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 368f5bb64fe..bf4330a29a7 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -97,7 +97,6 @@ pub mod query; #[macro_use] pub mod arena; -pub mod cfg; pub mod dep_graph; pub mod hir; pub mod ich; |
