use std::borrow::{Cow};
use rustc_data_structures::sync::ReadGuard;
use std::fmt::{self, Debug, Formatter, Write};
-use std::{iter, mem, u32};
+use std::{iter, mem, option, u32};
use std::ops::{Index, IndexMut};
use std::vec::IntoIter;
use syntax::ast::{self, Name};
},
}
+pub type Successors<'a> =
+ iter::Chain<option::IntoIter<&'a BasicBlock>, slice::Iter<'a, BasicBlock>>;
+pub type SuccessorsMut<'a> =
+ iter::Chain<option::IntoIter<&'a mut BasicBlock>, slice::IterMut<'a, BasicBlock>>;
+
impl<'tcx> Terminator<'tcx> {
- pub fn successors(&self) -> Cow<[BasicBlock]> {
+ pub fn successors(&self) -> Successors {
self.kind.successors()
}
- pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> {
+ pub fn successors_mut(&mut self) -> SuccessorsMut {
self.kind.successors_mut()
}
}
}
- pub fn successors(&self) -> Cow<[BasicBlock]> {
+ pub fn successors(&self) -> Successors {
use self::TerminatorKind::*;
match *self {
- Goto { target: ref b } => slice::from_ref(b).into_cow(),
- SwitchInt { targets: ref b, .. } => b[..].into_cow(),
- Resume | Abort | GeneratorDrop => (&[]).into_cow(),
- Return => (&[]).into_cow(),
- Unreachable => (&[]).into_cow(),
- Call { destination: Some((_, t)), cleanup: Some(c), .. } => vec![t, c].into_cow(),
- Call { destination: Some((_, ref t)), cleanup: None, .. } =>
- slice::from_ref(t).into_cow(),
- Call { destination: None, cleanup: Some(ref c), .. } => slice::from_ref(c).into_cow(),
- Call { destination: None, cleanup: None, .. } => (&[]).into_cow(),
- Yield { resume: t, drop: Some(c), .. } => vec![t, c].into_cow(),
- Yield { resume: ref t, drop: None, .. } => slice::from_ref(t).into_cow(),
- DropAndReplace { target, unwind: Some(unwind), .. } |
- Drop { target, unwind: Some(unwind), .. } => {
- vec![target, unwind].into_cow()
+ Resume | Abort | GeneratorDrop | Return | Unreachable |
+ Call { destination: None, cleanup: None, .. } => {
+ None.into_iter().chain(&[])
+ }
+ Goto { target: ref t } |
+ Call { destination: None, cleanup: Some(ref t), .. } |
+ Call { destination: Some((_, ref t)), cleanup: None, .. } |
+ Yield { resume: ref t, drop: None, .. } |
+ DropAndReplace { target: ref t, unwind: None, .. } |
+ Drop { target: ref t, unwind: None, .. } |
+ Assert { target: ref t, cleanup: None, .. } |
+ FalseUnwind { real_target: ref t, unwind: None } => {
+ Some(t).into_iter().chain(&[])
}
- DropAndReplace { ref target, unwind: None, .. } |
- Drop { ref target, unwind: None, .. } => {
- slice::from_ref(target).into_cow()
+ Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. } |
+ Yield { resume: ref t, drop: Some(ref u), .. } |
+ DropAndReplace { target: ref t, unwind: Some(ref u), .. } |
+ Drop { target: ref t, unwind: Some(ref u), .. } |
+ Assert { target: ref t, cleanup: Some(ref u), .. } |
+ FalseUnwind { real_target: ref t, unwind: Some(ref u) } => {
+ Some(t).into_iter().chain(slice::from_ref(u))
+ }
+ SwitchInt { ref targets, .. } => {
+ None.into_iter().chain(&targets[..])
}
- Assert { target, cleanup: Some(unwind), .. } => vec![target, unwind].into_cow(),
- Assert { ref target, .. } => slice::from_ref(target).into_cow(),
FalseEdges { ref real_target, ref imaginary_targets } => {
- let mut s = vec![*real_target];
- s.extend_from_slice(imaginary_targets);
- s.into_cow()
+ Some(real_target).into_iter().chain(&imaginary_targets[..])
}
- FalseUnwind { real_target: t, unwind: Some(u) } => vec![t, u].into_cow(),
- FalseUnwind { real_target: ref t, unwind: None } => slice::from_ref(t).into_cow(),
}
}
- // FIXME: no mootable cow. I’m honestly not sure what a “cow” between `&mut [BasicBlock]` and
- // `Vec<&mut BasicBlock>` would look like in the first place.
- pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> {
+ pub fn successors_mut(&mut self) -> SuccessorsMut {
use self::TerminatorKind::*;
match *self {
- Goto { target: ref mut b } => vec![b],
- SwitchInt { targets: ref mut b, .. } => b.iter_mut().collect(),
- Resume | Abort | GeneratorDrop => Vec::new(),
- Return => Vec::new(),
- Unreachable => Vec::new(),
- Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut c), .. } => vec![t, c],
- Call { destination: Some((_, ref mut t)), cleanup: None, .. } => vec![t],
- Call { destination: None, cleanup: Some(ref mut c), .. } => vec![c],
- Call { destination: None, cleanup: None, .. } => vec![],
- Yield { resume: ref mut t, drop: Some(ref mut c), .. } => vec![t, c],
- Yield { resume: ref mut t, drop: None, .. } => vec![t],
- DropAndReplace { ref mut target, unwind: Some(ref mut unwind), .. } |
- Drop { ref mut target, unwind: Some(ref mut unwind), .. } => vec![target, unwind],
- DropAndReplace { ref mut target, unwind: None, .. } |
- Drop { ref mut target, unwind: None, .. } => {
- vec![target]
+ Resume | Abort | GeneratorDrop | Return | Unreachable |
+ Call { destination: None, cleanup: None, .. } => {
+ None.into_iter().chain(&mut [])
+ }
+ Goto { target: ref mut t } |
+ Call { destination: None, cleanup: Some(ref mut t), .. } |
+ Call { destination: Some((_, ref mut t)), cleanup: None, .. } |
+ Yield { resume: ref mut t, drop: None, .. } |
+ DropAndReplace { target: ref mut t, unwind: None, .. } |
+ Drop { target: ref mut t, unwind: None, .. } |
+ Assert { target: ref mut t, cleanup: None, .. } |
+ FalseUnwind { real_target: ref mut t, unwind: None } => {
+ Some(t).into_iter().chain(&mut [])
+ }
+ Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. } |
+ Yield { resume: ref mut t, drop: Some(ref mut u), .. } |
+ DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. } |
+ Drop { target: ref mut t, unwind: Some(ref mut u), .. } |
+ Assert { target: ref mut t, cleanup: Some(ref mut u), .. } |
+ FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => {
+ Some(t).into_iter().chain(slice::from_ref_mut(u))
+ }
+ SwitchInt { ref mut targets, .. } => {
+ None.into_iter().chain(&mut targets[..])
}
- Assert { ref mut target, cleanup: Some(ref mut unwind), .. } => vec![target, unwind],
- Assert { ref mut target, .. } => vec![target],
FalseEdges { ref mut real_target, ref mut imaginary_targets } => {
- let mut s = vec![real_target];
- s.extend(imaginary_targets.iter_mut());
- s
+ Some(real_target).into_iter().chain(&mut imaginary_targets[..])
}
- FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => vec![t, u],
- FalseUnwind { ref mut real_target, unwind: None } => vec![real_target],
}
}
impl<'tcx> Debug for TerminatorKind<'tcx> {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
self.fmt_head(fmt)?;
- let successors = self.successors();
+ let successor_count = self.successors().count();
let labels = self.fmt_successor_labels();
- assert_eq!(successors.len(), labels.len());
+ assert_eq!(successor_count, labels.len());
- match successors.len() {
+ match successor_count {
0 => Ok(()),
- 1 => write!(fmt, " -> {:?}", successors[0]),
+ 1 => write!(fmt, " -> {:?}", self.successors().nth(0).unwrap()),
_ => {
write!(fmt, " -> [")?;
- for (i, target) in successors.iter().enumerate() {
+ for (i, target) in self.successors().enumerate() {
if i > 0 {
write!(fmt, ", ")?;
}
fn successors<'graph>(&'graph self, node: Self::Node)
-> <Self as GraphSuccessors<'graph>>::Iter
{
- self.basic_blocks[node].terminator().successors().into_owned().into_iter()
+ self.basic_blocks[node].terminator().successors().cloned()
}
}
impl<'a, 'b> GraphSuccessors<'b> for Mir<'a> {
type Item = BasicBlock;
- type Iter = IntoIter<BasicBlock>;
+ type Iter = iter::Cloned<Successors<'b>>;
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]