Skip to content

rustc: return iterators from Terminator(Kind)::successors(_mut). #50278

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc/mir/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ fn calculate_predecessors(mir: &Mir) -> IndexVec<BasicBlock, Vec<BasicBlock>> {
let mut result = IndexVec::from_elem(vec![], mir.basic_blocks());
for (bb, data) in mir.basic_blocks().iter_enumerated() {
if let Some(ref term) = data.terminator {
for &tgt in term.successors().iter() {
for &tgt in term.successors() {
result[tgt].push(bb);
}
}
Expand Down
128 changes: 66 additions & 62 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use hir::{self, InlineAsm};
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};
Expand Down Expand Up @@ -859,12 +859,17 @@ pub enum TerminatorKind<'tcx> {
},
}

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()
}

Expand All @@ -885,72 +890,71 @@ impl<'tcx> TerminatorKind<'tcx> {
}
}

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],
}
}

Expand Down Expand Up @@ -1070,18 +1074,18 @@ impl<'tcx> BasicBlockData<'tcx> {
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, ", ")?;
}
Expand Down Expand Up @@ -1969,7 +1973,7 @@ impl<'tcx> ControlFlowGraph for Mir<'tcx> {
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()
}
}

Expand All @@ -1980,7 +1984,7 @@ impl<'a, 'b> GraphPredecessors<'b> for Mir<'a> {

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)]
Expand Down
16 changes: 5 additions & 11 deletions src/librustc/mir/traversal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::vec;

use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::indexed_vec::Idx;

Expand Down Expand Up @@ -67,7 +65,7 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
let data = &self.mir[idx];

if let Some(ref term) = data.terminator {
for &succ in term.successors().iter() {
for &succ in term.successors() {
self.worklist.push(succ);
}
}
Expand Down Expand Up @@ -110,7 +108,7 @@ impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {}
pub struct Postorder<'a, 'tcx: 'a> {
mir: &'a Mir<'tcx>,
visited: BitVector,
visit_stack: Vec<(BasicBlock, vec::IntoIter<BasicBlock>)>
visit_stack: Vec<(BasicBlock, Successors<'a>)>
}

impl<'a, 'tcx> Postorder<'a, 'tcx> {
Expand All @@ -126,10 +124,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {

if let Some(ref term) = data.terminator {
po.visited.insert(root.index());

let succs = term.successors().into_owned().into_iter();

po.visit_stack.push((root, succs));
po.visit_stack.push((root, term.successors()));
po.traverse_successor();
}

Expand Down Expand Up @@ -186,7 +181,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
// two iterations yield `C` and finally `A` for a final traversal of [E, D, B, C, A]
loop {
let bb = if let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() {
if let Some(bb) = iter.next() {
if let Some(&bb) = iter.next() {
bb
} else {
break;
Expand All @@ -197,8 +192,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {

if self.visited.insert(bb.index()) {
if let Some(ref term) = self.mir[bb].terminator {
let succs = term.successors().into_owned().into_iter();
self.visit_stack.push((bb, succs));
self.visit_stack.push((bb, term.successors()));
}
}
}
Expand Down
1 change: 0 additions & 1 deletion src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> {
block_data
.terminator()
.successors()
.iter()
.map(|&basic_block| Location {
statement_index: 0,
block: basic_block,
Expand Down
1 change: 0 additions & 1 deletion src/librustc_mir/borrow_check/nll/region_infer/dfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
block_data
.terminator()
.successors()
.iter()
.map(|&basic_block| Location {
statement_index: 0,
block: basic_block,
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_mir/dataflow/graphviz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ pub type Node = BasicBlock;
pub struct Edge { source: BasicBlock, index: usize }

fn outgoing(mir: &Mir, bb: BasicBlock) -> Vec<Edge> {
let succ_len = mir[bb].terminator().successors().len();
(0..succ_len).map(|index| Edge { source: bb, index: index}).collect()
mir[bb].terminator().successors().enumerate()
.map(|(index, _)| Edge { source: bb, index: index}).collect()
}

impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
Expand Down Expand Up @@ -285,6 +285,6 @@ impl<'a, 'tcx, MWF, P> dot::GraphWalk<'a> for Graph<'a, 'tcx, MWF, P>

fn target(&self, edge: &Edge) -> Node {
let mir = self.mbcx.mir();
mir[edge.source].terminator().successors()[edge.index]
*mir[edge.source].terminator().successors().nth(edge.index).unwrap()
}
}
2 changes: 1 addition & 1 deletion src/librustc_mir/transform/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
}

if !is_drop {
for &succ in &term.successors()[..] {
for &succ in term.successors() {
work_list.push(succ);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/transform/remove_noop_landing_pads.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl RemoveNoopLandingPads {
TerminatorKind::SwitchInt { .. } |
TerminatorKind::FalseEdges { .. } |
TerminatorKind::FalseUnwind { .. } => {
terminator.successors().iter().all(|succ| {
terminator.successors().all(|succ| {
nop_landing_pads.contains(succ.index())
})
},
Expand Down
10 changes: 5 additions & 5 deletions src/librustc_mir/transform/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {

for (_, data) in traversal::preorder(mir) {
if let Some(ref term) = data.terminator {
for &tgt in term.successors().iter() {
for &tgt in term.successors() {
pred_count[tgt] += 1;
}
}
Expand Down Expand Up @@ -219,10 +219,10 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
};

let first_succ = {
let successors = terminator.successors();
if let Some(&first_succ) = terminator.successors().get(0) {
if successors.iter().all(|s| *s == first_succ) {
self.pred_count[first_succ] -= (successors.len()-1) as u32;
if let Some(&first_succ) = terminator.successors().nth(0) {
if terminator.successors().all(|s| *s == first_succ) {
let count = terminator.successors().count();
self.pred_count[first_succ] -= (count - 1) as u32;
first_succ
} else {
return false
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/util/graphviz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ fn write_edges<W: Write>(source: BasicBlock, mir: &Mir, w: &mut W) -> io::Result
let terminator = mir[source].terminator();
let labels = terminator.kind.fmt_successor_labels();

for (&target, label) in terminator.successors().iter().zip(labels) {
for (&target, label) in terminator.successors().zip(labels) {
writeln!(w, r#" {} -> {} [label="{}"];"#, node(source), node(target), label)?;
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/util/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>, mode: LivenessMode) -> Liveness
for b in mir.basic_blocks().indices().rev() {
// outs[b] = ∪ {ins of successors}
bits.clear();
for &successor in mir.basic_blocks()[b].terminator().successors().into_iter() {
for &successor in mir.basic_blocks()[b].terminator().successors() {
bits.union(&ins[successor]);
}
outs[b].clone_from(&bits);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/mir/analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ pub fn cleanup_kinds<'a, 'tcx>(mir: &mir::Mir<'tcx>) -> IndexVec<mir::BasicBlock
debug!("cleanup_kinds: {:?}/{:?}/{:?} propagating funclet {:?}",
bb, data, result[bb], funclet);

for &succ in data.terminator().successors().iter() {
for &succ in data.terminator().successors() {
let kind = result[succ];
debug!("cleanup_kinds: propagating {:?} to {:?}/{:?}",
funclet, succ, kind);
Expand Down