diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index db8251c7d9dc8..cd447d4ed992b 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -501,30 +501,37 @@ pub use helper::*; mod helper { use super::*; - // Note: the methods below use a `slice.chain(Option).chain(Option)` pattern so that all paths - // produce an iterator with the same concrete type. pub type Successors<'a> = impl DoubleEndedIterator + 'a; + // Note: this method ensures all paths below produce an iterator with the same concrete type. + #[inline] + #[define_opaque(Successors)] + fn mk_successors( + slice: &[BasicBlock], + option1: Option, + option2: Option, + ) -> Successors<'_> { + slice.iter().copied().chain(option1.into_iter().chain(option2)) + } + impl SwitchTargets { /// Like [`SwitchTargets::target_for_value`], but returning the same type as /// [`Terminator::successors`]. #[inline] - #[define_opaque(Successors)] pub fn successors_for_value(&self, value: u128) -> Successors<'_> { let target = self.target_for_value(value); - (&[]).into_iter().copied().chain(Some(target)).chain(None) + mk_successors(&[], Some(target), None) } } impl<'tcx> TerminatorKind<'tcx> { #[inline] - #[define_opaque(Successors)] pub fn successors(&self) -> Successors<'_> { use self::TerminatorKind::*; match *self { // 3-successors for async drop: target, unwind, dropline (parent coroutine drop) Drop { target: ref t, unwind: UnwindAction::Cleanup(u), drop: Some(d), .. } => { - slice::from_ref(t).into_iter().copied().chain(Some(u)).chain(Some(d)) + mk_successors(slice::from_ref(t), Some(u), Some(d)) } // 2-successors Call { target: Some(ref t), unwind: UnwindAction::Cleanup(u), .. } @@ -533,7 +540,7 @@ mod helper { | Drop { target: ref t, unwind: _, drop: Some(u), .. } | Assert { target: ref t, unwind: UnwindAction::Cleanup(u), .. } | FalseUnwind { real_target: ref t, unwind: UnwindAction::Cleanup(u) } => { - slice::from_ref(t).into_iter().copied().chain(Some(u)).chain(None) + mk_successors(slice::from_ref(t), Some(u), None) } // single successor Goto { target: ref t } @@ -543,7 +550,7 @@ mod helper { | Drop { target: ref t, unwind: _, .. } | Assert { target: ref t, unwind: _, .. } | FalseUnwind { real_target: ref t, unwind: _ } => { - slice::from_ref(t).into_iter().copied().chain(None).chain(None) + mk_successors(slice::from_ref(t), None, None) } // No successors UnwindResume @@ -552,25 +559,17 @@ mod helper { | Return | Unreachable | TailCall { .. } - | Call { target: None, unwind: _, .. } => { - (&[]).into_iter().copied().chain(None).chain(None) - } + | Call { target: None, unwind: _, .. } => mk_successors(&[], None, None), // Multiple successors InlineAsm { ref targets, unwind: UnwindAction::Cleanup(u), .. } => { - targets.iter().copied().chain(Some(u)).chain(None) - } - InlineAsm { ref targets, unwind: _, .. } => { - targets.iter().copied().chain(None).chain(None) - } - SwitchInt { ref targets, .. } => { - targets.targets.iter().copied().chain(None).chain(None) + mk_successors(targets, Some(u), None) } + InlineAsm { ref targets, unwind: _, .. } => mk_successors(targets, None, None), + SwitchInt { ref targets, .. } => mk_successors(&targets.targets, None, None), // FalseEdge - FalseEdge { ref real_target, imaginary_target } => slice::from_ref(real_target) - .into_iter() - .copied() - .chain(Some(imaginary_target)) - .chain(None), + FalseEdge { ref real_target, imaginary_target } => { + mk_successors(slice::from_ref(real_target), Some(imaginary_target), None) + } } }