提交 b174b0b9 编写于 作者: O Oliver Scherer

miri-engine value visitor update to VariantIdx

上级 4a9ed3f2
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
use std::ops::RangeInclusive; use std::ops::RangeInclusive;
use syntax_pos::symbol::Symbol; use syntax_pos::symbol::Symbol;
use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf}; use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf, VariantIdx};
use rustc::ty; use rustc::ty;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc::mir::interpret::{ use rustc::mir::interpret::{
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum PathElem { pub enum PathElem {
Field(Symbol), Field(Symbol),
Variant(Symbol),
ClosureVar(Symbol), ClosureVar(Symbol),
ArrayElem(usize), ArrayElem(usize),
TupleElem(usize), TupleElem(usize),
...@@ -107,6 +108,7 @@ fn path_format(path: &Vec<PathElem>) -> String { ...@@ -107,6 +108,7 @@ fn path_format(path: &Vec<PathElem>) -> String {
for elem in path.iter() { for elem in path.iter() {
match elem { match elem {
Field(name) => write!(out, ".{}", name), Field(name) => write!(out, ".{}", name),
Variant(name) => write!(out, ".<downcast-variant({})>", name),
ClosureVar(name) => write!(out, ".<closure-var({})>", name), ClosureVar(name) => write!(out, ".<closure-var({})>", name),
TupleElem(idx) => write!(out, ".{}", idx), TupleElem(idx) => write!(out, ".{}", idx),
ArrayElem(idx) => write!(out, "[{}]", idx), ArrayElem(idx) => write!(out, "[{}]", idx),
...@@ -192,9 +194,11 @@ fn push_aggregate_field_path_elem( ...@@ -192,9 +194,11 @@ fn push_aggregate_field_path_elem(
layout::Variants::Single { index } => layout::Variants::Single { index } =>
// Inside a variant // Inside a variant
PathElem::Field(def.variants[index].fields[field].ident.name), PathElem::Field(def.variants[index].fields[field].ident.name),
_ => _ => {
// To a variant // Enums have no fields other than their tag
PathElem::Field(def.variants[field].name) assert_eq!(field, 0);
PathElem::Tag
}
} }
} }
...@@ -241,6 +245,24 @@ fn visit_field( ...@@ -241,6 +245,24 @@ fn visit_field(
Ok(()) Ok(())
} }
#[inline]
fn visit_variant(
&mut self,
old_op: OpTy<'tcx, M::PointerTag>,
variant_id: VariantIdx,
new_op: OpTy<'tcx, M::PointerTag>
) -> EvalResult<'tcx> {
// Remember the old state
let path_len = self.path.len();
// Perform operation
let name = old_op.layout.ty.ty_adt_def().unwrap().variants[variant_id].name;
self.path.push(PathElem::Variant(name));
self.visit_value(new_op)?;
// Undo changes
self.path.truncate(path_len);
Ok(())
}
#[inline] #[inline]
fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> EvalResult<'tcx> fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
{ {
......
//! Visitor for a run-time value with a given layout: Traverse enums, structs and other compound //! Visitor for a run-time value with a given layout: Traverse enums, structs and other compound
//! types until we arrive at the leaves, with custom handling for primitive types. //! types until we arrive at the leaves, with custom handling for primitive types.
use rustc::ty::layout::{self, TyLayout}; use rustc::ty::layout::{self, TyLayout, VariantIdx};
use rustc::ty; use rustc::ty;
use rustc::mir::interpret::{ use rustc::mir::interpret::{
EvalResult, EvalResult,
...@@ -32,7 +32,7 @@ fn to_op( ...@@ -32,7 +32,7 @@ fn to_op(
fn project_downcast( fn project_downcast(
self, self,
ecx: &EvalContext<'a, 'mir, 'tcx, M>, ecx: &EvalContext<'a, 'mir, 'tcx, M>,
variant: usize, variant: VariantIdx,
) -> EvalResult<'tcx, Self>; ) -> EvalResult<'tcx, Self>;
/// Project to the n-th field. /// Project to the n-th field.
...@@ -70,7 +70,7 @@ fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self { ...@@ -70,7 +70,7 @@ fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
fn project_downcast( fn project_downcast(
self, self,
ecx: &EvalContext<'a, 'mir, 'tcx, M>, ecx: &EvalContext<'a, 'mir, 'tcx, M>,
variant: usize, variant: VariantIdx,
) -> EvalResult<'tcx, Self> { ) -> EvalResult<'tcx, Self> {
ecx.operand_downcast(self, variant) ecx.operand_downcast(self, variant)
} }
...@@ -109,7 +109,7 @@ fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self { ...@@ -109,7 +109,7 @@ fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
fn project_downcast( fn project_downcast(
self, self,
ecx: &EvalContext<'a, 'mir, 'tcx, M>, ecx: &EvalContext<'a, 'mir, 'tcx, M>,
variant: usize, variant: VariantIdx,
) -> EvalResult<'tcx, Self> { ) -> EvalResult<'tcx, Self> {
ecx.mplace_downcast(self, variant) ecx.mplace_downcast(self, variant)
} }
...@@ -171,6 +171,16 @@ fn visit_field( ...@@ -171,6 +171,16 @@ fn visit_field(
self.visit_value(new_val) self.visit_value(new_val)
} }
#[inline(always)]
fn visit_variant(
&mut self,
_old_val: Self::V,
_variant: VariantIdx,
new_val: Self::V,
) -> EvalResult<'tcx> {
self.visit_value(new_val)
}
/// Called whenever we reach a value with uninhabited layout. /// Called whenever we reach a value with uninhabited layout.
/// Recursing to fields will *always* continue after this! This is not meant to control /// 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, /// whether and how we descend recursively/ into the scalar's fields if there are any,
...@@ -221,7 +231,7 @@ fn walk_value(&mut self, v: Self::V) -> EvalResult<'tcx> ...@@ -221,7 +231,7 @@ fn walk_value(&mut self, v: Self::V) -> EvalResult<'tcx>
let inner = v.project_downcast(self.ecx(), idx)?; let inner = v.project_downcast(self.ecx(), idx)?;
trace!("walk_value: variant layout: {:#?}", inner.layout()); trace!("walk_value: variant layout: {:#?}", inner.layout());
// recurse with the inner type // recurse with the inner type
return self.visit_field(v, idx, inner); return self.visit_variant(v, idx, inner);
} }
layout::Variants::Single { .. } => {} layout::Variants::Single { .. } => {}
} }
......
...@@ -42,7 +42,7 @@ error[E0080]: it is undefined behavior to use this value ...@@ -42,7 +42,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:61:1 --> $DIR/ub-enum.rs:61:1
| |
LL | const BAD_ENUM_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b })); LL | const BAD_ENUM_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .Some.0.1, but expected something less or equal to 1114111 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .<downcast-variant(Some)>.0.1, but expected something less or equal to 1114111
| |
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册