//! initialization and can otherwise silence errors, if
//! move analysis runs after promotion on broken MIR.
+use rustc::hir::def_id::DefId;
use rustc::mir::*;
use rustc::mir::visit::{PlaceContext, MutatingUseContext, MutVisitor, Visitor};
use rustc::mir::traversal::ReversePostorder;
+use rustc::ty::subst::InternalSubsts;
use rustc::ty::TyCtxt;
use syntax_pos::Span;
new_temp
}
- fn promote_candidate(mut self, candidate: Candidate) {
+ fn promote_candidate(
+ mut self,
+ def_id: DefId,
+ candidate: Candidate,
+ next_promoted_id: usize,
+ ) -> Option<Body<'tcx>> {
let mut operand = {
let promoted = &mut self.promoted;
- let promoted_id = Promoted::new(self.source.promoted.len());
- let mut promoted_place = |ty, span| {
+ let promoted_id = Promoted::new(next_promoted_id);
+ let mut promoted_place = |ty, substs, span| {
promoted.span = span;
promoted.local_decls[RETURN_PLACE] = LocalDecl::new_return_place(ty, span);
Place {
base: PlaceBase::Static(box Static {
- kind: StaticKind::Promoted(promoted_id),
- ty
+ kind: StaticKind::Promoted(promoted_id, substs),
+ ty,
+ def_id,
}),
projection: None,
}
let span = statement.source_info.span;
Operand::Move(Place {
- base: mem::replace(&mut place.base, promoted_place(ty, span).base),
+ base: mem::replace(
+ &mut place.base,
+ promoted_place(
+ ty,
+ InternalSubsts::identity_for_item(self.tcx, def_id),
+ span,
+ ).base
+ ),
projection: None,
})
}
StatementKind::Assign(_, box Rvalue::Repeat(ref mut operand, _)) => {
let ty = operand.ty(local_decls, self.tcx);
let span = statement.source_info.span;
- mem::replace(operand, Operand::Copy(promoted_place(ty, span)))
+ mem::replace(
+ operand,
+ Operand::Copy(
+ promoted_place(
+ ty,
+ InternalSubsts::identity_for_item(self.tcx, def_id),
+ span,
+ )
+ )
+ )
}
_ => bug!()
}
TerminatorKind::Call { ref mut args, .. } => {
let ty = args[index].ty(local_decls, self.tcx);
let span = terminator.source_info.span;
- let operand = Operand::Copy(promoted_place(ty, span));
+ let operand =
+ Operand::Copy(
+ promoted_place(
+ ty,
+ InternalSubsts::identity_for_item(self.tcx, def_id),
+ span));
mem::replace(&mut args[index], operand)
}
// We expected a `TerminatorKind::Call` for which we'd like to promote an
// a function requiring a constant argument and as that constant value
// providing a value whose computation contains another call to a function
// requiring a constant argument.
- TerminatorKind::Goto { .. } => return,
+ TerminatorKind::Goto { .. } => return None,
_ => bug!()
}
}
let span = self.promoted.span;
self.assign(RETURN_PLACE, Rvalue::Use(operand), span);
- self.source.promoted.push(self.promoted);
+ Some(self.promoted)
}
}
}
pub fn promote_candidates<'tcx>(
+ def_id: DefId,
body: &mut Body<'tcx>,
tcx: TyCtxt<'tcx>,
mut temps: IndexVec<Local, TempState>,
candidates: Vec<Candidate>,
-) {
+) -> IndexVec<Promoted, Body<'tcx>> {
// Visit candidates in reverse, in case they're nested.
debug!("promote_candidates({:?})", candidates);
+ let mut promotions = IndexVec::new();
+
for candidate in candidates.into_iter().rev() {
match candidate {
Candidate::Repeat(Location { block, statement_index }) |
// memory usage?
body.source_scopes.clone(),
body.source_scope_local_data.clone(),
- IndexVec::new(),
None,
initial_locals,
IndexVec::new(),
temps: &mut temps,
keep_original: false
};
- promoter.promote_candidate(candidate);
+
+ if let Some(promoted) = promoter.promote_candidate(def_id, candidate, promotions.len()) {
+ promotions.push(promoted);
+ }
}
// Eliminate assignments to, and drops of promoted temps.
_ => {}
}
}
+
+ promotions
}