Do not call the const_eval
query in mir interpretation except for caching of nulary intrinsics
This commit is contained in:
parent
a6c60bbe5d
commit
dd9702a059
4 changed files with 8 additions and 34 deletions
|
@ -51,7 +51,7 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
|
|||
|
||||
let gid = GlobalId { instance, promoted: None };
|
||||
|
||||
let place = self.const_eval_raw(gid)?;
|
||||
let place = self.const_eval(gid)?;
|
||||
|
||||
self.copy_op(place.into(), dest)?;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ use rustc_span::{Pos, Span};
|
|||
use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout};
|
||||
|
||||
use super::{
|
||||
Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, OpTy, Operand, Place, PlaceTy,
|
||||
Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, Operand, Place, PlaceTy,
|
||||
ScalarMaybeUninit, StackPopJump,
|
||||
};
|
||||
use crate::transform::validate::equal_up_to_regions;
|
||||
|
@ -875,32 +875,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn const_eval(
|
||||
&self,
|
||||
gid: GlobalId<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
||||
// For statics we pick `ParamEnv::reveal_all`, because statics don't have generics
|
||||
// and thus don't care about the parameter environment. While we could just use
|
||||
// `self.param_env`, that would mean we invoke the query to evaluate the static
|
||||
// with different parameter environments, thus causing the static to be evaluated
|
||||
// multiple times.
|
||||
let param_env = if self.tcx.is_static(gid.instance.def_id()) {
|
||||
ty::ParamEnv::reveal_all()
|
||||
} else {
|
||||
self.param_env
|
||||
};
|
||||
let val = self.tcx.const_eval_global_id(param_env, gid, Some(self.tcx.span))?;
|
||||
|
||||
// Even though `ecx.const_eval` is called from `const_to_op` we can never have a
|
||||
// recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not
|
||||
// return `ConstValue::Unevaluated`, which is the only way that `const_to_op` will call
|
||||
// `ecx.const_eval`.
|
||||
let const_ = ty::Const { val: ty::ConstKind::Value(val), ty };
|
||||
self.const_to_op(&const_, None)
|
||||
}
|
||||
|
||||
pub fn const_eval_raw(
|
||||
pub fn const_eval(
|
||||
&self,
|
||||
gid: GlobalId<'tcx>,
|
||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
|
||||
|
|
|
@ -152,7 +152,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
sym::type_name => self.tcx.mk_static_str(),
|
||||
_ => bug!("already checked for nullary intrinsics"),
|
||||
};
|
||||
let val = self.const_eval(gid, ty)?;
|
||||
let val =
|
||||
self.tcx.const_eval_global_id(self.param_env, gid, Some(self.tcx.span))?;
|
||||
let const_ = ty::Const { val: ty::ConstKind::Value(val), ty };
|
||||
let val = self.const_to_op(&const_, None)?;
|
||||
self.copy_op(val, dest)?;
|
||||
}
|
||||
|
||||
|
|
|
@ -553,11 +553,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
ty::ConstKind::Error(_) => throw_inval!(TypeckError(ErrorReported)),
|
||||
ty::ConstKind::Unevaluated(def, substs, promoted) => {
|
||||
let instance = self.resolve(def.did, substs)?;
|
||||
// We use `const_eval` here and `const_eval_raw` elsewhere in mir interpretation.
|
||||
// The reason we use `const_eval` here is that there can never be a `ty::ConstKind`
|
||||
// that directly mentions the initializer of a static. Statics are always encoded
|
||||
// as constants with vaule `&STATIC`.
|
||||
return Ok(self.const_eval(GlobalId { instance, promoted }, val.ty)?);
|
||||
return Ok(self.const_eval(GlobalId { instance, promoted })?.into());
|
||||
}
|
||||
ty::ConstKind::Infer(..)
|
||||
| ty::ConstKind::Bound(..)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue