use rustc::mir::interpret::{ConstEvalErr, ErrorHandled};
use rustc::mir;
use rustc::ty::{self, TyCtxt, query::TyCtxtAt};
-use rustc::ty::layout::{self, LayoutOf, VariantIdx, Size};
+use rustc::ty::layout::{self, LayoutOf, VariantIdx};
use rustc::ty::subst::Subst;
use rustc::traits::Reveal;
use rustc::util::common::ErrorReported;
use crate::interpret::{self,
PlaceTy, MPlaceTy, MemPlace, OpTy, ImmTy, Immediate, Scalar,
RawConst, ConstValue,
- EvalResult, EvalError, InterpError, GlobalId, InterpretCx, StackPopCleanup,
+ InterpResult, InterpErrorInfo, InterpError, GlobalId, InterpretCx, StackPopCleanup,
Allocation, AllocId, MemoryKind,
snapshot, RefTracking,
};
/// that inform us about the generic bounds of the constant. E.g., using an associated constant
/// of a function's generic parameter will require knowledge about the bounds on the generic
/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
-pub(crate) fn mk_eval_cx<'a, 'mir, 'tcx>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub(crate) fn mk_eval_cx<'mir, 'tcx>(
+ tcx: TyCtxt<'tcx, 'tcx>,
span: Span,
param_env: ty::ParamEnv<'tcx>,
-) -> CompileTimeEvalContext<'a, 'mir, 'tcx> {
+) -> CompileTimeEvalContext<'mir, 'tcx> {
debug!("mk_eval_cx: {:?}", param_env);
InterpretCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new())
}
-pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub(crate) fn eval_promoted<'mir, 'tcx>(
+ tcx: TyCtxt<'tcx, 'tcx>,
cid: GlobalId<'tcx>,
- mir: &'mir mir::Body<'tcx>,
+ body: &'mir mir::Body<'tcx>,
param_env: ty::ParamEnv<'tcx>,
-) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
let span = tcx.def_span(cid.instance.def_id());
let mut ecx = mk_eval_cx(tcx, span, param_env);
- eval_body_using_ecx(&mut ecx, cid, mir, param_env)
+ eval_body_using_ecx(&mut ecx, cid, body, param_env)
}
fn mplace_to_const<'tcx>(
- ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
+ ecx: &CompileTimeEvalContext<'_, 'tcx>,
mplace: MPlaceTy<'tcx>,
) -> &'tcx ty::Const<'tcx> {
let MemPlace { ptr, align, meta } = *mplace;
}
fn op_to_const<'tcx>(
- ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
+ ecx: &CompileTimeEvalContext<'_, 'tcx>,
op: OpTy<'tcx>,
) -> &'tcx ty::Const<'tcx> {
// We do not normalize just any data. Only non-union scalars and slices.
),
Scalar::Raw { .. } => (
ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(
- b"" as &[u8], (),
+ b"" as &[u8],
)),
0,
),
// Returns a pointer to where the result lives
fn eval_body_using_ecx<'mir, 'tcx>(
- ecx: &mut CompileTimeEvalContext<'_, 'mir, 'tcx>,
+ ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
cid: GlobalId<'tcx>,
- mir: &'mir mir::Body<'tcx>,
+ body: &'mir mir::Body<'tcx>,
param_env: ty::ParamEnv<'tcx>,
-) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
+) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
debug!("eval_body_using_ecx: {:?}, {:?}", cid, param_env);
let tcx = ecx.tcx.tcx;
- let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
+ let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?;
assert!(!layout.is_unsized());
let ret = ecx.allocate(layout, MemoryKind::Stack);
let name = ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id()));
let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
trace!("eval_body_using_ecx: pushing stack frame for global: {}{}", name, prom);
- assert!(mir.arg_count == 0);
+ assert!(body.arg_count == 0);
ecx.push_stack_frame(
cid.instance,
- mir.span,
- mir,
+ body.span,
+ body,
Some(ret.into()),
StackPopCleanup::None { cleanup: false },
)?;
// Intern the result
let mutability = if tcx.is_mutable_static(cid.instance.def_id()) ||
- !layout.ty.is_freeze(tcx, param_env, mir.span) {
+ !layout.ty.is_freeze(tcx, param_env, body.span) {
Mutability::Mutable
} else {
Mutability::Immutable
Ok(ret)
}
-impl<'tcx> Into<EvalError<'tcx>> for ConstEvalError {
- fn into(self) -> EvalError<'tcx> {
+impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalError {
+ fn into(self) -> InterpErrorInfo<'tcx> {
InterpError::MachineError(self.to_string()).into()
}
}
}
// Extra machine state for CTFE, and the Machine instance
-pub struct CompileTimeInterpreter<'a, 'mir, 'tcx: 'a+'mir> {
+pub struct CompileTimeInterpreter<'mir, 'tcx> {
/// When this value is negative, it indicates the number of interpreter
/// steps *until* the loop detector is enabled. When it is positive, it is
/// the number of steps after the detector has been enabled modulo the loop
pub(super) steps_since_detector_enabled: isize,
/// Extra state to detect loops.
- pub(super) loop_detector: snapshot::InfiniteLoopDetector<'a, 'mir, 'tcx>,
+ pub(super) loop_detector: snapshot::InfiniteLoopDetector<'mir, 'tcx>,
}
-impl<'a, 'mir, 'tcx> CompileTimeInterpreter<'a, 'mir, 'tcx> {
+impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
fn new() -> Self {
CompileTimeInterpreter {
loop_detector: Default::default(),
}
}
-type CompileTimeEvalContext<'a, 'mir, 'tcx> =
- InterpretCx<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>;
+type CompileTimeEvalContext<'mir, 'tcx> =
+ InterpretCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>;
impl interpret::MayLeak for ! {
#[inline(always)]
}
}
-impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
- for CompileTimeInterpreter<'a, 'mir, 'tcx>
-{
+impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 'tcx> {
type MemoryKinds = !;
type PointerTag = ();
const STATIC_KIND: Option<!> = None; // no copying of statics allowed
#[inline(always)]
- fn enforce_validity(_ecx: &InterpretCx<'a, 'mir, 'tcx, Self>) -> bool {
+ fn enforce_validity(_ecx: &InterpretCx<'mir, 'tcx, Self>) -> bool {
false // for now, we don't enforce validity
}
fn find_fn(
- ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
+ ecx: &mut InterpretCx<'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx>],
dest: Option<PlaceTy<'tcx>>,
ret: Option<mir::BasicBlock>,
- ) -> EvalResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
+ ) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
debug!("eval_fn_call: {:?}", instance);
// Only check non-glue functions
if let ty::InstanceDef::Item(def_id) = instance.def {
}
// This is a const fn. Call it.
Ok(Some(match ecx.load_mir(instance.def) {
- Ok(mir) => mir,
+ Ok(body) => body,
Err(err) => {
if let InterpError::NoMirFor(ref path) = err.kind {
return Err(
}
fn call_intrinsic(
- ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
+ ecx: &mut InterpretCx<'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx>],
dest: PlaceTy<'tcx>,
- ) -> EvalResult<'tcx> {
+ ) -> InterpResult<'tcx> {
if ecx.emulate_intrinsic(instance, args, dest)? {
return Ok(());
}
}
fn ptr_op(
- _ecx: &InterpretCx<'a, 'mir, 'tcx, Self>,
+ _ecx: &InterpretCx<'mir, 'tcx, Self>,
_bin_op: mir::BinOp,
_left: ImmTy<'tcx>,
_right: ImmTy<'tcx>,
- ) -> EvalResult<'tcx, (Scalar, bool)> {
+ ) -> InterpResult<'tcx, (Scalar, bool)> {
Err(
ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into(),
)
fn find_foreign_static(
_def_id: DefId,
- _tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
- _memory_extra: &(),
- ) -> EvalResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag>>> {
+ _tcx: TyCtxtAt<'tcx, 'tcx>,
+ ) -> InterpResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag>>> {
err!(ReadForeignStatic)
}
#[inline(always)]
- fn adjust_static_allocation<'b>(
- alloc: &'b Allocation,
+ fn tag_allocation<'b>(
+ _id: AllocId,
+ alloc: Cow<'b, Allocation>,
+ _kind: Option<MemoryKind<!>>,
_memory_extra: &(),
- ) -> Cow<'b, Allocation<Self::PointerTag>> {
- // We do not use a tag so we can just cheaply forward the reference
- Cow::Borrowed(alloc)
+ ) -> (Cow<'b, Allocation<Self::PointerTag>>, Self::PointerTag) {
+ // We do not use a tag so we can just cheaply forward the allocation
+ (alloc, ())
}
#[inline(always)]
- fn new_allocation(
- _size: Size,
- _extra: &Self::MemoryExtra,
- _kind: MemoryKind<!>,
- ) -> (Self::AllocExtra, Self::PointerTag) {
- ((), ())
+ fn tag_static_base_pointer(
+ _id: AllocId,
+ _memory_extra: &(),
+ ) -> Self::PointerTag {
+ ()
}
fn box_alloc(
- _ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
+ _ecx: &mut InterpretCx<'mir, 'tcx, Self>,
_dest: PlaceTy<'tcx>,
- ) -> EvalResult<'tcx> {
+ ) -> InterpResult<'tcx> {
Err(
ConstEvalError::NeedsRfc("heap allocations via `box` keyword".to_string()).into(),
)
}
- fn before_terminator(ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx> {
+ fn before_terminator(ecx: &mut InterpretCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
{
let steps = &mut ecx.machine.steps_since_detector_enabled;
}
#[inline(always)]
- fn stack_push(
- _ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
- ) -> EvalResult<'tcx> {
+ fn stack_push(_ecx: &mut InterpretCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
Ok(())
}
/// Called immediately before a stack frame gets popped.
#[inline(always)]
- fn stack_pop(
- _ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
- _extra: (),
- ) -> EvalResult<'tcx> {
+ fn stack_pop(_ecx: &mut InterpretCx<'mir, 'tcx, Self>, _extra: ()) -> InterpResult<'tcx> {
Ok(())
}
}
-/// Projects to a field of a (variant of a) const.
+/// Extracts a field of a (variant of a) const.
// this function uses `unwrap` copiously, because an already validated constant must have valid
// fields and can thus never fail outside of compiler bugs
-pub fn const_field<'a, 'tcx>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub fn const_field<'tcx>(
+ tcx: TyCtxt<'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
variant: Option<VariantIdx>,
field: mir::Field,
// this function uses `unwrap` copiously, because an already validated constant must have valid
// fields and can thus never fail outside of compiler bugs
-pub fn const_variant_index<'a, 'tcx>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub fn const_variant_index<'tcx>(
+ tcx: TyCtxt<'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
val: &'tcx ty::Const<'tcx>,
) -> VariantIdx {
ecx.read_discriminant(op).unwrap().1
}
-pub fn error_to_const_error<'a, 'mir, 'tcx>(
- ecx: &InterpretCx<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
- mut error: EvalError<'tcx>
+pub fn error_to_const_error<'mir, 'tcx>(
+ ecx: &InterpretCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
+ mut error: InterpErrorInfo<'tcx>,
) -> ConstEvalErr<'tcx> {
error.print_backtrace();
let stacktrace = ecx.generate_stacktrace(None);
ConstEvalErr { error: error.kind, stacktrace, span: ecx.tcx.span }
}
-fn validate_and_turn_into_const<'a, 'tcx>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+fn validate_and_turn_into_const<'tcx>(
+ tcx: TyCtxt<'tcx, 'tcx>,
constant: RawConst<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
})
}
-pub fn const_eval_provider<'a, 'tcx>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub fn const_eval_provider<'tcx>(
+ tcx: TyCtxt<'tcx, 'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
// see comment in const_eval_provider for what we're doing here
})
}
-pub fn const_eval_raw_provider<'a, 'tcx>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub fn const_eval_raw_provider<'tcx>(
+ tcx: TyCtxt<'tcx, 'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc::mir::interpret::ConstEvalRawResult<'tcx> {
// Because the constant is computed twice (once per value of `Reveal`), we are at risk of
let mut ecx = InterpretCx::new(tcx.at(span), key.param_env, CompileTimeInterpreter::new());
let res = ecx.load_mir(cid.instance.def);
- res.map(|mir| {
+ res.map(|body| {
if let Some(index) = cid.promoted {
- &mir.promoted[index]
+ &body.promoted[index]
} else {
- mir
+ body
}
}).and_then(
- |mir| eval_body_using_ecx(&mut ecx, cid, mir, key.param_env)
+ |body| eval_body_using_ecx(&mut ecx, cid, body, key.param_env)
).and_then(|place| {
Ok(RawConst {
alloc_id: place.to_ptr().expect("we allocated this ptr!").alloc_id,