Compute the ParamEnv only once and use it to call tcx.const_eval
This commit is contained in:
parent
a678044c77
commit
64fbf5d5ad
2 changed files with 35 additions and 17 deletions
|
@ -61,7 +61,7 @@ pub fn eval_body_with_mir<'a, 'mir, 'tcx>(
|
||||||
mir: &'mir mir::Mir<'tcx>,
|
mir: &'mir mir::Mir<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> Option<(Value, Pointer, Ty<'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 {
|
match res {
|
||||||
Ok(val) => Some(val),
|
Ok(val) => Some(val),
|
||||||
Err(mut err) => {
|
Err(mut err) => {
|
||||||
|
@ -76,7 +76,7 @@ pub fn eval_body<'a, 'tcx>(
|
||||||
cid: GlobalId<'tcx>,
|
cid: GlobalId<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> Option<(Value, Pointer, Ty<'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 {
|
match res {
|
||||||
Ok(val) => Some(val),
|
Ok(val) => Some(val),
|
||||||
Err(mut err) => {
|
Err(mut err) => {
|
||||||
|
@ -91,9 +91,12 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
|
||||||
cid: GlobalId<'tcx>,
|
cid: GlobalId<'tcx>,
|
||||||
mir: Option<&'mir mir::Mir<'tcx>>,
|
mir: Option<&'mir mir::Mir<'tcx>>,
|
||||||
param_env: ty::ParamEnv<'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);
|
debug!("eval_body: {:?}, {:?}", cid, param_env);
|
||||||
let mut ecx = EvalContext::new(tcx, param_env, CompileTimeEvaluator, ());
|
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 res = (|| {
|
||||||
let mut mir = match mir {
|
let mut mir = match mir {
|
||||||
Some(mir) => mir,
|
Some(mir) => mir,
|
||||||
|
@ -102,6 +105,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
|
||||||
if let Some(index) = cid.promoted {
|
if let Some(index) = cid.promoted {
|
||||||
mir = &mir.promoted[index];
|
mir = &mir.promoted[index];
|
||||||
}
|
}
|
||||||
|
span = mir.span;
|
||||||
let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
|
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 = tcx.interpret_interner.get_cached(cid.instance.def_id());
|
||||||
let alloc = match alloc {
|
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() {
|
if tcx.is_static(cid.instance.def_id()).is_some() {
|
||||||
tcx.interpret_interner.cache(cid.instance.def_id(), ptr.alloc_id);
|
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, mir.span);
|
||||||
let internally_mutable = !layout.ty.is_freeze(tcx, param_env, span);
|
|
||||||
let mutability = tcx.is_static(cid.instance.def_id());
|
let mutability = tcx.is_static(cid.instance.def_id());
|
||||||
let mutability = if mutability == Some(hir::Mutability::MutMutable) || internally_mutable {
|
let mutability = if mutability == Some(hir::Mutability::MutMutable) || internally_mutable {
|
||||||
Mutability::Mutable
|
Mutability::Mutable
|
||||||
|
@ -152,7 +155,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
|
||||||
};
|
};
|
||||||
Ok((value, ptr, layout.ty))
|
Ok((value, ptr, layout.ty))
|
||||||
})();
|
})();
|
||||||
(res, ecx)
|
(res, ecx, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CompileTimeEvaluator;
|
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)| {
|
res.map(|(miri_value, _, miri_ty)| {
|
||||||
tcx.mk_const(ty::Const {
|
tcx.mk_const(ty::Const {
|
||||||
val: ConstVal::Value(miri_value),
|
val: ConstVal::Value(miri_value),
|
||||||
|
@ -509,7 +512,6 @@ pub fn const_eval_provider<'a, 'tcx>(
|
||||||
if tcx.is_static(def_id).is_some() {
|
if tcx.is_static(def_id).is_some() {
|
||||||
ecx.report(&mut err, true, None);
|
ecx.report(&mut err, true, None);
|
||||||
}
|
}
|
||||||
let span = ecx.frame().span;
|
|
||||||
ConstEvalErr {
|
ConstEvalErr {
|
||||||
kind: err.into(),
|
kind: err.into(),
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -21,11 +21,12 @@ use rustc::ty::layout::LayoutOf;
|
||||||
use rustc::middle::const_val::ConstVal;
|
use rustc::middle::const_val::ConstVal;
|
||||||
use rustc::ty::{TyCtxt, self, Instance};
|
use rustc::ty::{TyCtxt, self, Instance};
|
||||||
use rustc::mir::interpret::{Value, PrimVal, GlobalId};
|
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 transform::{MirPass, MirSource};
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
use rustc_data_structures::indexed_vec::IndexVec;
|
use rustc_data_structures::indexed_vec::IndexVec;
|
||||||
|
use rustc::ty::ParamEnv;
|
||||||
|
|
||||||
pub struct ConstProp;
|
pub struct ConstProp;
|
||||||
|
|
||||||
|
@ -56,6 +57,7 @@ struct ConstPropagator<'b, 'a, 'tcx:'a+'b> {
|
||||||
source: MirSource,
|
source: MirSource,
|
||||||
places: IndexVec<Local, Option<Const<'tcx>>>,
|
places: IndexVec<Local, Option<Const<'tcx>>>,
|
||||||
can_const_prop: IndexVec<Local, bool>,
|
can_const_prop: IndexVec<Local, bool>,
|
||||||
|
param_env: ParamEnv<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, '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>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
source: MirSource,
|
source: MirSource,
|
||||||
) -> ConstPropagator<'b, 'a, 'tcx> {
|
) -> ConstPropagator<'b, 'a, 'tcx> {
|
||||||
|
let param_env = tcx.param_env(source.def_id);
|
||||||
ConstPropagator {
|
ConstPropagator {
|
||||||
mir,
|
mir,
|
||||||
tcx,
|
tcx,
|
||||||
source,
|
source,
|
||||||
|
param_env,
|
||||||
can_const_prop: CanConstProp::check(mir),
|
can_const_prop: CanConstProp::check(mir),
|
||||||
places: IndexVec::from_elem(None, &mir.local_decls),
|
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>> {
|
fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
|
||||||
match c.literal {
|
match c.literal {
|
||||||
Literal::Value { value } => match value.val {
|
Literal::Value { value } => match value.val {
|
||||||
ConstVal::Value(v) => Some((v, value.ty, c.span)),
|
ConstVal::Value(v) => Some((v, value.ty, c.span)),
|
||||||
ConstVal::Unevaluated(did, substs) => {
|
ConstVal::Unevaluated(did, substs) => {
|
||||||
let param_env = self.tcx.param_env(self.source.def_id);
|
|
||||||
let instance = Instance::resolve(
|
let instance = Instance::resolve(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
param_env,
|
self.param_env,
|
||||||
did,
|
did,
|
||||||
substs,
|
substs,
|
||||||
)?;
|
)?;
|
||||||
|
@ -89,10 +107,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
|
||||||
instance,
|
instance,
|
||||||
promoted: None,
|
promoted: None,
|
||||||
};
|
};
|
||||||
let (value, _, ty) = eval_body(self.tcx, cid, param_env)?;
|
self.const_eval(cid, c.span)
|
||||||
let val = (value, ty, c.span);
|
|
||||||
trace!("evaluated {:?} to {:?}", c, val);
|
|
||||||
Some(val)
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// evaluate the promoted and replace the constant with the evaluated result
|
// 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,
|
instance,
|
||||||
promoted: Some(index),
|
promoted: Some(index),
|
||||||
};
|
};
|
||||||
let param_env = self.tcx.param_env(self.source.def_id);
|
// cannot use `const_eval` here, because that would require having the MIR
|
||||||
let (value, _, ty) = eval_body_with_mir(self.tcx, cid, self.mir, param_env)?;
|
// 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);
|
let val = (value, ty, c.span);
|
||||||
trace!("evaluated {:?} to {:?}", c, val);
|
trace!("evaluated {:?} to {:?}", c, val);
|
||||||
Some(val)
|
Some(val)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue