diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 4e727de53582..3b32fe21adf8 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -99,8 +99,7 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>( eval_body_using_ecx(&mut ecx, cid, Some(mir), param_env) } -// FIXME: This thing is a bad hack. We should get rid of it. Ideally constants are always -// in an allocation. +// FIXME: These two conversion functions are bad hacks. We should just always use allocations. pub fn op_to_const<'tcx>( ecx: &CompileTimeEvalContext<'_, '_, 'tcx>, op: OpTy<'tcx>, @@ -146,6 +145,13 @@ pub fn op_to_const<'tcx>( }; Ok(ty::Const::from_const_value(ecx.tcx.tcx, val, op.layout.ty)) } +pub fn const_to_op<'tcx>( + ecx: &CompileTimeEvalContext<'_, '_, 'tcx>, + cnst: &ty::Const<'tcx>, +) -> EvalResult<'tcx, OpTy<'tcx>> { + let op = ecx.const_value_to_op(cnst.val)?; + Ok(OpTy { op, layout: ecx.layout_of(cnst.ty)? }) +} fn eval_body_and_ecx<'a, 'mir, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -496,7 +502,7 @@ pub fn const_field<'a, 'tcx>( let ecx = mk_eval_cx(tcx, instance, param_env).unwrap(); let result = (|| { // get the operand again - let op = ecx.const_to_op(value)?; + let op = const_to_op(&ecx, value)?; // downcast let down = match variant { None => op, @@ -523,7 +529,7 @@ pub fn const_variant_index<'a, 'tcx>( ) -> EvalResult<'tcx, VariantIdx> { trace!("const_variant_index: {:?}, {:?}", instance, val); let ecx = mk_eval_cx(tcx, instance, param_env).unwrap(); - let op = ecx.const_to_op(val)?; + let op = const_to_op(&ecx, val)?; Ok(ecx.read_discriminant(op)?.1) } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index ce7269d1e783..1d7eae50e718 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -588,18 +588,22 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc Ok(()) } - pub fn const_eval(&self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, &'tcx ty::Const<'tcx>> { + pub fn const_eval_raw( + &self, + gid: GlobalId<'tcx>, + ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { let param_env = if self.tcx.is_static(gid.instance.def_id()).is_some() { ty::ParamEnv::reveal_all() } else { self.param_env }; - self.tcx.const_eval(param_env.and(gid)).map_err(|err| { + let val = self.tcx.const_eval_raw(param_env.and(gid)).map_err(|err| { match err { - ErrorHandled::Reported => EvalErrorKind::ReferencedConstant.into(), - ErrorHandled::TooGeneric => EvalErrorKind::TooGeneric.into(), + ErrorHandled::Reported => EvalErrorKind::ReferencedConstant, + ErrorHandled::TooGeneric => EvalErrorKind::TooGeneric, } - }) + })?; + self.raw_const_to_mplace(val) } pub fn dump_place(&self, place: Place) { diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 16f1e487f59a..5d993cfee084 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -13,7 +13,7 @@ use std::convert::TryInto; -use rustc::{mir, ty}; +use rustc::mir; use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt, VariantIdx}; use rustc::mir::interpret::{ @@ -535,9 +535,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> .collect() } - // Also used e.g. when miri runs into a constant. - // FIXME: Can we avoid converting with ConstValue and Const? We should be using RawConst. - fn const_value_to_op( + // Used when miri runs into a constant, and by CTFE. + // FIXME: CTFE should use allocations, then we can make this private (embed it into + // `eval_operand`, ideally). + pub(crate) fn const_value_to_op( &self, val: ConstValue<'tcx>, ) -> EvalResult<'tcx, Operand> { @@ -545,10 +546,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> match val { ConstValue::Unevaluated(def_id, substs) => { let instance = self.resolve(def_id, substs)?; - self.global_to_op(GlobalId { + Ok(*OpTy::from(self.const_eval_raw(GlobalId { instance, promoted: None, - }) + })?)) } ConstValue::ByRef(id, alloc, offset) => { // We rely on mutability being set correctly in that allocation to prevent writes @@ -566,21 +567,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> Ok(Operand::Immediate(Immediate::Scalar(x.into())).with_default_tag()), } } - pub fn const_to_op( - &self, - cnst: &ty::Const<'tcx>, - ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> { - let op = self.const_value_to_op(cnst.val)?; - Ok(OpTy { op, layout: self.layout_of(cnst.ty)? }) - } - - pub(super) fn global_to_op( - &self, - gid: GlobalId<'tcx> - ) -> EvalResult<'tcx, Operand> { - let cv = self.const_eval(gid)?; - self.const_value_to_op(cv.val) - } /// Read discriminant, return the runtime value as well as the variant index. pub fn read_discriminant( diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 104d66f7bde2..9f248d463507 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -553,16 +553,10 @@ where Ok(match *mir_place { Promoted(ref promoted) => { let instance = self.frame().instance; - let op = self.global_to_op(GlobalId { + self.const_eval_raw(GlobalId { instance, promoted: Some(promoted.0), - })?; - let mplace = op.to_mem_place(); // these are always in memory - let ty = self.monomorphize(promoted.1, self.substs()); - MPlaceTy { - mplace, - layout: self.layout_of(ty)?, - } + })? } Static(ref static_) => { diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 6b8233c941e8..661ca4773b4a 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -29,7 +29,9 @@ use rustc::ty::layout::{ }; use interpret::{self, EvalContext, ScalarMaybeUndef, Immediate, OpTy, MemoryKind}; -use const_eval::{CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_borrowck_eval_cx}; +use const_eval::{ + CompileTimeInterpreter, const_to_op, error_to_const_error, eval_promoted, mk_borrowck_eval_cx +}; use transform::{MirPass, MirSource}; pub struct ConstProp; @@ -262,7 +264,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { source_info: SourceInfo, ) -> Option> { self.ecx.tcx.span = source_info.span; - match self.ecx.const_to_op(c.literal) { + match const_to_op(&self.ecx, c.literal) { Ok(op) => { Some((op, c.span)) },