mir: &'mir mir::Mir<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Option<(Value, Pointer, Ty<'tcx>)> {
- let (res, ecx) = eval_body_and_ecx(tcx, cid, Some(mir), param_env);
+ let (res, ecx, _) = eval_body_and_ecx(tcx, cid, Some(mir), param_env);
match res {
Ok(val) => Some(val),
Err(mut err) => {
cid: GlobalId<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Option<(Value, Pointer, Ty<'tcx>)> {
- let (res, ecx) = eval_body_and_ecx(tcx, cid, None, param_env);
+ let (res, ecx, _) = eval_body_and_ecx(tcx, cid, None, param_env);
match res {
Ok(val) => Some(val),
Err(mut err) => {
cid: GlobalId<'tcx>,
mir: Option<&'mir mir::Mir<'tcx>>,
param_env: ty::ParamEnv<'tcx>,
-) -> (EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)>, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>) {
+) -> (EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)>, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>, Span) {
debug!("eval_body: {:?}, {:?}", cid, param_env);
let mut ecx = EvalContext::new(tcx, param_env, CompileTimeEvaluator, ());
+ // we start out with the best span we have
+ // and try improving it down the road when more information is available
+ let mut span = tcx.def_span(cid.instance.def_id());
let res = (|| {
let mut mir = match mir {
Some(mir) => mir,
if let Some(index) = cid.promoted {
mir = &mir.promoted[index];
}
+ span = mir.span;
let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
let alloc = tcx.interpret_interner.get_cached(cid.instance.def_id());
let alloc = match alloc {
if tcx.is_static(cid.instance.def_id()).is_some() {
tcx.interpret_interner.cache(cid.instance.def_id(), ptr.alloc_id);
}
- let span = tcx.def_span(cid.instance.def_id());
- let internally_mutable = !layout.ty.is_freeze(tcx, param_env, span);
+ let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span);
let mutability = tcx.is_static(cid.instance.def_id());
let mutability = if mutability == Some(hir::Mutability::MutMutable) || internally_mutable {
Mutability::Mutable
};
Ok((value, ptr, layout.ty))
})();
- (res, ecx)
+ (res, ecx, span)
}
pub struct CompileTimeEvaluator;
}
};
- let (res, ecx) = eval_body_and_ecx(tcx, cid, None, key.param_env);
+ let (res, ecx, span) = eval_body_and_ecx(tcx, cid, None, key.param_env);
res.map(|(miri_value, _, miri_ty)| {
tcx.mk_const(ty::Const {
val: ConstVal::Value(miri_value),
if tcx.is_static(def_id).is_some() {
ecx.report(&mut err, true, None);
}
- let span = ecx.frame().span;
ConstEvalErr {
kind: err.into(),
span,
use rustc::middle::const_val::ConstVal;
use rustc::ty::{TyCtxt, self, Instance};
use rustc::mir::interpret::{Value, PrimVal, GlobalId};
-use interpret::{eval_body_with_mir, eval_body, mk_borrowck_eval_cx, unary_op, ValTy};
+use interpret::{eval_body_with_mir, mk_borrowck_eval_cx, unary_op, ValTy};
use transform::{MirPass, MirSource};
use syntax::codemap::Span;
use rustc::ty::subst::Substs;
use rustc_data_structures::indexed_vec::IndexVec;
+use rustc::ty::ParamEnv;
pub struct ConstProp;
source: MirSource,
places: IndexVec<Local, Option<Const<'tcx>>>,
can_const_prop: IndexVec<Local, bool>,
+ param_env: ParamEnv<'tcx>,
}
impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
source: MirSource,
) -> ConstPropagator<'b, 'a, 'tcx> {
+ let param_env = tcx.param_env(source.def_id);
ConstPropagator {
mir,
tcx,
source,
+ param_env,
can_const_prop: CanConstProp::check(mir),
places: IndexVec::from_elem(None, &mir.local_decls),
}
}
+ fn const_eval(&self, cid: GlobalId<'tcx>, span: Span) -> Option<Const<'tcx>> {
+ let value = match self.tcx.const_eval(self.param_env.and(cid)) {
+ Ok(val) => val,
+ // FIXME: report some errors
+ Err(_) => return None,
+ };
+ let val = match value.val {
+ ConstVal::Value(v) => v,
+ _ => bug!("eval produced: {:?}", value),
+ };
+ let val = (val, value.ty, span);
+ trace!("evaluated {:?} to {:?}", cid, val);
+ Some(val)
+ }
+
fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
match c.literal {
Literal::Value { value } => match value.val {
ConstVal::Value(v) => Some((v, value.ty, c.span)),
ConstVal::Unevaluated(did, substs) => {
- let param_env = self.tcx.param_env(self.source.def_id);
let instance = Instance::resolve(
self.tcx,
- param_env,
+ self.param_env,
did,
substs,
)?;
instance,
promoted: None,
};
- let (value, _, ty) = eval_body(self.tcx, cid, param_env)?;
- let val = (value, ty, c.span);
- trace!("evaluated {:?} to {:?}", c, val);
- Some(val)
+ self.const_eval(cid, c.span)
},
},
// evaluate the promoted and replace the constant with the evaluated result
instance,
promoted: Some(index),
};
- let param_env = self.tcx.param_env(self.source.def_id);
- let (value, _, ty) = eval_body_with_mir(self.tcx, cid, self.mir, param_env)?;
+ // cannot use `const_eval` here, because that would require having the MIR
+ // for the current function available, but we're producing said MIR right now
+ let (value, _, ty) = eval_body_with_mir(self.tcx, cid, self.mir, self.param_env)?;
let val = (value, ty, c.span);
trace!("evaluated {:?} to {:?}", c, val);
Some(val)