diff --git a/crates/oxc_semantic/src/control_flow/mod.rs b/crates/oxc_semantic/src/control_flow/mod.rs index 240cbc888777ba..715dea363f7df9 100644 --- a/crates/oxc_semantic/src/control_flow/mod.rs +++ b/crates/oxc_semantic/src/control_flow/mod.rs @@ -1,14 +1,13 @@ mod builder; mod dot; -use itertools::Itertools; use oxc_span::CompactStr; use oxc_syntax::operator::{ AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator, UpdateOperator, }; use petgraph::{ stable_graph::NodeIndex, - visit::{depth_first_search, Dfs, DfsEvent, Walker}, + visit::{depth_first_search, Control, DfsEvent}, Graph, }; @@ -192,19 +191,29 @@ impl ControlFlowGraph { } pub fn is_reachabale(&self, from: BasicBlockId, to: BasicBlockId) -> bool { + if from == to { + return true; + } let graph = &self.graph; - let mut dfs = Dfs::empty(graph); - dfs.reset(graph); - dfs.move_to(from); - dfs.iter(graph) - .take_while_inclusive(|it| { - !self - .basic_block(*it) - .instructions() - .iter() - .any(|it| matches!(it, Instruction { kind: InstructionKind::Unreachable, .. })) - }) - .any(|x| x == to) + depth_first_search(&self.graph, Some(from), |event| match event { + DfsEvent::TreeEdge(a, b) => { + if b == to { + return Control::Break(true); + } + + let test = graph.edges_connecting(a, b).all(|edge| { + !matches!(edge.weight(), EdgeType::NewFunction | EdgeType::Unreachable) + }); + if test { + Control::Continue + } else { + Control::Prune + } + } + _ => Control::Continue, + }) + .break_value() + .unwrap_or(false) } pub fn is_cyclic(&self, node: BasicBlockId) -> bool {