1
Fork 0

Auto merge of #125602 - RalfJung:interpret-mir-lifetime, r=oli-obk

interpret: get rid of 'mir lifetime

I realized our MIR bodies are actually at lifetime `'tcx`, so we don't need to carry around this other lifetime everywhere.

r? `@oli-obk`
This commit is contained in:
bors 2024-05-27 11:01:15 +00:00
commit a59072ec4f
88 changed files with 727 additions and 815 deletions

View file

@ -44,8 +44,8 @@ impl HasStaticRootDefId for DummyMachine {
}
}
impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
interpret::compile_time_machine!(<'mir, 'tcx>);
impl<'tcx> interpret::Machine<'tcx> for DummyMachine {
interpret::compile_time_machine!(<'tcx>);
type MemoryKind = !;
const PANIC_ON_ALLOC_FAIL: bool = true;
@ -53,11 +53,11 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
const ALL_CONSTS_ARE_PRECHECKED: bool = false;
#[inline(always)]
fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
fn enforce_alignment(_ecx: &InterpCx<'tcx, Self>) -> bool {
false // no reason to enforce alignment
}
fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>, _layout: TyAndLayout<'tcx>) -> bool {
fn enforce_validity(_ecx: &InterpCx<'tcx, Self>, _layout: TyAndLayout<'tcx>) -> bool {
false
}
@ -83,26 +83,26 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
}
fn find_mir_or_eval_fn(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_ecx: &mut InterpCx<'tcx, Self>,
_instance: ty::Instance<'tcx>,
_abi: rustc_target::spec::abi::Abi,
_args: &[interpret::FnArg<'tcx, Self::Provenance>],
_destination: &interpret::MPlaceTy<'tcx, Self::Provenance>,
_target: Option<BasicBlock>,
_unwind: UnwindAction,
) -> interpret::InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
) -> interpret::InterpResult<'tcx, Option<(&'tcx Body<'tcx>, ty::Instance<'tcx>)>> {
unimplemented!()
}
fn panic_nounwind(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_ecx: &mut InterpCx<'tcx, Self>,
_msg: &str,
) -> interpret::InterpResult<'tcx> {
unimplemented!()
}
fn call_intrinsic(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_ecx: &mut InterpCx<'tcx, Self>,
_instance: ty::Instance<'tcx>,
_args: &[interpret::OpTy<'tcx, Self::Provenance>],
_destination: &interpret::MPlaceTy<'tcx, Self::Provenance>,
@ -113,7 +113,7 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
}
fn assert_panic(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_ecx: &mut InterpCx<'tcx, Self>,
_msg: &rustc_middle::mir::AssertMessage<'tcx>,
_unwind: UnwindAction,
) -> interpret::InterpResult<'tcx> {
@ -121,7 +121,7 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
}
fn binary_ptr_op(
ecx: &InterpCx<'mir, 'tcx, Self>,
ecx: &InterpCx<'tcx, Self>,
bin_op: BinOp,
left: &interpret::ImmTy<'tcx, Self::Provenance>,
right: &interpret::ImmTy<'tcx, Self::Provenance>,
@ -168,32 +168,30 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
}
fn expose_ptr(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_ecx: &mut InterpCx<'tcx, Self>,
_ptr: interpret::Pointer<Self::Provenance>,
) -> interpret::InterpResult<'tcx> {
unimplemented!()
}
fn init_frame_extra(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_frame: interpret::Frame<'mir, 'tcx, Self::Provenance>,
) -> interpret::InterpResult<
'tcx,
interpret::Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
> {
_ecx: &mut InterpCx<'tcx, Self>,
_frame: interpret::Frame<'tcx, Self::Provenance>,
) -> interpret::InterpResult<'tcx, interpret::Frame<'tcx, Self::Provenance, Self::FrameExtra>>
{
unimplemented!()
}
fn stack<'a>(
_ecx: &'a InterpCx<'mir, 'tcx, Self>,
) -> &'a [interpret::Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>] {
_ecx: &'a InterpCx<'tcx, Self>,
) -> &'a [interpret::Frame<'tcx, Self::Provenance, Self::FrameExtra>] {
// Return an empty stack instead of panicking, as `cur_span` uses it to evaluate constants.
&[]
}
fn stack_mut<'a>(
_ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
) -> &'a mut Vec<interpret::Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>> {
_ecx: &'a mut InterpCx<'tcx, Self>,
) -> &'a mut Vec<interpret::Frame<'tcx, Self::Provenance, Self::FrameExtra>> {
unimplemented!()
}
}

View file

@ -58,13 +58,10 @@ impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalErrKind {
}
}
pub fn get_span_and_frames<'tcx, 'mir>(
pub fn get_span_and_frames<'tcx>(
tcx: TyCtxtAt<'tcx>,
stack: &[Frame<'mir, 'tcx, impl Provenance, impl Sized>],
) -> (Span, Vec<errors::FrameNote>)
where
'tcx: 'mir,
{
stack: &[Frame<'tcx, impl Provenance, impl Sized>],
) -> (Span, Vec<errors::FrameNote>) {
let mut stacktrace = Frame::generate_stacktrace_from_stack(stack);
// Filter out `requires_caller_location` frames.
stacktrace.retain(|frame| !frame.instance.def.requires_caller_location(*tcx));
@ -161,9 +158,9 @@ where
/// Emit a lint from a const-eval situation.
// Even if this is unused, please don't remove it -- chances are we will need to emit a lint during const-eval again in the future!
pub(super) fn lint<'tcx, 'mir, L>(
pub(super) fn lint<'tcx, L>(
tcx: TyCtxtAt<'tcx>,
machine: &CompileTimeInterpreter<'mir, 'tcx>,
machine: &CompileTimeInterpreter<'tcx>,
lint: &'static rustc_session::lint::Lint,
decorator: impl FnOnce(Vec<errors::FrameNote>) -> L,
) where

View file

@ -31,10 +31,10 @@ use crate::CTRL_C_RECEIVED;
// Returns a pointer to where the result lives
#[instrument(level = "trace", skip(ecx, body))]
fn eval_body_using_ecx<'mir, 'tcx, R: InterpretationResult<'tcx>>(
ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
ecx: &mut CompileTimeEvalContext<'tcx>,
cid: GlobalId<'tcx>,
body: &'mir mir::Body<'tcx>,
body: &'tcx mir::Body<'tcx>,
) -> InterpResult<'tcx, R> {
trace!(?ecx.param_env);
let tcx = *ecx.tcx;
@ -134,12 +134,12 @@ fn eval_body_using_ecx<'mir, 'tcx, R: InterpretationResult<'tcx>>(
/// 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_to_read_const_val<'mir, 'tcx>(
pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>(
tcx: TyCtxt<'tcx>,
root_span: Span,
param_env: ty::ParamEnv<'tcx>,
can_access_mut_global: CanAccessMutGlobal,
) -> CompileTimeEvalContext<'mir, 'tcx> {
) -> CompileTimeEvalContext<'tcx> {
debug!("mk_eval_cx: {:?}", param_env);
InterpCx::new(
tcx,
@ -151,12 +151,12 @@ pub(crate) fn mk_eval_cx_to_read_const_val<'mir, 'tcx>(
/// Create an interpreter context to inspect the given `ConstValue`.
/// Returns both the context and an `OpTy` that represents the constant.
pub fn mk_eval_cx_for_const_val<'mir, 'tcx>(
pub fn mk_eval_cx_for_const_val<'tcx>(
tcx: TyCtxtAt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
val: mir::ConstValue<'tcx>,
ty: Ty<'tcx>,
) -> Option<(CompileTimeEvalContext<'mir, 'tcx>, OpTy<'tcx>)> {
) -> Option<(CompileTimeEvalContext<'tcx>, OpTy<'tcx>)> {
let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, param_env, CanAccessMutGlobal::No);
let op = ecx.const_val_to_op(val, ty, None).ok()?;
Some((ecx, op))
@ -170,7 +170,7 @@ pub fn mk_eval_cx_for_const_val<'mir, 'tcx>(
/// encounter an `Indirect` they cannot handle.
#[instrument(skip(ecx), level = "debug")]
pub(super) fn op_to_const<'tcx>(
ecx: &CompileTimeEvalContext<'_, 'tcx>,
ecx: &CompileTimeEvalContext<'tcx>,
op: &OpTy<'tcx>,
for_diagnostics: bool,
) -> ConstValue<'tcx> {
@ -326,16 +326,16 @@ pub trait InterpretationResult<'tcx> {
/// This function takes the place where the result of the evaluation is stored
/// and prepares it for returning it in the appropriate format needed by the specific
/// evaluation query.
fn make_result<'mir>(
fn make_result(
mplace: MPlaceTy<'tcx>,
ecx: &mut InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
) -> Self;
}
impl<'tcx> InterpretationResult<'tcx> for ConstAlloc<'tcx> {
fn make_result<'mir>(
fn make_result(
mplace: MPlaceTy<'tcx>,
_ecx: &mut InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
_ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
) -> Self {
ConstAlloc { alloc_id: mplace.ptr().provenance.unwrap().alloc_id(), ty: mplace.layout.ty }
}
@ -416,8 +416,8 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
}
#[inline(always)]
fn const_validate_mplace<'mir, 'tcx>(
ecx: &InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
fn const_validate_mplace<'tcx>(
ecx: &InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
mplace: &MPlaceTy<'tcx>,
cid: GlobalId<'tcx>,
) -> Result<(), ErrorHandled> {
@ -446,8 +446,8 @@ fn const_validate_mplace<'mir, 'tcx>(
}
#[inline(always)]
fn report_validation_error<'mir, 'tcx>(
ecx: &InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
fn report_validation_error<'tcx>(
ecx: &InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
error: InterpErrorInfo<'tcx>,
alloc_id: AllocId,
) -> ErrorHandled {

View file

@ -45,7 +45,7 @@ const TINY_LINT_TERMINATOR_LIMIT: usize = 20;
const PROGRESS_INDICATOR_START: usize = 4_000_000;
/// Extra machine state for CTFE, and the Machine instance
pub struct CompileTimeInterpreter<'mir, 'tcx> {
pub struct CompileTimeInterpreter<'tcx> {
/// The number of terminators that have been evaluated.
///
/// This is used to produce lints informing the user that the compiler is not stuck.
@ -53,7 +53,7 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
pub(super) num_evaluated_steps: usize,
/// The virtual call stack.
pub(super) stack: Vec<Frame<'mir, 'tcx>>,
pub(super) stack: Vec<Frame<'tcx>>,
/// Pattern matching on consts with references would be unsound if those references
/// could point to anything mutable. Therefore, when evaluating consts and when constructing valtrees,
@ -90,7 +90,7 @@ impl From<bool> for CanAccessMutGlobal {
}
}
impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
impl<'tcx> CompileTimeInterpreter<'tcx> {
pub(crate) fn new(
can_access_mut_global: CanAccessMutGlobal,
check_alignment: CheckAlignment,
@ -164,8 +164,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxIndexMap<K, V> {
}
}
pub(crate) type CompileTimeEvalContext<'mir, 'tcx> =
InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>;
pub(crate) type CompileTimeEvalContext<'tcx> = InterpCx<'tcx, CompileTimeInterpreter<'tcx>>;
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum MemoryKind {
@ -197,7 +196,7 @@ impl interpret::MayLeak for ! {
}
}
impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
impl<'tcx> CompileTimeEvalContext<'tcx> {
fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
@ -371,25 +370,25 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
}
}
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 'tcx> {
compile_time_machine!(<'mir, 'tcx>);
impl<'tcx> interpret::Machine<'tcx> for CompileTimeInterpreter<'tcx> {
compile_time_machine!(<'tcx>);
type MemoryKind = MemoryKind;
const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error
#[inline(always)]
fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
fn enforce_alignment(ecx: &InterpCx<'tcx, Self>) -> bool {
matches!(ecx.machine.check_alignment, CheckAlignment::Error)
}
#[inline(always)]
fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>, layout: TyAndLayout<'tcx>) -> bool {
fn enforce_validity(ecx: &InterpCx<'tcx, Self>, layout: TyAndLayout<'tcx>) -> bool {
ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks || layout.abi.is_uninhabited()
}
fn load_mir(
ecx: &InterpCx<'mir, 'tcx, Self>,
ecx: &InterpCx<'tcx, Self>,
instance: ty::InstanceDef<'tcx>,
) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
match instance {
@ -410,14 +409,14 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
}
fn find_mir_or_eval_fn(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
ecx: &mut InterpCx<'tcx, Self>,
orig_instance: ty::Instance<'tcx>,
_abi: CallAbi,
args: &[FnArg<'tcx>],
dest: &MPlaceTy<'tcx>,
ret: Option<mir::BasicBlock>,
_unwind: mir::UnwindAction, // unwinding is not supported in consts
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> {
debug!("find_mir_or_eval_fn: {:?}", orig_instance);
// Replace some functions.
@ -448,7 +447,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
Ok(Some((ecx.load_mir(instance.def, None)?, orig_instance)))
}
fn panic_nounwind(ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx> {
fn panic_nounwind(ecx: &mut InterpCx<'tcx, Self>, msg: &str) -> InterpResult<'tcx> {
let msg = Symbol::intern(msg);
let span = ecx.find_closest_untracked_caller_location();
let (file, line, col) = ecx.location_triple_for_span(span);
@ -456,7 +455,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
}
fn call_intrinsic(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
ecx: &mut InterpCx<'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx, Self::Provenance>,
@ -555,7 +554,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
}
fn assert_panic(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
ecx: &mut InterpCx<'tcx, Self>,
msg: &AssertMessage<'tcx>,
_unwind: mir::UnwindAction,
) -> InterpResult<'tcx> {
@ -586,7 +585,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
}
fn binary_ptr_op(
_ecx: &InterpCx<'mir, 'tcx, Self>,
_ecx: &InterpCx<'tcx, Self>,
_bin_op: mir::BinOp,
_left: &ImmTy<'tcx>,
_right: &ImmTy<'tcx>,
@ -594,7 +593,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
throw_unsup_format!("pointer arithmetic or comparison is not supported at compile-time");
}
fn increment_const_eval_counter(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
fn increment_const_eval_counter(ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> {
// The step limit has already been hit in a previous call to `increment_const_eval_counter`.
if let Some(new_steps) = ecx.machine.num_evaluated_steps.checked_add(1) {
@ -650,16 +649,16 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
}
#[inline(always)]
fn expose_ptr(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx> {
fn expose_ptr(_ecx: &mut InterpCx<'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx> {
// This is only reachable with -Zunleash-the-miri-inside-of-you.
throw_unsup_format!("exposing pointers is not possible at compile-time")
}
#[inline(always)]
fn init_frame_extra(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
frame: Frame<'mir, 'tcx>,
) -> InterpResult<'tcx, Frame<'mir, 'tcx>> {
ecx: &mut InterpCx<'tcx, Self>,
frame: Frame<'tcx>,
) -> InterpResult<'tcx, Frame<'tcx>> {
// Enforce stack size limit. Add 1 because this is run before the new frame is pushed.
if !ecx.recursion_limit.value_within_limit(ecx.stack().len() + 1) {
throw_exhaust!(StackFrameLimitReached)
@ -670,15 +669,15 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
#[inline(always)]
fn stack<'a>(
ecx: &'a InterpCx<'mir, 'tcx, Self>,
) -> &'a [Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>] {
ecx: &'a InterpCx<'tcx, Self>,
) -> &'a [Frame<'tcx, Self::Provenance, Self::FrameExtra>] {
&ecx.machine.stack
}
#[inline(always)]
fn stack_mut<'a>(
ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
) -> &'a mut Vec<Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>> {
ecx: &'a mut InterpCx<'tcx, Self>,
) -> &'a mut Vec<Frame<'tcx, Self::Provenance, Self::FrameExtra>> {
&mut ecx.machine.stack
}
@ -715,7 +714,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
}
fn retag_ptr_value(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
ecx: &mut InterpCx<'tcx, Self>,
_kind: mir::RetagKind,
val: &ImmTy<'tcx, CtfeProvenance>,
) -> InterpResult<'tcx, ImmTy<'tcx, CtfeProvenance>> {
@ -756,10 +755,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
Ok(())
}
fn before_alloc_read(
ecx: &InterpCx<'mir, 'tcx, Self>,
alloc_id: AllocId,
) -> InterpResult<'tcx> {
fn before_alloc_read(ecx: &InterpCx<'tcx, Self>, alloc_id: AllocId) -> InterpResult<'tcx> {
// Check if this is the currently evaluated static.
if Some(alloc_id) == ecx.machine.static_root_ids.map(|(id, _)| id) {
return Err(ConstEvalErrKind::RecursiveStatic.into());

View file

@ -21,7 +21,7 @@ use crate::interpret::{
#[instrument(skip(ecx), level = "debug")]
fn branches<'tcx>(
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
ecx: &CompileTimeEvalContext<'tcx>,
place: &MPlaceTy<'tcx>,
n: usize,
variant: Option<VariantIdx>,
@ -59,7 +59,7 @@ fn branches<'tcx>(
#[instrument(skip(ecx), level = "debug")]
fn slice_branches<'tcx>(
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
ecx: &CompileTimeEvalContext<'tcx>,
place: &MPlaceTy<'tcx>,
num_nodes: &mut usize,
) -> ValTreeCreationResult<'tcx> {
@ -77,7 +77,7 @@ fn slice_branches<'tcx>(
#[instrument(skip(ecx), level = "debug")]
fn const_to_valtree_inner<'tcx>(
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
ecx: &CompileTimeEvalContext<'tcx>,
place: &MPlaceTy<'tcx>,
num_nodes: &mut usize,
) -> ValTreeCreationResult<'tcx> {
@ -219,7 +219,7 @@ fn reconstruct_place_meta<'tcx>(
#[instrument(skip(ecx), level = "debug", ret)]
fn create_valtree_place<'tcx>(
ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>,
ecx: &mut CompileTimeEvalContext<'tcx>,
layout: TyAndLayout<'tcx>,
valtree: ty::ValTree<'tcx>,
) -> MPlaceTy<'tcx> {
@ -364,7 +364,7 @@ pub fn valtree_to_const_value<'tcx>(
/// Put a valtree into memory and return a reference to that.
fn valtree_to_ref<'tcx>(
ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>,
ecx: &mut CompileTimeEvalContext<'tcx>,
valtree: ty::ValTree<'tcx>,
pointee_ty: Ty<'tcx>,
) -> Immediate {
@ -380,7 +380,7 @@ fn valtree_to_ref<'tcx>(
#[instrument(skip(ecx), level = "debug")]
fn valtree_into_mplace<'tcx>(
ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>,
ecx: &mut CompileTimeEvalContext<'tcx>,
place: &MPlaceTy<'tcx>,
valtree: ty::ValTree<'tcx>,
) {
@ -457,6 +457,6 @@ fn valtree_into_mplace<'tcx>(
}
}
fn dump_place<'tcx>(ecx: &CompileTimeEvalContext<'tcx, 'tcx>, place: &MPlaceTy<'tcx>) {
fn dump_place<'tcx>(ecx: &CompileTimeEvalContext<'tcx>, place: &MPlaceTy<'tcx>) {
trace!("{:?}", ecx.dump_place(&PlaceTy::from(place.clone())));
}

View file

@ -19,7 +19,7 @@ use super::{
use crate::fluent_generated as fluent;
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
pub fn cast(
&mut self,
src: &OpTy<'tcx, M::Provenance>,
@ -324,13 +324,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
use rustc_type_ir::TyKind::*;
fn adjust_nan<
'mir,
'tcx: 'mir,
M: Machine<'mir, 'tcx>,
'tcx,
M: Machine<'tcx>,
F1: rustc_apfloat::Float + FloatConvert<F2>,
F2: rustc_apfloat::Float,
>(
ecx: &InterpCx<'mir, 'tcx, M>,
ecx: &InterpCx<'tcx, M>,
f1: F1,
f2: F2,
) -> F2 {

View file

@ -12,7 +12,7 @@ use super::{
err_ub, throw_ub, ImmTy, InterpCx, InterpResult, Machine, Readable, Scalar, Writeable,
};
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Writes the discriminant of the given variant.
///
/// If the variant is uninhabited, this is UB.

View file

@ -34,7 +34,7 @@ use crate::errors;
use crate::util;
use crate::{fluent_generated as fluent, ReportErrorExt};
pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
pub struct InterpCx<'tcx, M: Machine<'tcx>> {
/// Stores the `Machine` instance.
///
/// Note: the stack is provided by the machine.
@ -49,7 +49,7 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
pub(crate) param_env: ty::ParamEnv<'tcx>,
/// The virtual memory system.
pub memory: Memory<'mir, 'tcx, M>,
pub memory: Memory<'tcx, M>,
/// The recursion limit (cached from `tcx.recursion_limit(())`)
pub recursion_limit: Limit,
@ -90,12 +90,12 @@ impl Drop for SpanGuard {
}
/// A stack frame.
pub struct Frame<'mir, 'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> {
pub struct Frame<'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> {
////////////////////////////////////////////////////////////////////////////////
// Function and callsite information
////////////////////////////////////////////////////////////////////////////////
/// The MIR for the function called on this frame.
pub body: &'mir mir::Body<'tcx>,
pub body: &'tcx mir::Body<'tcx>,
/// The def_id and args of the current function.
pub instance: ty::Instance<'tcx>,
@ -232,8 +232,8 @@ impl<'tcx, Prov: Provenance> LocalState<'tcx, Prov> {
}
}
impl<'mir, 'tcx, Prov: Provenance> Frame<'mir, 'tcx, Prov> {
pub fn with_extra<Extra>(self, extra: Extra) -> Frame<'mir, 'tcx, Prov, Extra> {
impl<'tcx, Prov: Provenance> Frame<'tcx, Prov> {
pub fn with_extra<Extra>(self, extra: Extra) -> Frame<'tcx, Prov, Extra> {
Frame {
body: self.body,
instance: self.instance,
@ -247,7 +247,7 @@ impl<'mir, 'tcx, Prov: Provenance> Frame<'mir, 'tcx, Prov> {
}
}
impl<'mir, 'tcx, Prov: Provenance, Extra> Frame<'mir, 'tcx, Prov, Extra> {
impl<'tcx, Prov: Provenance, Extra> Frame<'tcx, Prov, Extra> {
/// Get the current location within the Frame.
///
/// If this is `Left`, we are not currently executing any particular statement in
@ -345,16 +345,16 @@ impl<'tcx> FrameInfo<'tcx> {
}
}
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> HasDataLayout for InterpCx<'tcx, M> {
#[inline]
fn data_layout(&self) -> &TargetDataLayout {
&self.tcx.data_layout
}
}
impl<'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for InterpCx<'mir, 'tcx, M>
impl<'tcx, M> layout::HasTyCtxt<'tcx> for InterpCx<'tcx, M>
where
M: Machine<'mir, 'tcx>,
M: Machine<'tcx>,
{
#[inline]
fn tcx(&self) -> TyCtxt<'tcx> {
@ -362,16 +362,16 @@ where
}
}
impl<'mir, 'tcx, M> layout::HasParamEnv<'tcx> for InterpCx<'mir, 'tcx, M>
impl<'tcx, M> layout::HasParamEnv<'tcx> for InterpCx<'tcx, M>
where
M: Machine<'mir, 'tcx>,
M: Machine<'tcx>,
{
fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.param_env
}
}
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOfHelpers<'tcx> for InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> LayoutOfHelpers<'tcx> for InterpCx<'tcx, M> {
type LayoutOfResult = InterpResult<'tcx, TyAndLayout<'tcx>>;
#[inline]
@ -391,7 +391,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOfHelpers<'tcx> for InterpC
}
}
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'tcx, M> {
type FnAbiOfResult = InterpResult<'tcx, &'tcx FnAbi<'tcx, Ty<'tcx>>>;
fn handle_fn_abi_err(
@ -484,7 +484,7 @@ pub fn format_interp_error<'tcx>(dcx: &DiagCtxt, e: InterpErrorInfo<'tcx>) -> St
s
}
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
pub fn new(
tcx: TyCtxt<'tcx>,
root_span: Span,
@ -517,14 +517,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
#[inline(always)]
pub(crate) fn stack(&self) -> &[Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>] {
pub(crate) fn stack(&self) -> &[Frame<'tcx, M::Provenance, M::FrameExtra>] {
M::stack(self)
}
#[inline(always)]
pub(crate) fn stack_mut(
&mut self,
) -> &mut Vec<Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>> {
pub(crate) fn stack_mut(&mut self) -> &mut Vec<Frame<'tcx, M::Provenance, M::FrameExtra>> {
M::stack_mut(self)
}
@ -536,17 +534,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
#[inline(always)]
pub fn frame(&self) -> &Frame<'mir, 'tcx, M::Provenance, M::FrameExtra> {
pub fn frame(&self) -> &Frame<'tcx, M::Provenance, M::FrameExtra> {
self.stack().last().expect("no call frames exist")
}
#[inline(always)]
pub fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx, M::Provenance, M::FrameExtra> {
pub fn frame_mut(&mut self) -> &mut Frame<'tcx, M::Provenance, M::FrameExtra> {
self.stack_mut().last_mut().expect("no call frames exist")
}
#[inline(always)]
pub fn body(&self) -> &'mir mir::Body<'tcx> {
pub fn body(&self) -> &'tcx mir::Body<'tcx> {
self.frame().body
}
@ -602,7 +600,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
T: TypeFoldable<TyCtxt<'tcx>>,
>(
&self,
frame: &Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>,
frame: &Frame<'tcx, M::Provenance, M::FrameExtra>,
value: T,
) -> Result<T, ErrorHandled> {
frame
@ -680,7 +678,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
#[inline(always)]
pub(super) fn layout_of_local(
&self,
frame: &Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>,
frame: &Frame<'tcx, M::Provenance, M::FrameExtra>,
local: mir::Local,
layout: Option<TyAndLayout<'tcx>>,
) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
@ -803,7 +801,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
pub fn push_stack_frame(
&mut self,
instance: ty::Instance<'tcx>,
body: &'mir mir::Body<'tcx>,
body: &'tcx mir::Body<'tcx>,
return_place: &MPlaceTy<'tcx, M::Provenance>,
return_to_block: StackPopCleanup,
) -> InterpResult<'tcx> {
@ -1205,10 +1203,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
#[must_use]
pub fn dump_place(
&self,
place: &PlaceTy<'tcx, M::Provenance>,
) -> PlacePrinter<'_, 'mir, 'tcx, M> {
pub fn dump_place(&self, place: &PlaceTy<'tcx, M::Provenance>) -> PlacePrinter<'_, 'tcx, M> {
PlacePrinter { ecx: self, place: *place.place() }
}
@ -1220,14 +1215,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
#[doc(hidden)]
/// Helper struct for the `dump_place` function.
pub struct PlacePrinter<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
ecx: &'a InterpCx<'mir, 'tcx, M>,
pub struct PlacePrinter<'a, 'tcx, M: Machine<'tcx>> {
ecx: &'a InterpCx<'tcx, M>,
place: Place<M::Provenance>,
}
impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug
for PlacePrinter<'a, 'mir, 'tcx, M>
{
impl<'a, 'tcx, M: Machine<'tcx>> std::fmt::Debug for PlacePrinter<'a, 'tcx, M> {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.place {
Place::Local { local, offset, locals_addr } => {

View file

@ -29,8 +29,7 @@ use super::{err_ub, AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind
use crate::const_eval;
use crate::errors::NestedStaticInThreadLocal;
pub trait CompileTimeMachine<'mir, 'tcx: 'mir, T> = Machine<
'mir,
pub trait CompileTimeMachine<'tcx, T> = Machine<
'tcx,
MemoryKind = T,
Provenance = CtfeProvenance,
@ -46,7 +45,7 @@ pub trait HasStaticRootDefId {
fn static_def_id(&self) -> Option<LocalDefId>;
}
impl HasStaticRootDefId for const_eval::CompileTimeInterpreter<'_, '_> {
impl HasStaticRootDefId for const_eval::CompileTimeInterpreter<'_> {
fn static_def_id(&self) -> Option<LocalDefId> {
Some(self.static_root_ids?.1)
}
@ -59,8 +58,8 @@ impl HasStaticRootDefId for const_eval::CompileTimeInterpreter<'_, '_> {
/// already mutable (as a sanity check).
///
/// Returns an iterator over all relocations referred to by this allocation.
fn intern_shallow<'rt, 'mir, 'tcx, T, M: CompileTimeMachine<'mir, 'tcx, T>>(
ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
fn intern_shallow<'rt, 'tcx, T, M: CompileTimeMachine<'tcx, T>>(
ecx: &'rt mut InterpCx<'tcx, M>,
alloc_id: AllocId,
mutability: Mutability,
) -> Result<impl Iterator<Item = CtfeProvenance> + 'tcx, ()> {
@ -146,12 +145,8 @@ pub enum InternResult {
///
/// For `InternKind::Static` the root allocation will not be interned, but must be handled by the caller.
#[instrument(level = "debug", skip(ecx))]
pub fn intern_const_alloc_recursive<
'mir,
'tcx: 'mir,
M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>,
>(
ecx: &mut InterpCx<'mir, 'tcx, M>,
pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval::MemoryKind>>(
ecx: &mut InterpCx<'tcx, M>,
intern_kind: InternKind,
ret: &MPlaceTy<'tcx>,
) -> Result<(), InternResult> {
@ -290,13 +285,8 @@ pub fn intern_const_alloc_recursive<
/// Intern `ret`. This function assumes that `ret` references no other allocation.
#[instrument(level = "debug", skip(ecx))]
pub fn intern_const_alloc_for_constprop<
'mir,
'tcx: 'mir,
T,
M: CompileTimeMachine<'mir, 'tcx, T>,
>(
ecx: &mut InterpCx<'mir, 'tcx, M>,
pub fn intern_const_alloc_for_constprop<'tcx, T, M: CompileTimeMachine<'tcx, T>>(
ecx: &mut InterpCx<'tcx, M>,
alloc_id: AllocId,
) -> InterpResult<'tcx, ()> {
if ecx.tcx.try_get_global_alloc(alloc_id).is_some() {
@ -315,19 +305,14 @@ pub fn intern_const_alloc_for_constprop<
Ok(())
}
impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>>
InterpCx<'mir, 'tcx, M>
{
impl<'tcx, M: super::intern::CompileTimeMachine<'tcx, !>> InterpCx<'tcx, M> {
/// A helper function that allocates memory for the layout given and gives you access to mutate
/// it. Once your own mutation code is done, the backing `Allocation` is removed from the
/// current `Memory` and interned as read-only into the global memory.
pub fn intern_with_temp_alloc(
&mut self,
layout: TyAndLayout<'tcx>,
f: impl FnOnce(
&mut InterpCx<'mir, 'tcx, M>,
&PlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx, ()>,
f: impl FnOnce(&mut InterpCx<'tcx, M>, &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx, ()>,
) -> InterpResult<'tcx, AllocId> {
// `allocate` picks a fresh AllocId that we will associate with its data below.
let dest = self.allocate(layout, MemoryKind::Stack)?;

View file

@ -98,7 +98,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
})
}
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Returns `true` if emulation happened.
/// Here we implement the intrinsics that are common to all Miri instances; individual machines can add their own
/// intrinsic handling.
@ -605,9 +605,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Copy `count*size_of::<T>()` many bytes from `*src` to `*dst`.
pub(crate) fn copy_intrinsic(
&mut self,
src: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
dst: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
src: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
dst: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
count: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
nonoverlapping: bool,
) -> InterpResult<'tcx> {
let count = self.read_target_usize(count)?;
@ -634,8 +634,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Does a *typed* swap of `*left` and `*right`.
fn typed_swap_intrinsic(
&mut self,
left: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
right: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
left: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
right: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
) -> InterpResult<'tcx> {
let left = self.deref_pointer(left)?;
let right = self.deref_pointer(right)?;
@ -651,9 +651,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
pub(crate) fn write_bytes_intrinsic(
&mut self,
dst: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
byte: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
dst: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
byte: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
count: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
) -> InterpResult<'tcx> {
let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap())?;
@ -673,9 +673,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
pub(crate) fn compare_bytes_intrinsic(
&mut self,
left: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
right: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
byte_count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
left: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
right: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
byte_count: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
let left = self.read_pointer(left)?;
let right = self.read_pointer(right)?;
@ -691,14 +691,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
pub(crate) fn raw_eq_intrinsic(
&mut self,
lhs: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
rhs: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
lhs: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
rhs: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
let layout = self.layout_of(lhs.layout.ty.builtin_deref(true).unwrap())?;
assert!(layout.is_sized());
let get_bytes = |this: &InterpCx<'mir, 'tcx, M>,
op: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
let get_bytes = |this: &InterpCx<'tcx, M>,
op: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
size|
-> InterpResult<'tcx, &[u8]> {
let ptr = this.read_pointer(op)?;

View file

@ -94,7 +94,7 @@ pub trait AllocMap<K: Hash + Eq, V> {
/// Methods of this trait signifies a point where CTFE evaluation would fail
/// and some use case dependent behaviour can instead be applied.
pub trait Machine<'mir, 'tcx: 'mir>: Sized {
pub trait Machine<'tcx>: Sized {
/// Additional memory kinds a machine wishes to distinguish from the builtin ones
type MemoryKind: Debug + std::fmt::Display + MayLeak + Eq + 'static;
@ -145,12 +145,12 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
const ALL_CONSTS_ARE_PRECHECKED: bool = true;
/// Whether memory accesses should be alignment-checked.
fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
fn enforce_alignment(ecx: &InterpCx<'tcx, Self>) -> bool;
/// Gives the machine a chance to detect more misalignment than the built-in checks would catch.
#[inline(always)]
fn alignment_check(
_ecx: &InterpCx<'mir, 'tcx, Self>,
_ecx: &InterpCx<'tcx, Self>,
_alloc_id: AllocId,
_alloc_align: Align,
_alloc_kind: AllocKind,
@ -161,22 +161,22 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
}
/// Whether to enforce the validity invariant for a specific layout.
fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>, layout: TyAndLayout<'tcx>) -> bool;
fn enforce_validity(ecx: &InterpCx<'tcx, Self>, layout: TyAndLayout<'tcx>) -> bool;
/// Whether function calls should be [ABI](CallAbi)-checked.
fn enforce_abi(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
fn enforce_abi(_ecx: &InterpCx<'tcx, Self>) -> bool {
true
}
/// Whether Assert(OverflowNeg) and Assert(Overflow) MIR terminators should actually
/// check for overflow.
fn ignore_optional_overflow_checks(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
fn ignore_optional_overflow_checks(_ecx: &InterpCx<'tcx, Self>) -> bool;
/// Entry point for obtaining the MIR of anything that should get evaluated.
/// So not just functions and shims, but also const/static initializers, anonymous
/// constants, ...
fn load_mir(
ecx: &InterpCx<'mir, 'tcx, Self>,
ecx: &InterpCx<'tcx, Self>,
instance: ty::InstanceDef<'tcx>,
) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
Ok(ecx.tcx.instance_mir(instance))
@ -193,19 +193,19 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// Passing `dest`and `ret` in the same `Option` proved very annoying when only one of them
/// was used.
fn find_mir_or_eval_fn(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
ecx: &mut InterpCx<'tcx, Self>,
instance: ty::Instance<'tcx>,
abi: CallAbi,
args: &[FnArg<'tcx, Self::Provenance>],
destination: &MPlaceTy<'tcx, Self::Provenance>,
target: Option<mir::BasicBlock>,
unwind: mir::UnwindAction,
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>>;
) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>>;
/// Execute `fn_val`. It is the hook's responsibility to advance the instruction
/// pointer as appropriate.
fn call_extra_fn(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
ecx: &mut InterpCx<'tcx, Self>,
fn_val: Self::ExtraFnVal,
abi: CallAbi,
args: &[FnArg<'tcx, Self::Provenance>],
@ -220,7 +220,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// Returns `None` if the intrinsic was fully handled.
/// Otherwise, returns an `Instance` of the function that implements the intrinsic.
fn call_intrinsic(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
ecx: &mut InterpCx<'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Self::Provenance>],
destination: &MPlaceTy<'tcx, Self::Provenance>,
@ -230,17 +230,17 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// Called to evaluate `Assert` MIR terminators that trigger a panic.
fn assert_panic(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
ecx: &mut InterpCx<'tcx, Self>,
msg: &mir::AssertMessage<'tcx>,
unwind: mir::UnwindAction,
) -> InterpResult<'tcx>;
/// Called to trigger a non-unwinding panic.
fn panic_nounwind(_ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx>;
fn panic_nounwind(_ecx: &mut InterpCx<'tcx, Self>, msg: &str) -> InterpResult<'tcx>;
/// Called when unwinding reached a state where execution should be terminated.
fn unwind_terminate(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
ecx: &mut InterpCx<'tcx, Self>,
reason: mir::UnwindTerminateReason,
) -> InterpResult<'tcx>;
@ -248,7 +248,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
///
/// Returns a (value, overflowed) pair if the operation succeeded
fn binary_ptr_op(
ecx: &InterpCx<'mir, 'tcx, Self>,
ecx: &InterpCx<'tcx, Self>,
bin_op: mir::BinOp,
left: &ImmTy<'tcx, Self::Provenance>,
right: &ImmTy<'tcx, Self::Provenance>,
@ -257,7 +257,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// Generate the NaN returned by a float operation, given the list of inputs.
/// (This is all inputs, not just NaN inputs!)
fn generate_nan<F1: Float + FloatConvert<F2>, F2: Float>(
_ecx: &InterpCx<'mir, 'tcx, Self>,
_ecx: &InterpCx<'tcx, Self>,
_inputs: &[F1],
) -> F2 {
// By default we always return the preferred NaN.
@ -266,14 +266,14 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// Called before a basic block terminator is executed.
#[inline]
fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
fn before_terminator(_ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> {
Ok(())
}
/// Called when the interpreter encounters a `StatementKind::ConstEvalCounter` instruction.
/// You can use this to detect long or endlessly running programs.
#[inline]
fn increment_const_eval_counter(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
fn increment_const_eval_counter(_ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> {
Ok(())
}
@ -293,7 +293,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// Return the `AllocId` for the given thread-local static in the current thread.
fn thread_local_static_pointer(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_ecx: &mut InterpCx<'tcx, Self>,
def_id: DefId,
) -> InterpResult<'tcx, Pointer<Self::Provenance>> {
throw_unsup!(ThreadLocalStatic(def_id))
@ -301,20 +301,20 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// Return the `AllocId` for the given `extern static`.
fn extern_static_pointer(
ecx: &InterpCx<'mir, 'tcx, Self>,
ecx: &InterpCx<'tcx, Self>,
def_id: DefId,
) -> InterpResult<'tcx, Pointer<Self::Provenance>>;
/// "Int-to-pointer cast"
fn ptr_from_addr_cast(
ecx: &InterpCx<'mir, 'tcx, Self>,
ecx: &InterpCx<'tcx, Self>,
addr: u64,
) -> InterpResult<'tcx, Pointer<Option<Self::Provenance>>>;
/// Marks a pointer as exposed, allowing it's provenance
/// to be recovered. "Pointer-to-int cast"
fn expose_ptr(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
ecx: &mut InterpCx<'tcx, Self>,
ptr: Pointer<Self::Provenance>,
) -> InterpResult<'tcx>;
@ -325,7 +325,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
///
/// When this fails, that means the pointer does not point to a live allocation.
fn ptr_get_alloc(
ecx: &InterpCx<'mir, 'tcx, Self>,
ecx: &InterpCx<'tcx, Self>,
ptr: Pointer<Self::Provenance>,
) -> Option<(AllocId, Size, Self::ProvenanceExtra)>;
@ -345,7 +345,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// cache the result. (This relies on `AllocMap::get_or` being able to add the
/// owned allocation to the map even when the map is shared.)
fn adjust_allocation<'b>(
ecx: &InterpCx<'mir, 'tcx, Self>,
ecx: &InterpCx<'tcx, Self>,
id: AllocId,
alloc: Cow<'b, Allocation>,
kind: Option<MemoryKind<Self::MemoryKind>>,
@ -359,7 +359,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// `kind` is the kind of the allocation the pointer points to; it can be `None` when
/// it's a global and `GLOBAL_KIND` is `None`.
fn adjust_alloc_root_pointer(
ecx: &InterpCx<'mir, 'tcx, Self>,
ecx: &InterpCx<'tcx, Self>,
ptr: Pointer,
kind: Option<MemoryKind<Self::MemoryKind>>,
) -> InterpResult<'tcx, Pointer<Self::Provenance>>;
@ -370,7 +370,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// is triggered, `targets[0]` when the assembly falls through, or diverge in case of
/// `InlineAsmOptions::NORETURN` being set.
fn eval_inline_asm(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_ecx: &mut InterpCx<'tcx, Self>,
_template: &'tcx [InlineAsmTemplatePiece],
_operands: &[mir::InlineAsmOperand<'tcx>],
_options: InlineAsmOptions,
@ -406,10 +406,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
///
/// Used to prevent statics from self-initializing by reading from their own memory
/// as it is being initialized.
fn before_alloc_read(
_ecx: &InterpCx<'mir, 'tcx, Self>,
_alloc_id: AllocId,
) -> InterpResult<'tcx> {
fn before_alloc_read(_ecx: &InterpCx<'tcx, Self>, _alloc_id: AllocId) -> InterpResult<'tcx> {
Ok(())
}
@ -444,7 +441,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// Returns the possibly adjusted pointer.
#[inline]
fn retag_ptr_value(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_ecx: &mut InterpCx<'tcx, Self>,
_kind: mir::RetagKind,
val: &ImmTy<'tcx, Self::Provenance>,
) -> InterpResult<'tcx, ImmTy<'tcx, Self::Provenance>> {
@ -455,7 +452,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// Replaces all pointers stored in the given place.
#[inline]
fn retag_place_contents(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_ecx: &mut InterpCx<'tcx, Self>,
_kind: mir::RetagKind,
_place: &PlaceTy<'tcx, Self::Provenance>,
) -> InterpResult<'tcx> {
@ -467,7 +464,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// These places need to be protected to make sure the program cannot tell whether the
/// argument/return value was actually copied or passed in-place..
fn protect_in_place_function_argument(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
ecx: &mut InterpCx<'tcx, Self>,
mplace: &MPlaceTy<'tcx, Self::Provenance>,
) -> InterpResult<'tcx> {
// Without an aliasing model, all we can do is put `Uninit` into the place.
@ -477,29 +474,29 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// Called immediately before a new stack frame gets pushed.
fn init_frame_extra(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
frame: Frame<'mir, 'tcx, Self::Provenance>,
) -> InterpResult<'tcx, Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>>;
ecx: &mut InterpCx<'tcx, Self>,
frame: Frame<'tcx, Self::Provenance>,
) -> InterpResult<'tcx, Frame<'tcx, Self::Provenance, Self::FrameExtra>>;
/// Borrow the current thread's stack.
fn stack<'a>(
ecx: &'a InterpCx<'mir, 'tcx, Self>,
) -> &'a [Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>];
ecx: &'a InterpCx<'tcx, Self>,
) -> &'a [Frame<'tcx, Self::Provenance, Self::FrameExtra>];
/// Mutably borrow the current thread's stack.
fn stack_mut<'a>(
ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
) -> &'a mut Vec<Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>>;
ecx: &'a mut InterpCx<'tcx, Self>,
) -> &'a mut Vec<Frame<'tcx, Self::Provenance, Self::FrameExtra>>;
/// Called immediately after a stack frame got pushed and its locals got initialized.
fn after_stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
fn after_stack_push(_ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> {
Ok(())
}
/// Called just before the return value is copied to the caller-provided return place.
fn before_stack_pop(
_ecx: &InterpCx<'mir, 'tcx, Self>,
_frame: &Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
_ecx: &InterpCx<'tcx, Self>,
_frame: &Frame<'tcx, Self::Provenance, Self::FrameExtra>,
) -> InterpResult<'tcx> {
Ok(())
}
@ -508,8 +505,8 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// The `locals` have already been destroyed!
#[inline(always)]
fn after_stack_pop(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_frame: Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
_ecx: &mut InterpCx<'tcx, Self>,
_frame: Frame<'tcx, Self::Provenance, Self::FrameExtra>,
unwinding: bool,
) -> InterpResult<'tcx, StackPopJump> {
// By default, we do not support unwinding from panics
@ -521,7 +518,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// but before the local's stack frame is updated to point to that memory.
#[inline(always)]
fn after_local_allocated(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_ecx: &mut InterpCx<'tcx, Self>,
_local: mir::Local,
_mplace: &MPlaceTy<'tcx, Self::Provenance>,
) -> InterpResult<'tcx> {
@ -532,7 +529,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// but this hook has the chance to do some pre/postprocessing.
#[inline(always)]
fn eval_mir_constant<F>(
ecx: &InterpCx<'mir, 'tcx, Self>,
ecx: &InterpCx<'tcx, Self>,
val: mir::Const<'tcx>,
span: Span,
layout: Option<TyAndLayout<'tcx>>,
@ -540,7 +537,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
) -> InterpResult<'tcx, OpTy<'tcx, Self::Provenance>>
where
F: Fn(
&InterpCx<'mir, 'tcx, Self>,
&InterpCx<'tcx, Self>,
mir::Const<'tcx>,
Span,
Option<TyAndLayout<'tcx>>,
@ -552,7 +549,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
/// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines
/// (CTFE and ConstProp) use the same instance. Here, we share that code.
pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
pub macro compile_time_machine(<$tcx: lifetime>) {
type Provenance = CtfeProvenance;
type ProvenanceExtra = bool; // the "immutable" flag
@ -567,13 +564,13 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
type Bytes = Box<[u8]>;
#[inline(always)]
fn ignore_optional_overflow_checks(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
fn ignore_optional_overflow_checks(_ecx: &InterpCx<$tcx, Self>) -> bool {
false
}
#[inline(always)]
fn unwind_terminate(
_ecx: &mut InterpCx<$mir, $tcx, Self>,
_ecx: &mut InterpCx<$tcx, Self>,
_reason: mir::UnwindTerminateReason,
) -> InterpResult<$tcx> {
unreachable!("unwinding cannot happen during compile-time evaluation")
@ -581,7 +578,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
#[inline(always)]
fn call_extra_fn(
_ecx: &mut InterpCx<$mir, $tcx, Self>,
_ecx: &mut InterpCx<$tcx, Self>,
fn_val: !,
_abi: CallAbi,
_args: &[FnArg<$tcx>],
@ -594,7 +591,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
#[inline(always)]
fn adjust_allocation<'b>(
_ecx: &InterpCx<$mir, $tcx, Self>,
_ecx: &InterpCx<$tcx, Self>,
_id: AllocId,
alloc: Cow<'b, Allocation>,
_kind: Option<MemoryKind<Self::MemoryKind>>,
@ -603,7 +600,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
}
fn extern_static_pointer(
ecx: &InterpCx<$mir, $tcx, Self>,
ecx: &InterpCx<$tcx, Self>,
def_id: DefId,
) -> InterpResult<$tcx, Pointer> {
// Use the `AllocId` associated with the `DefId`. Any actual *access* will fail.
@ -612,7 +609,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
#[inline(always)]
fn adjust_alloc_root_pointer(
_ecx: &InterpCx<$mir, $tcx, Self>,
_ecx: &InterpCx<$tcx, Self>,
ptr: Pointer<CtfeProvenance>,
_kind: Option<MemoryKind<Self::MemoryKind>>,
) -> InterpResult<$tcx, Pointer<CtfeProvenance>> {
@ -621,7 +618,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
#[inline(always)]
fn ptr_from_addr_cast(
_ecx: &InterpCx<$mir, $tcx, Self>,
_ecx: &InterpCx<$tcx, Self>,
addr: u64,
) -> InterpResult<$tcx, Pointer<Option<CtfeProvenance>>> {
// Allow these casts, but make the pointer not dereferenceable.
@ -632,7 +629,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
#[inline(always)]
fn ptr_get_alloc(
_ecx: &InterpCx<$mir, $tcx, Self>,
_ecx: &InterpCx<$tcx, Self>,
ptr: Pointer<CtfeProvenance>,
) -> Option<(AllocId, Size, Self::ProvenanceExtra)> {
// We know `offset` is relative to the allocation, so we can use `into_parts`.

View file

@ -96,7 +96,7 @@ impl<'tcx, Other> FnVal<'tcx, Other> {
// `Memory` has to depend on the `Machine` because some of its operations
// (e.g., `get`) call a `Machine` hook.
pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
pub struct Memory<'tcx, M: Machine<'tcx>> {
/// Allocations local to this instance of the interpreter. The kind
/// helps ensure that the same mechanism is used for allocation and
/// deallocation. When an allocation is not found here, it is a
@ -142,7 +142,7 @@ pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Bo
alloc_id: AllocId,
}
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> Memory<'tcx, M> {
pub fn new() -> Self {
Memory {
alloc_map: M::MemoryMap::default(),
@ -158,7 +158,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
}
}
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Call this to turn untagged "global" pointers (obtained via `tcx`) into
/// the machine pointer to the allocation. Must never be used
/// for any other pointers, nor for TLS statics.
@ -524,7 +524,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
}
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// This function is used by Miri's provenance GC to remove unreachable entries from the dead_alloc_map.
pub fn remove_unreachable_allocs(&mut self, reachable_allocs: &FxHashSet<AllocId>) {
// Unlike all the other GC helpers where we check if an `AllocId` is found in the interpreter or
@ -536,7 +536,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
/// Allocation accessors
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Helper function to obtain a global (tcx) allocation.
/// This attempts to return a reference to an existing allocation if
/// one can be found in `tcx`. That, however, is only possible if `tcx` and
@ -888,14 +888,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Create a lazy debug printer that prints the given allocation and all allocations it points
/// to, recursively.
#[must_use]
pub fn dump_alloc<'a>(&'a self, id: AllocId) -> DumpAllocs<'a, 'mir, 'tcx, M> {
pub fn dump_alloc<'a>(&'a self, id: AllocId) -> DumpAllocs<'a, 'tcx, M> {
self.dump_allocs(vec![id])
}
/// Create a lazy debug printer for a list of allocations and all allocations they point to,
/// recursively.
#[must_use]
pub fn dump_allocs<'a>(&'a self, mut allocs: Vec<AllocId>) -> DumpAllocs<'a, 'mir, 'tcx, M> {
pub fn dump_allocs<'a>(&'a self, mut allocs: Vec<AllocId>) -> DumpAllocs<'a, 'tcx, M> {
allocs.sort();
allocs.dedup();
DumpAllocs { ecx: self, allocs }
@ -975,12 +975,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
#[doc(hidden)]
/// There's no way to use this directly, it's just a helper struct for the `dump_alloc(s)` methods.
pub struct DumpAllocs<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
ecx: &'a InterpCx<'mir, 'tcx, M>,
pub struct DumpAllocs<'a, 'tcx, M: Machine<'tcx>> {
ecx: &'a InterpCx<'tcx, M>,
allocs: Vec<AllocId>,
}
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, 'mir, 'tcx, M> {
impl<'a, 'tcx, M: Machine<'tcx>> std::fmt::Debug for DumpAllocs<'a, 'tcx, M> {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// Cannot be a closure because it is generic in `Prov`, `Extra`.
fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
@ -1125,7 +1125,7 @@ impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Pr
}
}
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Reads the given number of bytes from memory, and strips their provenance if possible.
/// Returns them as a slice.
///
@ -1338,7 +1338,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
/// Machine pointer introspection.
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Test if this value might be null.
/// If the machine does not support ptr-to-int casts, this is conservative.
pub fn scalar_may_be_null(&self, scalar: Scalar<M::Provenance>) -> InterpResult<'tcx, bool> {

View file

@ -374,21 +374,21 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for ImmTy<'tcx, Prov> {
MemPlaceMeta::None
}
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
&self,
offset: Size,
_mode: OffsetMode,
meta: MemPlaceMeta<Prov>,
layout: TyAndLayout<'tcx>,
ecx: &InterpCx<'mir, 'tcx, M>,
ecx: &InterpCx<'tcx, M>,
) -> InterpResult<'tcx, Self> {
assert_matches!(meta, MemPlaceMeta::None); // we can't store this anywhere anyway
Ok(self.offset_(offset, layout, ecx))
}
fn to_op<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn to_op<M: Machine<'tcx, Provenance = Prov>>(
&self,
_ecx: &InterpCx<'mir, 'tcx, M>,
_ecx: &InterpCx<'tcx, M>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
Ok(self.clone().into())
}
@ -457,13 +457,13 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for OpTy<'tcx, Prov> {
}
}
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
&self,
offset: Size,
mode: OffsetMode,
meta: MemPlaceMeta<Prov>,
layout: TyAndLayout<'tcx>,
ecx: &InterpCx<'mir, 'tcx, M>,
ecx: &InterpCx<'tcx, M>,
) -> InterpResult<'tcx, Self> {
match self.as_mplace_or_imm() {
Left(mplace) => Ok(mplace.offset_with_meta(offset, mode, meta, layout, ecx)?.into()),
@ -475,9 +475,9 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for OpTy<'tcx, Prov> {
}
}
fn to_op<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn to_op<M: Machine<'tcx, Provenance = Prov>>(
&self,
_ecx: &InterpCx<'mir, 'tcx, M>,
_ecx: &InterpCx<'tcx, M>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
Ok(self.clone())
}
@ -509,7 +509,7 @@ impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for ImmTy<'tcx, Prov> {
}
}
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`.
/// Returns `None` if the layout does not permit loading this as a value.
///

View file

@ -11,7 +11,7 @@ use tracing::trace;
use super::{err_ub, throw_ub, ImmTy, InterpCx, Machine};
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
fn three_way_compare<T: Ord>(&self, lhs: T, rhs: T) -> ImmTy<'tcx, M::Provenance> {
let res = Ord::cmp(&lhs, &rhs);
return ImmTy::from_ordering(res, *self.tcx);

View file

@ -77,12 +77,12 @@ impl<Prov: Provenance> MemPlace<Prov> {
#[inline]
// Not called `offset_with_meta` to avoid confusion with the trait method.
fn offset_with_meta_<'mir, 'tcx, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn offset_with_meta_<'tcx, M: Machine<'tcx, Provenance = Prov>>(
self,
offset: Size,
mode: OffsetMode,
meta: MemPlaceMeta<Prov>,
ecx: &InterpCx<'mir, 'tcx, M>,
ecx: &InterpCx<'tcx, M>,
) -> InterpResult<'tcx, Self> {
debug_assert!(
!meta.has_meta() || self.meta.has_meta(),
@ -162,20 +162,20 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for MPlaceTy<'tcx, Prov> {
self.mplace.meta
}
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
&self,
offset: Size,
mode: OffsetMode,
meta: MemPlaceMeta<Prov>,
layout: TyAndLayout<'tcx>,
ecx: &InterpCx<'mir, 'tcx, M>,
ecx: &InterpCx<'tcx, M>,
) -> InterpResult<'tcx, Self> {
Ok(MPlaceTy { mplace: self.mplace.offset_with_meta_(offset, mode, meta, ecx)?, layout })
}
fn to_op<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn to_op<M: Machine<'tcx, Provenance = Prov>>(
&self,
_ecx: &InterpCx<'mir, 'tcx, M>,
_ecx: &InterpCx<'tcx, M>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
Ok(self.clone().into())
}
@ -274,13 +274,13 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for PlaceTy<'tcx, Prov> {
}
}
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
&self,
offset: Size,
mode: OffsetMode,
meta: MemPlaceMeta<Prov>,
layout: TyAndLayout<'tcx>,
ecx: &InterpCx<'mir, 'tcx, M>,
ecx: &InterpCx<'tcx, M>,
) -> InterpResult<'tcx, Self> {
Ok(match self.as_mplace_or_local() {
Left(mplace) => mplace.offset_with_meta(offset, mode, meta, layout, ecx)?.into(),
@ -305,9 +305,9 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for PlaceTy<'tcx, Prov> {
})
}
fn to_op<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn to_op<M: Machine<'tcx, Provenance = Prov>>(
&self,
ecx: &InterpCx<'mir, 'tcx, M>,
ecx: &InterpCx<'tcx, M>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
ecx.place_to_op(self)
}
@ -341,9 +341,9 @@ pub trait Writeable<'tcx, Prov: Provenance>: Projectable<'tcx, Prov> {
&self,
) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize, TyAndLayout<'tcx>)>;
fn force_mplace<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn force_mplace<M: Machine<'tcx, Provenance = Prov>>(
&self,
ecx: &mut InterpCx<'mir, 'tcx, M>,
ecx: &mut InterpCx<'tcx, M>,
) -> InterpResult<'tcx, MPlaceTy<'tcx, Prov>>;
}
@ -357,9 +357,9 @@ impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for PlaceTy<'tcx, Prov> {
}
#[inline(always)]
fn force_mplace<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn force_mplace<M: Machine<'tcx, Provenance = Prov>>(
&self,
ecx: &mut InterpCx<'mir, 'tcx, M>,
ecx: &mut InterpCx<'tcx, M>,
) -> InterpResult<'tcx, MPlaceTy<'tcx, Prov>> {
ecx.force_allocation(self)
}
@ -374,19 +374,19 @@ impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for MPlaceTy<'tcx, Prov> {
}
#[inline(always)]
fn force_mplace<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn force_mplace<M: Machine<'tcx, Provenance = Prov>>(
&self,
_ecx: &mut InterpCx<'mir, 'tcx, M>,
_ecx: &mut InterpCx<'tcx, M>,
) -> InterpResult<'tcx, MPlaceTy<'tcx, Prov>> {
Ok(self.clone())
}
}
// FIXME: Working around https://github.com/rust-lang/rust/issues/54385
impl<'mir, 'tcx: 'mir, Prov, M> InterpCx<'mir, 'tcx, M>
impl<'tcx, Prov, M> InterpCx<'tcx, M>
where
Prov: Provenance,
M: Machine<'mir, 'tcx, Provenance = Prov>,
M: Machine<'tcx, Provenance = Prov>,
{
pub fn ptr_with_meta_to_mplace(
&self,

View file

@ -43,9 +43,9 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug {
fn meta(&self) -> MemPlaceMeta<Prov>;
/// Get the length of a slice/string/array stored here.
fn len<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn len<M: Machine<'tcx, Provenance = Prov>>(
&self,
ecx: &InterpCx<'mir, 'tcx, M>,
ecx: &InterpCx<'tcx, M>,
) -> InterpResult<'tcx, u64> {
let layout = self.layout();
if layout.is_unsized() {
@ -65,29 +65,29 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug {
}
/// Offset the value by the given amount, replacing the layout and metadata.
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
&self,
offset: Size,
mode: OffsetMode,
meta: MemPlaceMeta<Prov>,
layout: TyAndLayout<'tcx>,
ecx: &InterpCx<'mir, 'tcx, M>,
ecx: &InterpCx<'tcx, M>,
) -> InterpResult<'tcx, Self>;
fn offset<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn offset<M: Machine<'tcx, Provenance = Prov>>(
&self,
offset: Size,
layout: TyAndLayout<'tcx>,
ecx: &InterpCx<'mir, 'tcx, M>,
ecx: &InterpCx<'tcx, M>,
) -> InterpResult<'tcx, Self> {
assert!(layout.is_sized());
self.offset_with_meta(offset, OffsetMode::Inbounds, MemPlaceMeta::None, layout, ecx)
}
fn transmute<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn transmute<M: Machine<'tcx, Provenance = Prov>>(
&self,
layout: TyAndLayout<'tcx>,
ecx: &InterpCx<'mir, 'tcx, M>,
ecx: &InterpCx<'tcx, M>,
) -> InterpResult<'tcx, Self> {
assert!(self.layout().is_sized() && layout.is_sized());
assert_eq!(self.layout().size, layout.size);
@ -96,9 +96,9 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug {
/// Convert this to an `OpTy`. This might be an irreversible transformation, but is useful for
/// reading from this thing.
fn to_op<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
fn to_op<M: Machine<'tcx, Provenance = Prov>>(
&self,
ecx: &InterpCx<'mir, 'tcx, M>,
ecx: &InterpCx<'tcx, M>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>>;
}
@ -113,9 +113,9 @@ pub struct ArrayIterator<'tcx, 'a, Prov: Provenance, P: Projectable<'tcx, Prov>>
impl<'tcx, 'a, Prov: Provenance, P: Projectable<'tcx, Prov>> ArrayIterator<'tcx, 'a, Prov, P> {
/// Should be the same `ecx` on each call, and match the one used to create the iterator.
pub fn next<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
pub fn next<M: Machine<'tcx, Provenance = Prov>>(
&mut self,
ecx: &InterpCx<'mir, 'tcx, M>,
ecx: &InterpCx<'tcx, M>,
) -> InterpResult<'tcx, Option<(u64, P)>> {
let Some(idx) = self.range.next() else { return Ok(None) };
// We use `Wrapping` here since the offset has already been checked when the iterator was created.
@ -133,10 +133,10 @@ impl<'tcx, 'a, Prov: Provenance, P: Projectable<'tcx, Prov>> ArrayIterator<'tcx,
}
// FIXME: Working around https://github.com/rust-lang/rust/issues/54385
impl<'mir, 'tcx: 'mir, Prov, M> InterpCx<'mir, 'tcx, M>
impl<'tcx, Prov, M> InterpCx<'tcx, M>
where
Prov: Provenance,
M: Machine<'mir, 'tcx, Provenance = Prov>,
M: Machine<'tcx, Provenance = Prov>,
{
/// Offset a pointer to project to a field of a struct/union. Unlike `place_field`, this is
/// always possible without allocating, so it can take `&self`. Also return the field's layout.

View file

@ -16,7 +16,7 @@ use super::{
};
use crate::util;
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Returns `true` as long as there are more things to do.
///
/// This is used by [priroda](https://github.com/oli-obk/priroda)

View file

@ -46,7 +46,7 @@ impl<'tcx, Prov: Provenance> FnArg<'tcx, Prov> {
}
}
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Make a copy of the given fn_arg. Any `InPlace` are degenerated to copies, no protection of the
/// original memory occurs.
pub fn copy_fn_arg(&self, arg: &FnArg<'tcx, M::Provenance>) -> OpTy<'tcx, M::Provenance> {

View file

@ -7,7 +7,7 @@ use tracing::trace;
use super::util::ensure_monomorphic_enough;
use super::{InterpCx, Machine};
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Creates a dynamic vtable for the given type and vtable origin. This is used only for
/// objects.
///

View file

@ -82,9 +82,9 @@ where
}
impl<'tcx> InterpretationResult<'tcx> for mir::interpret::ConstAllocation<'tcx> {
fn make_result<'mir>(
fn make_result(
mplace: MPlaceTy<'tcx>,
ecx: &mut InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
) -> Self {
let alloc_id = mplace.ptr().provenance.unwrap().alloc_id();
let alloc = ecx.memory.alloc_map.swap_remove(&alloc_id).unwrap().1;
@ -92,8 +92,8 @@ impl<'tcx> InterpretationResult<'tcx> for mir::interpret::ConstAllocation<'tcx>
}
}
pub(crate) fn create_static_alloc<'mir, 'tcx: 'mir>(
ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
pub(crate) fn create_static_alloc<'tcx>(
ecx: &mut CompileTimeEvalContext<'tcx>,
static_def_id: LocalDefId,
layout: TyAndLayout<'tcx>,
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {

View file

@ -205,7 +205,7 @@ fn write_path(out: &mut String, path: &[PathElem]) {
}
}
struct ValidityVisitor<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> {
/// The `path` may be pushed to, but the part that is present when a function
/// starts must not be changed! `visit_fields` and `visit_array` rely on
/// this stack discipline.
@ -213,10 +213,10 @@ struct ValidityVisitor<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
ref_tracking: Option<&'rt mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Vec<PathElem>>>,
/// `None` indicates this is not validating for CTFE (but for runtime).
ctfe_mode: Option<CtfeValidationMode>,
ecx: &'rt InterpCx<'mir, 'tcx, M>,
ecx: &'rt InterpCx<'tcx, M>,
}
impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M> {
impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
fn aggregate_field_path_elem(&mut self, layout: TyAndLayout<'tcx>, field: usize) -> PathElem {
// First, check if we are projecting to a variant.
match layout.variants {
@ -706,10 +706,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
/// Returns whether the allocation is mutable, and whether it's actually a static.
/// For "root" statics we look at the type to account for interior
/// mutability; for nested statics we have no type and directly use the annotated mutability.
fn mutability<'mir, 'tcx: 'mir>(
ecx: &InterpCx<'mir, 'tcx, impl Machine<'mir, 'tcx>>,
alloc_id: AllocId,
) -> Mutability {
fn mutability<'tcx>(ecx: &InterpCx<'tcx, impl Machine<'tcx>>, alloc_id: AllocId) -> Mutability {
// Let's see what kind of memory this points to.
// We're not using `try_global_alloc` since dangling pointers have already been handled.
match ecx.tcx.global_alloc(alloc_id) {
@ -751,13 +748,11 @@ fn mutability<'mir, 'tcx: 'mir>(
}
}
impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
for ValidityVisitor<'rt, 'mir, 'tcx, M>
{
impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, 'tcx, M> {
type V = OpTy<'tcx, M::Provenance>;
#[inline(always)]
fn ecx(&self) -> &InterpCx<'mir, 'tcx, M> {
fn ecx(&self) -> &InterpCx<'tcx, M> {
self.ecx
}
@ -1009,7 +1004,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
}
}
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
fn validate_operand_internal(
&self,
op: &OpTy<'tcx, M::Provenance>,

View file

@ -13,11 +13,11 @@ use std::num::NonZero;
use super::{throw_inval, InterpCx, MPlaceTy, Machine, Projectable};
/// How to traverse a value and what to do when we are at the leaves.
pub trait ValueVisitor<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized {
pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
type V: Projectable<'tcx, M::Provenance> + From<MPlaceTy<'tcx, M::Provenance>>;
/// The visitor must have an `InterpCx` in it.
fn ecx(&self) -> &InterpCx<'mir, 'tcx, M>;
fn ecx(&self) -> &InterpCx<'tcx, M>;
/// `read_discriminant` can be hooked for better error messages.
#[inline(always)]

View file

@ -11,8 +11,8 @@ use crate::const_eval::{mk_eval_cx_to_read_const_val, CanAccessMutGlobal, Compil
use crate::interpret::*;
/// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
fn alloc_caller_location<'mir, 'tcx>(
ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
fn alloc_caller_location<'tcx>(
ecx: &mut CompileTimeEvalContext<'tcx>,
filename: Symbol,
line: u32,
col: u32,

View file

@ -69,7 +69,7 @@ struct ConstAnalysis<'a, 'tcx> {
map: Map,
tcx: TyCtxt<'tcx>,
local_decls: &'a LocalDecls<'tcx>,
ecx: InterpCx<'tcx, 'tcx, DummyMachine>,
ecx: InterpCx<'tcx, DummyMachine>,
param_env: ty::ParamEnv<'tcx>,
}
@ -143,10 +143,9 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
};
if let Some(variant_target_idx) = variant_target {
for (field_index, operand) in operands.iter_enumerated() {
if let Some(field) = self.map().apply(
variant_target_idx,
TrackElem::Field(field_index),
) {
if let Some(field) =
self.map().apply(variant_target_idx, TrackElem::Field(field_index))
{
self.assign_operand(state, field, operand);
}
}
@ -565,7 +564,7 @@ impl<'tcx, 'locals> Collector<'tcx, 'locals> {
fn try_make_constant(
&self,
ecx: &mut InterpCx<'tcx, 'tcx, DummyMachine>,
ecx: &mut InterpCx<'tcx, DummyMachine>,
place: Place<'tcx>,
state: &State<FlatSet<Scalar>>,
map: &Map,
@ -618,7 +617,7 @@ fn propagatable_scalar(
#[instrument(level = "trace", skip(ecx, state, map))]
fn try_write_constant<'tcx>(
ecx: &mut InterpCx<'_, 'tcx, DummyMachine>,
ecx: &mut InterpCx<'tcx, DummyMachine>,
dest: &PlaceTy<'tcx>,
place: PlaceIndex,
ty: Ty<'tcx>,
@ -836,7 +835,7 @@ impl<'tcx> MutVisitor<'tcx> for Patch<'tcx> {
struct OperandCollector<'tcx, 'map, 'locals, 'a> {
state: &'a State<FlatSet<Scalar>>,
visitor: &'a mut Collector<'tcx, 'locals>,
ecx: &'map mut InterpCx<'tcx, 'tcx, DummyMachine>,
ecx: &'map mut InterpCx<'tcx, DummyMachine>,
map: &'map Map,
}

View file

@ -234,7 +234,7 @@ enum Value<'tcx> {
struct VnState<'body, 'tcx> {
tcx: TyCtxt<'tcx>,
ecx: InterpCx<'tcx, 'tcx, DummyMachine>,
ecx: InterpCx<'tcx, DummyMachine>,
param_env: ty::ParamEnv<'tcx>,
local_decls: &'body LocalDecls<'tcx>,
/// Value stored in each local.
@ -1139,7 +1139,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
}
fn op_to_prop_const<'tcx>(
ecx: &mut InterpCx<'_, 'tcx, DummyMachine>,
ecx: &mut InterpCx<'tcx, DummyMachine>,
op: &OpTy<'tcx>,
) -> Option<ConstValue<'tcx>> {
// Do not attempt to propagate unsized locals.

View file

@ -155,7 +155,7 @@ struct ThreadingOpportunity {
struct TOFinder<'tcx, 'a> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
ecx: InterpCx<'tcx, 'tcx, DummyMachine>,
ecx: InterpCx<'tcx, DummyMachine>,
body: &'a Body<'tcx>,
map: &'a Map,
loop_headers: &'a BitSet<BasicBlock>,

View file

@ -64,7 +64,7 @@ impl<'tcx> MirLint<'tcx> for KnownPanicsLint {
/// Visits MIR nodes, performs const propagation
/// and runs lint checks as it goes
struct ConstPropagator<'mir, 'tcx> {
ecx: InterpCx<'mir, 'tcx, DummyMachine>,
ecx: InterpCx<'tcx, DummyMachine>,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
worklist: Vec<BasicBlock>,