make ValueVisitor mut-polymorphic
This commit is contained in:
parent
7565b5ac67
commit
873041009d
@ -535,7 +535,7 @@ fn validate_const<'a, 'tcx>(
|
||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
||||
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
|
||||
let cid = key.value;
|
||||
let mut ecx = mk_eval_cx(tcx, cid.instance, key.param_env).unwrap();
|
||||
let ecx = mk_eval_cx(tcx, cid.instance, key.param_env).unwrap();
|
||||
let val = (|| {
|
||||
let op = ecx.const_to_op(constant)?;
|
||||
let mut ref_tracking = RefTracking::new(op);
|
||||
|
@ -129,7 +129,7 @@ struct ValidityVisitor<'rt, 'a: 'rt, 'mir: 'rt, 'tcx: 'a+'rt+'mir, M: Machine<'a
|
||||
path: Vec<PathElem>,
|
||||
ref_tracking: Option<&'rt mut RefTracking<'tcx, M::PointerTag>>,
|
||||
const_mode: bool,
|
||||
ecx: &'rt mut EvalContext<'a, 'mir, 'tcx, M>,
|
||||
ecx: &'rt EvalContext<'a, 'mir, 'tcx, M>,
|
||||
}
|
||||
|
||||
impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> ValidityVisitor<'rt, 'a, 'mir, 'tcx, M> {
|
||||
@ -188,8 +188,8 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
|
||||
type V = OpTy<'tcx, M::PointerTag>;
|
||||
|
||||
#[inline(always)]
|
||||
fn ecx(&mut self) -> &mut EvalContext<'a, 'mir, 'tcx, M> {
|
||||
&mut self.ecx
|
||||
fn ecx(&self) -> &EvalContext<'a, 'mir, 'tcx, M> {
|
||||
&self.ecx
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -557,7 +557,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
|
||||
/// This also toggles between "run-time" (no recursion) and "compile-time" (with recursion)
|
||||
/// validation (e.g., pointer values are fine in integers at runtime).
|
||||
pub fn validate_operand(
|
||||
&mut self,
|
||||
&self,
|
||||
op: OpTy<'tcx, M::PointerTag>,
|
||||
path: Vec<PathElem>,
|
||||
ref_tracking: Option<&mut RefTracking<'tcx, M::PointerTag>>,
|
||||
|
@ -8,7 +8,7 @@ use rustc::mir::interpret::{
|
||||
};
|
||||
|
||||
use super::{
|
||||
Machine, EvalContext, MPlaceTy, PlaceTy, OpTy, ImmTy,
|
||||
Machine, EvalContext, MPlaceTy, OpTy, ImmTy,
|
||||
};
|
||||
|
||||
// A thing that we can project into, and that has a layout.
|
||||
@ -38,12 +38,13 @@ pub trait Value<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: Copy
|
||||
/// Project to the n-th field.
|
||||
fn project_field(
|
||||
self,
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, M>,
|
||||
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
|
||||
field: u64,
|
||||
) -> EvalResult<'tcx, Self>;
|
||||
}
|
||||
|
||||
// Operands and places are both values
|
||||
// Operands and memory-places are both values.
|
||||
// Places in general are not due to `place_field` having to do `force_allocation`.
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
|
||||
for OpTy<'tcx, M::PointerTag>
|
||||
{
|
||||
@ -77,7 +78,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
|
||||
#[inline(always)]
|
||||
fn project_field(
|
||||
self,
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, M>,
|
||||
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
|
||||
field: u64,
|
||||
) -> EvalResult<'tcx, Self> {
|
||||
ecx.operand_field(self, field)
|
||||
@ -116,58 +117,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
|
||||
#[inline(always)]
|
||||
fn project_field(
|
||||
self,
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, M>,
|
||||
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
|
||||
field: u64,
|
||||
) -> EvalResult<'tcx, Self> {
|
||||
ecx.mplace_field(self, field)
|
||||
}
|
||||
}
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
|
||||
for PlaceTy<'tcx, M::PointerTag>
|
||||
{
|
||||
#[inline(always)]
|
||||
fn layout(&self) -> TyLayout<'tcx> {
|
||||
self.layout
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn to_op(
|
||||
self,
|
||||
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
|
||||
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
||||
ecx.place_to_op(self)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
|
||||
mplace.into()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn project_downcast(
|
||||
self,
|
||||
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
|
||||
variant: usize,
|
||||
) -> EvalResult<'tcx, Self> {
|
||||
ecx.place_downcast(self, variant)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn project_field(
|
||||
self,
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, M>,
|
||||
field: u64,
|
||||
) -> EvalResult<'tcx, Self> {
|
||||
ecx.place_field(self, field)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! make_value_visitor {
|
||||
($visitor_trait_name:ident, $($mutability:ident)*) => {
|
||||
// How to traverse a value and what to do when we are at the leaves.
|
||||
pub trait ValueVisitor<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Sized {
|
||||
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.
|
||||
fn ecx(&mut self) -> &mut EvalContext<'a, 'mir, 'tcx, M>;
|
||||
fn ecx(&$($mutability)* self)
|
||||
-> &$($mutability)* EvalContext<'a, 'mir, 'tcx, M>;
|
||||
|
||||
// Recursive actions, ready to be overloaded.
|
||||
/// Visit the given value, dispatching as appropriate to more specialized visitors.
|
||||
@ -208,18 +173,19 @@ pub trait ValueVisitor<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Siz
|
||||
|
||||
/// Called whenever we reach a value with uninhabited layout.
|
||||
/// Recursing to fields will *always* continue after this! This is not meant to control
|
||||
/// whether and how we descend recursively/ into the scalar's fields if there are any, it is
|
||||
/// meant to provide the chance for additional checks when a value of uninhabited layout is
|
||||
/// detected.
|
||||
/// whether and how we descend recursively/ into the scalar's fields if there are any,
|
||||
/// it is meant to provide the chance for additional checks when a value of uninhabited
|
||||
/// layout is detected.
|
||||
#[inline(always)]
|
||||
fn visit_uninhabited(&mut self) -> EvalResult<'tcx>
|
||||
{ Ok(()) }
|
||||
/// Called whenever we reach a value with scalar layout.
|
||||
/// We do NOT provide a `ScalarMaybeUndef` here to avoid accessing memory if the visitor is not
|
||||
/// even interested in scalars.
|
||||
/// We do NOT provide a `ScalarMaybeUndef` here to avoid accessing memory if the
|
||||
/// visitor is not even interested in scalars.
|
||||
/// Recursing to fields will *always* continue after this! This is not meant to control
|
||||
/// whether and how we descend recursively/ into the scalar's fields if there are any, it is
|
||||
/// meant to provide the chance for additional checks when a value of scalar layout is detected.
|
||||
/// whether and how we descend recursively/ into the scalar's fields if there are any,
|
||||
/// it is meant to provide the chance for additional checks when a value of scalar
|
||||
/// layout is detected.
|
||||
#[inline(always)]
|
||||
fn visit_scalar(&mut self, _v: Self::V, _layout: &layout::Scalar) -> EvalResult<'tcx>
|
||||
{ Ok(()) }
|
||||
@ -244,8 +210,8 @@ pub trait ValueVisitor<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Siz
|
||||
}
|
||||
fn walk_value(&mut self, v: Self::V) -> EvalResult<'tcx>
|
||||
{
|
||||
// If this is a multi-variant layout, we have find the right one and proceed with that.
|
||||
// (No benefit from making this recursion, but it is equivalent to that.)
|
||||
// If this is a multi-variant layout, we have find the right one and proceed with
|
||||
// that.
|
||||
match v.layout().variants {
|
||||
layout::Variants::NicheFilling { .. } |
|
||||
layout::Variants::Tagged { .. } => {
|
||||
@ -297,7 +263,7 @@ pub trait ValueVisitor<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Siz
|
||||
// It is CRITICAL that we get this check right, or we might be
|
||||
// validating the wrong thing!
|
||||
let primitive = match v.layout().fields {
|
||||
// Primitives appear as Union with 0 fields -- except for Boxes and fat pointers.
|
||||
// Primitives appear as Union with 0 fields - except for Boxes and fat pointers.
|
||||
layout::FieldPlacement::Union(0) => true,
|
||||
_ => v.layout().ty.builtin_deref(true).is_some(),
|
||||
};
|
||||
@ -346,3 +312,8 @@ pub trait ValueVisitor<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Siz
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
make_value_visitor!(ValueVisitor,);
|
||||
make_value_visitor!(MutValueVisitor,mut);
|
||||
|
Loading…
Reference in New Issue
Block a user