use crate::interpret::{self,
PlaceTy, MPlaceTy, MemPlace, OpTy, ImmTy, Immediate, Scalar, Pointer,
RawConst, ConstValue,
- EvalResult, EvalError, EvalErrorKind, GlobalId, EvalContext, StackPopCleanup,
+ EvalResult, EvalError, EvalErrorKind, GlobalId, InterpretCx, StackPopCleanup,
Allocation, AllocId, MemoryKind,
snapshot, RefTracking,
};
param_env: ty::ParamEnv<'tcx>,
) -> CompileTimeEvalContext<'a, 'mir, 'tcx> {
debug!("mk_eval_cx: {:?}", param_env);
- EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new())
+ InterpretCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new())
}
pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
// and try improving it down the road when more information is available
let span = tcx.def_span(cid.instance.def_id());
let span = mir.map(|mir| mir.span).unwrap_or(span);
- let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new());
+ let mut ecx = InterpretCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new());
let r = eval_body_using_ecx(&mut ecx, cid, mir, param_env);
(r, ecx)
}
}
type CompileTimeEvalContext<'a, 'mir, 'tcx> =
- EvalContext<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>;
+ InterpretCx<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>;
impl interpret::MayLeak for ! {
#[inline(always)]
const STATIC_KIND: Option<!> = None; // no copying of statics allowed
#[inline(always)]
- fn enforce_validity(_ecx: &EvalContext<'a, 'mir, 'tcx, Self>) -> bool {
+ fn enforce_validity(_ecx: &InterpretCx<'a, 'mir, 'tcx, Self>) -> bool {
false // for now, we don't enforce validity
}
fn find_fn(
- ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+ ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx>],
dest: Option<PlaceTy<'tcx>>,
}
fn call_intrinsic(
- ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+ ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx>],
dest: PlaceTy<'tcx>,
}
fn ptr_op(
- _ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
+ _ecx: &InterpretCx<'a, 'mir, 'tcx, Self>,
_bin_op: mir::BinOp,
_left: ImmTy<'tcx>,
_right: ImmTy<'tcx>,
}
fn box_alloc(
- _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+ _ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
_dest: PlaceTy<'tcx>,
) -> EvalResult<'tcx> {
Err(
)
}
- fn before_terminator(ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx> {
+ fn before_terminator(ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx> {
{
let steps = &mut ecx.machine.steps_since_detector_enabled;
#[inline(always)]
fn tag_new_allocation(
- _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+ _ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
ptr: Pointer,
_kind: MemoryKind<Self::MemoryKinds>,
) -> Pointer {
#[inline(always)]
fn stack_push(
- _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+ _ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
) -> EvalResult<'tcx> {
Ok(())
}
/// Called immediately before a stack frame gets popped.
#[inline(always)]
fn stack_pop(
- _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+ _ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
_extra: (),
) -> EvalResult<'tcx> {
Ok(())
}
pub fn error_to_const_error<'a, 'mir, 'tcx>(
- ecx: &EvalContext<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
+ ecx: &InterpretCx<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
mut error: EvalError<'tcx>
) -> ConstEvalErr<'tcx> {
error.print_backtrace();
use rustc::mir::CastKind;
use rustc_apfloat::Float;
-use super::{EvalContext, Machine, PlaceTy, OpTy, ImmTy, Immediate};
+use super::{InterpretCx, Machine, PlaceTy, OpTy, ImmTy, Immediate};
-impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
+impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
match ty.sty {
ty::RawPtr(ty::TypeAndMut { ty, .. }) |
Memory, Machine
};
-pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
+pub struct InterpretCx<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
/// Stores the `Machine` instance.
pub machine: M,
}
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> HasDataLayout
- for EvalContext<'a, 'mir, 'tcx, M>
+ for InterpretCx<'a, 'mir, 'tcx, M>
{
#[inline]
fn data_layout(&self) -> &layout::TargetDataLayout {
}
}
-impl<'a, 'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for EvalContext<'a, 'mir, 'tcx, M>
+impl<'a, 'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for InterpretCx<'a, 'mir, 'tcx, M>
where M: Machine<'a, 'mir, 'tcx>
{
#[inline]
}
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> LayoutOf
- for EvalContext<'a, 'mir, 'tcx, M>
+ for InterpretCx<'a, 'mir, 'tcx, M>
{
type Ty = Ty<'tcx>;
type TyLayout = EvalResult<'tcx, TyLayout<'tcx>>;
}
}
-impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
+impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
pub fn new(
tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
machine: M,
) -> Self {
- EvalContext {
+ InterpretCx {
machine,
tcx,
param_env,
};
use super::{
- Machine, PlaceTy, OpTy, EvalContext,
+ Machine, PlaceTy, OpTy, InterpretCx,
};
Ok(Scalar::from_uint(bits_out, size))
}
-impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
+impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
/// Returns `true` if emulation happened.
pub fn emulate_intrinsic(
&mut self,
use super::{
Allocation, AllocId, EvalResult, Scalar, AllocationExtra,
- EvalContext, PlaceTy, MPlaceTy, OpTy, ImmTy, Pointer, MemoryKind,
+ InterpretCx, PlaceTy, MPlaceTy, OpTy, ImmTy, Pointer, MemoryKind,
};
/// Whether this kind of memory is allowed to leak
const STATIC_KIND: Option<Self::MemoryKinds>;
/// Whether to enforce the validity invariant
- fn enforce_validity(ecx: &EvalContext<'a, 'mir, 'tcx, Self>) -> bool;
+ fn enforce_validity(ecx: &InterpretCx<'a, 'mir, 'tcx, Self>) -> bool;
/// Called before a basic block terminator is executed.
/// You can use this to detect endlessly running programs.
- fn before_terminator(ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx>;
+ fn before_terminator(ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx>;
/// Entry point to all function calls.
///
/// Passing `dest`and `ret` in the same `Option` proved very annoying when only one of them
/// was used.
fn find_fn(
- ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+ ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Self::PointerTag>],
dest: Option<PlaceTy<'tcx, Self::PointerTag>>,
/// Directly process an intrinsic without pushing a stack frame.
/// If this returns successfully, the engine will take care of jumping to the next block.
fn call_intrinsic(
- ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+ ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Self::PointerTag>],
dest: PlaceTy<'tcx, Self::PointerTag>,
///
/// Returns a (value, overflowed) pair if the operation succeeded
fn ptr_op(
- ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
+ ecx: &InterpretCx<'a, 'mir, 'tcx, Self>,
bin_op: mir::BinOp,
left: ImmTy<'tcx, Self::PointerTag>,
right: ImmTy<'tcx, Self::PointerTag>,
/// Heap allocations via the `box` keyword.
fn box_alloc(
- ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+ ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
dest: PlaceTy<'tcx, Self::PointerTag>,
) -> EvalResult<'tcx>;
/// Adds the tag for a newly allocated pointer.
fn tag_new_allocation(
- ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+ ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
ptr: Pointer,
kind: MemoryKind<Self::MemoryKinds>,
) -> Pointer<Self::PointerTag>;
/// `mutability` can be `None` in case a raw ptr is being dereferenced.
#[inline]
fn tag_dereference(
- _ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
+ _ecx: &InterpretCx<'a, 'mir, 'tcx, Self>,
place: MPlaceTy<'tcx, Self::PointerTag>,
_mutability: Option<hir::Mutability>,
) -> EvalResult<'tcx, Scalar<Self::PointerTag>> {
/// Executes a retagging operation
#[inline]
fn retag(
- _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+ _ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
_kind: mir::RetagKind,
_place: PlaceTy<'tcx, Self::PointerTag>,
) -> EvalResult<'tcx> {
/// Called immediately before a new stack frame got pushed
fn stack_push(
- ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+ ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
) -> EvalResult<'tcx, Self::FrameExtra>;
/// Called immediately after a stack frame gets popped
fn stack_pop(
- ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+ ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
extra: Self::FrameExtra,
) -> EvalResult<'tcx>;
}
pub use rustc::mir::interpret::*; // have all the `interpret` symbols in one place: here
pub use self::eval_context::{
- EvalContext, Frame, StackPopCleanup, LocalState, LocalValue,
+ InterpretCx, Frame, StackPopCleanup, LocalState, LocalValue,
};
pub use self::place::{Place, PlaceTy, MemPlace, MPlaceTy};
sign_extend, truncate,
};
use super::{
- EvalContext, Machine,
+ InterpretCx, Machine,
MemPlace, MPlaceTy, PlaceTy, Place, MemoryKind,
};
pub use rustc::mir::interpret::ScalarMaybeUndef;
}
}
-impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
+impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, '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.
fn try_read_immediate_from_mplace(
use rustc_apfloat::Float;
use rustc::mir::interpret::{EvalResult, Scalar};
-use super::{EvalContext, PlaceTy, Immediate, Machine, ImmTy};
+use super::{InterpretCx, PlaceTy, Immediate, Machine, ImmTy};
-impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
+impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
/// Applies the binary operation `op` to the two operands and writes a tuple of the result
/// and a boolean signifying the potential overflow to the destination.
pub fn binop_with_overflow(
}
}
-impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
+impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
fn binary_char_op(
&self,
bin_op: mir::BinOp,
use super::{
GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic,
- EvalContext, Machine, AllocMap, AllocationExtra,
+ InterpretCx, Machine, AllocMap, AllocationExtra,
RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind
};
}
// separating the pointer tag for `impl Trait`, see https://github.com/rust-lang/rust/issues/54385
-impl<'a, 'mir, 'tcx, Tag, M> EvalContext<'a, 'mir, 'tcx, M>
+impl<'a, 'mir, 'tcx, Tag, M> InterpretCx<'a, 'mir, 'tcx, M>
where
// FIXME: Working around https://github.com/rust-lang/rust/issues/54385
Tag: ::std::fmt::Debug+Default+Copy+Eq+Hash+'static,
// global table but not in its local memory: It calls back into tcx through
// a query, triggering the CTFE machinery to actually turn this lazy reference
// into a bunch of bytes. IOW, statics are evaluated with CTFE even when
- // this EvalContext uses another Machine (e.g., in miri). This is what we
+ // this InterpretCx uses another Machine (e.g., in miri). This is what we
// want! This way, computing statics works concistently between codegen
// and miri: They use the same query to eventually obtain a `ty::Const`
// and use that for further computation.
-//! This module contains the `EvalContext` methods for executing a single step of the interpreter.
+//! This module contains the `InterpretCx` methods for executing a single step of the interpreter.
//!
//! The main entry point is the `step` method.
use rustc::ty::layout::LayoutOf;
use rustc::mir::interpret::{EvalResult, Scalar, PointerArithmetic};
-use super::{EvalContext, Machine};
+use super::{InterpretCx, Machine};
/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
/// same type as the result.
}
}
-impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
+impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
pub fn run(&mut self) -> EvalResult<'tcx> {
while self.step()? {}
Ok(())
use rustc::mir::interpret::{EvalResult, PointerArithmetic, EvalErrorKind, Scalar};
use super::{
- EvalContext, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup
+ InterpretCx, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup
};
-impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
+impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
#[inline]
pub fn goto_block(&mut self, target: Option<mir::BasicBlock>) -> EvalResult<'tcx> {
if let Some(target) = target {
use rustc::ty::layout::{Size, Align, LayoutOf};
use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic};
-use super::{EvalContext, Machine, MemoryKind};
+use super::{InterpretCx, Machine, MemoryKind};
-impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
+impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
/// Creates a dynamic vtable for the given type and vtable origin. This is used only for
/// objects.
///
};
use super::{
- OpTy, Machine, EvalContext, ValueVisitor, MPlaceTy,
+ OpTy, Machine, InterpretCx, ValueVisitor, MPlaceTy,
};
macro_rules! validation_failure {
path: Vec<PathElem>,
ref_tracking: Option<&'rt mut RefTracking<MPlaceTy<'tcx, M::PointerTag>>>,
const_mode: bool,
- ecx: &'rt EvalContext<'a, 'mir, 'tcx, M>,
+ ecx: &'rt InterpretCx<'a, 'mir, 'tcx, M>,
}
impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> ValidityVisitor<'rt, 'a, 'mir, 'tcx, M> {
type V = OpTy<'tcx, M::PointerTag>;
#[inline(always)]
- fn ecx(&self) -> &EvalContext<'a, 'mir, 'tcx, M> {
+ fn ecx(&self) -> &InterpretCx<'a, 'mir, 'tcx, M> {
&self.ecx
}
}
}
-impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
+impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
/// This function checks the data at `op`. `op` is assumed to cover valid memory if it
/// is an indirect operand.
/// It will error if the bits at the destination do not match the ones described by the layout.
};
use super::{
- Machine, EvalContext, MPlaceTy, OpTy,
+ Machine, InterpretCx, MPlaceTy, OpTy,
};
// A thing that we can project into, and that has a layout.
/// Makes this into an `OpTy`.
fn to_op(
self,
- ecx: &EvalContext<'a, 'mir, 'tcx, M>,
+ ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>>;
/// Creates this from an `MPlaceTy`.
/// Projects to the given enum variant.
fn project_downcast(
self,
- ecx: &EvalContext<'a, 'mir, 'tcx, M>,
+ ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
variant: VariantIdx,
) -> EvalResult<'tcx, Self>;
/// Projects to the n-th field.
fn project_field(
self,
- ecx: &EvalContext<'a, 'mir, 'tcx, M>,
+ ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
field: u64,
) -> EvalResult<'tcx, Self>;
}
#[inline(always)]
fn to_op(
self,
- _ecx: &EvalContext<'a, 'mir, 'tcx, M>,
+ _ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
Ok(self)
}
#[inline(always)]
fn project_downcast(
self,
- ecx: &EvalContext<'a, 'mir, 'tcx, M>,
+ ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
variant: VariantIdx,
) -> EvalResult<'tcx, Self> {
ecx.operand_downcast(self, variant)
#[inline(always)]
fn project_field(
self,
- ecx: &EvalContext<'a, 'mir, 'tcx, M>,
+ ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
field: u64,
) -> EvalResult<'tcx, Self> {
ecx.operand_field(self, field)
#[inline(always)]
fn to_op(
self,
- _ecx: &EvalContext<'a, 'mir, 'tcx, M>,
+ _ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
Ok(self.into())
}
#[inline(always)]
fn project_downcast(
self,
- ecx: &EvalContext<'a, 'mir, 'tcx, M>,
+ ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
variant: VariantIdx,
) -> EvalResult<'tcx, Self> {
ecx.mplace_downcast(self, variant)
#[inline(always)]
fn project_field(
self,
- ecx: &EvalContext<'a, 'mir, 'tcx, M>,
+ ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
field: u64,
) -> EvalResult<'tcx, Self> {
ecx.mplace_field(self, field)
pub trait $visitor_trait_name<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Sized {
type V: Value<'a, 'mir, 'tcx, M>;
- /// The visitor must have an `EvalContext` in it.
+ /// The visitor must have an `InterpretCx` in it.
fn ecx(&$($mutability)? self)
- -> &$($mutability)? EvalContext<'a, 'mir, 'tcx, M>;
+ -> &$($mutability)? InterpretCx<'a, 'mir, 'tcx, M>;
// Recursive actions, ready to be overloaded.
/// Visits the given value, dispatching as appropriate to more specialized visitors.
HasTyCtxt, TargetDataLayout, HasDataLayout,
};
-use crate::interpret::{EvalContext, ScalarMaybeUndef, Immediate, OpTy, ImmTy, MemoryKind};
+use crate::interpret::{InterpretCx, ScalarMaybeUndef, Immediate, OpTy, ImmTy, MemoryKind};
use crate::const_eval::{
CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_eval_cx,
};
/// Finds optimization opportunities on the MIR.
struct ConstPropagator<'a, 'mir, 'tcx:'a+'mir> {
- ecx: EvalContext<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
+ ecx: InterpretCx<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
mir: &'mir Mir<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
source: MirSource<'tcx>,