diff --git a/src/librustc_mir/dataflow/at_location.rs b/src/librustc_mir/dataflow/at_location.rs index 0fbb54e8e0a..a89d1afae86 100644 --- a/src/librustc_mir/dataflow/at_location.rs +++ b/src/librustc_mir/dataflow/at_location.rs @@ -204,10 +204,22 @@ where T: HasMoveData<'tcx> + BitDenotation, { pub fn has_any_child_of(&self, mpi: T::Idx) -> Option { + // We process `mpi` before the loop below, for two reasons: + // - it's a little different from the loop case (we don't traverse its + // siblings); + // - ~99% of the time the loop isn't reached, and this code is hot, so + // we don't want to allocate `todo` unnecessarily. + if self.contains(&mpi) { + return Some(mpi); + } let move_data = self.operator().move_data(); + let move_path = &move_data.move_paths[mpi]; + let mut todo = if let Some(child) = move_path.first_child { + vec![child] + } else { + return None; + }; - let mut todo = vec![mpi]; - let mut push_siblings = false; // don't look at siblings of original `mpi`. while let Some(mpi) = todo.pop() { if self.contains(&mpi) { return Some(mpi); @@ -216,15 +228,10 @@ where if let Some(child) = move_path.first_child { todo.push(child); } - if push_siblings { - if let Some(sibling) = move_path.next_sibling { - todo.push(sibling); - } - } else { - // after we've processed the original `mpi`, we should - // always traverse the siblings of any of its - // children. - push_siblings = true; + // After we've processed the original `mpi`, we should always + // traverse the siblings of any of its children. + if let Some(sibling) = move_path.next_sibling { + todo.push(sibling); } } return None;