Auto merge of #148157 - nnethercote:undo-chain, r=saethlin

Adjust successor iterators.

Because rust-lang/rust#148054 was a slight perf regression.

The problem was seemingly because this iterator structure:
```
slice_iter.chain(Option_iter.chain(Option_iter))
```
changed to this:
```
slice_iter.chain(Option_iter).chain(Option_iter)
```
The commit also tweaks the `slice_iter` part, changing `into_iter` to `iter` and using `[]` instead of `(&[])`, for conciseness and consistency.

r? `@saethlin`
This commit is contained in:
bors 2025-10-31 05:12:24 +00:00
commit 23c7bad921

View file

@ -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<Item = BasicBlock> + '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<BasicBlock>,
option2: Option<BasicBlock>,
) -> 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)
}
}
}