use rustc::middle::lang_items;
use rustc::ty::{self, Ty, TypeFoldable};
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
-use rustc::mir;
+use rustc::mir::{self, Place, PlaceBase};
use rustc::mir::interpret::EvalErrorKind;
use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
use rustc_target::spec::abi::Abi;
// but specified directly in the code. This means it gets promoted
// and we can then extract the value by evaluating the promoted.
mir::Operand::Copy(
- mir::Place::Base(mir::PlaceBase::Promoted(box(index, ty)))
+ Place::Base(PlaceBase::Static(
+ box mir::Static {promoted: Some(promoted), ty, ..}
+ ))
) |
mir::Operand::Move(
- mir::Place::Base(mir::PlaceBase::Promoted(box(index, ty)))
+ Place::Base(PlaceBase::Static(
+ box mir::Static {promoted: Some(promoted), ty, ..}
+ ))
) => {
let param_env = ty::ParamEnv::reveal_all();
let cid = mir::interpret::GlobalId {
instance: self.instance,
- promoted: Some(index),
+ promoted: Some(promoted),
};
let c = bx.tcx().const_eval(param_env.and(cid));
let (llval, ty) = self.simd_shuffle_indices(
let result = match *place {
mir::Place::Base(mir::PlaceBase::Local(_)) => bug!(), // handled above
- mir::Place::Base(mir::PlaceBase::Promoted(box (index, ty))) => {
+ mir::Place::Base(
+ mir::PlaceBase::Static(box mir::Static { def_id: _, ty, promoted: Some(promoted) })
+ ) => {
let param_env = ty::ParamEnv::reveal_all();
let cid = mir::interpret::GlobalId {
instance: self.instance,
- promoted: Some(index),
+ promoted: Some(promoted),
};
let layout = cx.layout_of(self.monomorphize(&ty));
match bx.tcx().const_eval(param_env.and(cid)) {
}
}
}
- mir::Place::Base(mir::PlaceBase::Static(box mir::Static { def_id, ty })) => {
+ mir::Place::Base(
+ mir::PlaceBase::Static(box mir::Static { def_id, ty, promoted: None })
+ ) => {
// NB: The layout of a static may be unsized as is the case when working
// with a static that is an extern_type.
let layout = cx.layout_of(self.monomorphize(&ty));
// The rules for promotion are made by `qualify_consts`, there wouldn't even be a
// `Place::Promoted` if the promotion weren't 100% legal. So we just forward this
Place::Base(PlaceBase::Static(ref static_)) => {
- if static_.promoted.is_some() {
+ if static_.promoted.is_some() ||
+ (static_.promoted.is_none() &&
+ self.infcx.tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable)
+ ){
Ok(RootPlace {
place,
is_local_mutation_allowed,
})
} else {
- if self.infcx.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) {
- Err(place)
- } else {
- Ok(RootPlace {
- place,
- is_local_mutation_allowed,
- })
- }
+ Err(place)
}
}
Place::Projection(ref proj) => {
}
}
Place::Base(PlaceBase::Static(static_)) => {
- if static_.promoted.is_none() {
- tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable)
- } else {
- false
- }
+ static_.promoted.is_none() &&
+ (tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable))
}
Place::Projection(proj) => match proj.elem {
ProjectionElem::Field(..)
Overlap::Disjoint
}
},
- (p1_, p2_) => {
+ (_, _) => {
debug!("place_element_conflict: DISJOINT-STATIC-PROMOTED");
Overlap::Disjoint
}
use rustc::mir::PlaceBase;
use rustc::mir::Static;
Ok(match *mir_place {
- Base(PlaceBase::Static(box Static {promoted: Some(promoted), ty, ..})) => {
+ Base(PlaceBase::Static(box Static {promoted: Some(promoted), ty: _, ..})) => {
let instance = self.frame().instance;
self.const_eval_raw(GlobalId {
instance,
// an `Index` projection would throw us off-track.
_ => None,
},
- Place::Base(PlaceBase::Static(box Static {promoted: Some(promoted), ty, ..})) => {
+ Place::Base(PlaceBase::Static(box Static {promoted: Some(promoted), ty: _, ..})) => {
let generics = self.tcx.generics_of(self.source.def_id());
if generics.requires_monomorphization(self.tcx) {
// FIXME: can't handle code with generics
None => self.super_place(place, _ctxt, _location)
}
},
+ _ => self.super_place(place, _ctxt, _location)
}
}
//! 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;
/// If true, all nested temps are also kept in the
/// source MIR, not moved to the promoted MIR.
- keep_original: bool
+ keep_original: bool,
+ def_id: DefId
}
impl<'a, 'tcx> Promoter<'a, 'tcx> {
}
fn promote_candidate(mut self, candidate: Candidate) {
+ use rustc::mir::Static;
let mut operand = {
+ let def_id = self.def_id.clone();
let promoted = &mut self.promoted;
let promoted_id = Promoted::new(self.source.promoted.len());
let mut promoted_place = |ty, span| {
promoted.span = span;
promoted.local_decls[RETURN_PLACE] =
LocalDecl::new_return_place(ty, span);
- Place::Base(PlaceBase::Promoted(box (promoted_id, ty)))
+ Place::Base(PlaceBase::Static(
+ Box::new(Static { def_id: def_id, ty, promoted: Some(promoted_id) })
+ )
+ )
};
let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
match candidate {
pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mut temps: IndexVec<Local, TempState>,
- candidates: Vec<Candidate>) {
+ candidates: Vec<Candidate>,
+ def_id: DefId) {
// Visit candidates in reverse, in case they're nested.
debug!("promote_candidates({:?})", candidates);
tcx,
source: mir,
temps: &mut temps,
- keep_original: false
+ keep_original: false,
+ def_id
};
promoter.promote_candidate(candidate);
}
match *place {
Place::Base(PlaceBase::Local(_)) => {}
Place::Base(PlaceBase::Static(ref global)) => {
- assert!(global.promoted.is_none(), {});
+ assert!(global.promoted.is_none());
if self.tcx
.get_attrs(global.def_id)
.iter()
};
// Do the actual promotion, now that we know what's viable.
- promote_consts::promote_candidates(mir, tcx, temps, candidates);
+ promote_consts::promote_candidates(mir, tcx, temps, candidates, def_id);
} else {
if !mir.control_flow_destroyed.is_empty() {
let mut locals = mir.vars_iter();