Skip to content

Commit

Permalink
the visitor can already load the value for visit_primitive
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Nov 5, 2018
1 parent c267721 commit 996a425
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 16 deletions.
19 changes: 9 additions & 10 deletions src/librustc_mir/interpret/validity.rs
Expand Up @@ -20,7 +20,7 @@ use rustc::mir::interpret::{
};

use super::{
OpTy, MPlaceTy, Machine, EvalContext, ValueVisitor
OpTy, MPlaceTy, ImmTy, Machine, EvalContext, ValueVisitor
};

macro_rules! validation_failure {
Expand Down Expand Up @@ -213,24 +213,25 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
{
trace!("visit_value: {:?}, {:?}", *op, op.layout);
// Translate enum discriminant errors to something nicer.
// Translate some possible errors to something nicer.
match self.walk_value(op) {
Ok(()) => Ok(()),
Err(err) => match err.kind {
EvalErrorKind::InvalidDiscriminant(val) =>
validation_failure!(
val, self.path, "a valid enum discriminant"
),
EvalErrorKind::ReadPointerAsBytes =>
validation_failure!(
"a pointer", self.path, "plain bytes"
),
_ => Err(err),
}
}
}

fn visit_primitive(&mut self, op: OpTy<'tcx, M::PointerTag>)
-> EvalResult<'tcx>
fn visit_primitive(&mut self, value: ImmTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
{
let value = try_validation!(self.ecx.read_immediate(op),
"uninitialized or unrepresentable data", self.path);
// Go over all the primitive types
let ty = value.layout.ty;
match ty.sty {
Expand Down Expand Up @@ -379,8 +380,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
Ok(())
}

fn visit_uninhabited(&mut self, _op: OpTy<'tcx, M::PointerTag>)
-> EvalResult<'tcx>
fn visit_uninhabited(&mut self) -> EvalResult<'tcx>
{
validation_failure!("a value of an uninhabited type", self.path)
}
Expand All @@ -390,8 +390,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
op: OpTy<'tcx, M::PointerTag>,
layout: &layout::Scalar,
) -> EvalResult<'tcx> {
let value = try_validation!(self.ecx.read_scalar(op),
"uninitialized or unrepresentable data", self.path);
let value = self.ecx.read_scalar(op)?;
// Determine the allowed range
let (lo, hi) = layout.valid_range.clone().into_inner();
// `max_hi` is as big as the size fits
Expand Down
14 changes: 9 additions & 5 deletions src/librustc_mir/interpret/visitor.rs
Expand Up @@ -8,7 +8,7 @@ use rustc::mir::interpret::{
};

use super::{
Machine, EvalContext, MPlaceTy, PlaceTy, OpTy,
Machine, EvalContext, MPlaceTy, PlaceTy, OpTy, ImmTy,
};

// A thing that we can project into, and that has a layout.
Expand Down Expand Up @@ -205,17 +205,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 continue after this!
#[inline(always)]
fn visit_uninhabited(&mut self, _v: Self::V) -> EvalResult<'tcx>
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.
/// Recursing to fields will continue after this!
#[inline(always)]
fn visit_scalar(&mut self, _v: Self::V, _layout: &layout::Scalar) -> EvalResult<'tcx>
{ Ok(()) }
/// Called whenever we reach a value of primitive type. There can be no recursion
/// below such a value.
#[inline(always)]
fn visit_primitive(&mut self, _v: Self::V) -> EvalResult<'tcx>
fn visit_primitive(&mut self, _val: ImmTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
{ Ok(()) }

// Default recursors. Not meant to be overloaded.
Expand Down Expand Up @@ -275,7 +277,7 @@ pub trait ValueVisitor<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Siz
// MyNewtype and then the scalar in there).
match v.layout().abi {
layout::Abi::Uninhabited => {
self.visit_uninhabited(v)?;
self.visit_uninhabited()?;
}
layout::Abi::Scalar(ref layout) => {
self.visit_scalar(v, layout)?;
Expand All @@ -295,7 +297,9 @@ pub trait ValueVisitor<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Siz
_ => v.layout().ty.builtin_deref(true).is_some(),
};
if primitive {
return self.visit_primitive(v);
let op = v.to_op(self.ecx())?;
let val = self.ecx().read_immediate(op)?;
return self.visit_primitive(val);
}

// Proceed into the fields.
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/consts/const-eval/ub-ref.stderr
Expand Up @@ -26,7 +26,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-ref.rs:25:1
|
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a raw memory access tried to access part of a pointer value as raw bytes
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain bytes
|
= 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

Expand Down

0 comments on commit 996a425

Please sign in to comment.