Compute the ParamEnv only once and use it to call tcx.const_eval

This commit is contained in:
Oliver Schneider 2018-01-31 09:31:24 +01:00
parent a678044c77
commit 64fbf5d5ad
No known key found for this signature in database
GPG key ID: A69F8D225B3AD7D9
2 changed files with 35 additions and 17 deletions

View file

@ -61,7 +61,7 @@ pub fn eval_body_with_mir<'a, 'mir, 'tcx>(
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) => {
@ -76,7 +76,7 @@ pub fn eval_body<'a, 'tcx>(
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) => {
@ -91,9 +91,12 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
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,
@ -102,6 +105,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
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 {
@ -120,8 +124,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
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
@ -152,7 +155,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
};
Ok((value, ptr, layout.ty))
})();
(res, ecx)
(res, ecx, span)
}
pub struct CompileTimeEvaluator;
@ -499,7 +502,7 @@ pub fn const_eval_provider<'a, 'tcx>(
}
};
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),
@ -509,7 +512,6 @@ pub fn const_eval_provider<'a, 'tcx>(
if tcx.is_static(def_id).is_some() {
ecx.report(&mut err, true, None);
}
let span = ecx.frame().span;
ConstEvalErr {
kind: err.into(),
span,

View file

@ -21,11 +21,12 @@ use rustc::ty::layout::LayoutOf;
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;
@ -56,6 +57,7 @@ struct ConstPropagator<'b, 'a, 'tcx:'a+'b> {
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> {
@ -64,24 +66,40 @@ 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,
)?;
@ -89,10 +107,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
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
@ -108,8 +123,9 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
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)