about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWesley Wiser <wwiser@gmail.com>2019-09-03 21:56:15 -0400
committerWesley Wiser <wwiser@gmail.com>2019-09-27 20:11:12 -0400
commitbc17936c8a466e56d472b811e0aca0cf8ffdf9a1 (patch)
treef274545ce17f8befddaf37d9b6921453a3163eaa
parent59367b074f1523353dddefa678ffe3cac9fd4e50 (diff)
downloadrust-bc17936c8a466e56d472b811e0aca0cf8ffdf9a1.tar.gz
rust-bc17936c8a466e56d472b811e0aca0cf8ffdf9a1.zip
[const-prop] Replace `eval_place()` with use of `InterpCx`
-rw-r--r--src/librustc/mir/interpret/error.rs12
-rw-r--r--src/librustc_mir/interpret/eval_context.rs3
-rw-r--r--src/librustc_mir/interpret/operand.rs2
-rw-r--r--src/librustc_mir/interpret/place.rs9
-rw-r--r--src/librustc_mir/transform/const_prop.rs56
-rw-r--r--src/test/mir-opt/const_prop/slice_len.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-50814.rs1
-rw-r--r--src/test/ui/consts/const-eval/issue-50814.stderr12
-rw-r--r--src/test/ui/issues/issue-52060.stderr3
9 files changed, 43 insertions, 57 deletions
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index ac99ccd45ea..0328f93859b 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -389,6 +389,14 @@ pub enum UnsupportedOpInfo<'tcx> {
     /// Free-form case. Only for errors that are never caught!
     Unsupported(String),
 
+    /// Error used by the `ConstProp` pass when an attempt is made
+    /// to read an uninitialized local.
+    UninitializedLocal,
+
+    /// Error used by the `ConstProp` pass to prevent reading statics
+    /// while evaluating `const` items.
+    ReadOfStaticInConst,
+
     // -- Everything below is not categorized yet --
     FunctionAbiMismatch(Abi, Abi),
     FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
@@ -511,6 +519,8 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
                     addresses, e.g., comparing pointers into different allocations"),
             DeadLocal =>
                 write!(f, "tried to access a dead local variable"),
+            UninitializedLocal =>
+                write!(f, "tried to access an uninitialized local variable"),
             DerefFunctionPointer =>
                 write!(f, "tried to dereference a function pointer"),
             ExecuteMemory =>
@@ -552,6 +562,8 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
                     not a power of two"),
             Unsupported(ref msg) =>
                 write!(f, "{}", msg),
+            ReadOfStaticInConst =>
+                write!(f, "tried to read from a static during const evaluation"),
         }
     }
 }
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index fdf85260c3d..7ca14b51740 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -134,8 +134,7 @@ impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
     pub fn access(&self) -> InterpResult<'tcx, Operand<Tag>> {
         match self.value {
             LocalValue::Dead => throw_unsup!(DeadLocal),
-            LocalValue::Uninitialized =>
-                bug!("The type checker should prevent reading from a never-written local"),
+            LocalValue::Uninitialized => throw_unsup!(UninitializedLocal),
             LocalValue::Live(val) => Ok(val),
         }
     }
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index f5d1ec3eb75..89af0031bfd 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -481,7 +481,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     // Evaluate a place with the goal of reading from it.  This lets us sometimes
     // avoid allocations.
-    pub(super) fn eval_place_to_op(
+    pub fn eval_place_to_op(
         &self,
         place: &mir::Place<'tcx>,
         layout: Option<TyLayout<'tcx>>,
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 2f1b35757fe..f9ba1452d64 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -597,6 +597,15 @@ where
             }
 
             StaticKind::Static => {
+                //if the first frame on the stack isn't a static item, then we shouldn't
+                //eval any static places (unless -Z unleash-the-miri-inside-of-you is on)
+                if let ty::InstanceDef::Item(item_def_id) = self.stack[0].instance.def {
+                    if !self.tcx.is_static(item_def_id) &&
+                        !self.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you {
+                        trace!("eval_static_to_mplace: can't eval static in constant");
+                        throw_unsup!(ReadOfStaticInConst);
+                    }
+                }
                 let ty = place_static.ty;
                 assert!(!ty.needs_subst());
                 let layout = self.layout_of(ty)?;
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 857757ada53..ff1a7c2c48f 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -6,14 +6,14 @@ use std::cell::Cell;
 use rustc::hir::def::DefKind;
 use rustc::mir::{
     AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue,
-    Local, NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind,
-    TerminatorKind, Terminator,  ClearCrossCrate, SourceInfo, BinOp, ProjectionElem,
+    Local, NullOp, UnOp, StatementKind, Statement, LocalKind,
+    TerminatorKind, Terminator,  ClearCrossCrate, SourceInfo, BinOp,
     SourceScope, SourceScopeLocalData, LocalDecl,
 };
 use rustc::mir::visit::{
     Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext,
 };
-use rustc::mir::interpret::{Scalar, GlobalId, InterpResult, PanicInfo};
+use rustc::mir::interpret::{Scalar, InterpResult, PanicInfo};
 use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
 use syntax_pos::{Span, DUMMY_SP};
 use rustc::ty::subst::InternalSubsts;
@@ -282,53 +282,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
 
     fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
         trace!("eval_place(place={:?})", place);
-        let mut eval = match place.base {
-            PlaceBase::Local(loc) => self.get_const(loc).clone()?,
-            PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted, _), ..}) => {
-                let generics = self.tcx.generics_of(self.source.def_id());
-                if generics.requires_monomorphization(self.tcx) {
-                    // FIXME: can't handle code with generics
-                    return None;
-                }
-                let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
-                let instance = Instance::new(self.source.def_id(), substs);
-                let cid = GlobalId {
-                    instance,
-                    promoted: Some(promoted),
-                };
-                let res = self.use_ecx(source_info, |this| {
-                    this.ecx.const_eval_raw(cid)
-                })?;
-                trace!("evaluated promoted {:?} to {:?}", promoted, res);
-                res.into()
-            }
-            _ => return None,
-        };
-
-        for (i, elem) in place.projection.iter().enumerate() {
-            let proj_base = &place.projection[..i];
-
-            match elem {
-                ProjectionElem::Field(field, _) => {
-                    trace!("field proj on {:?}", proj_base);
-                    eval = self.use_ecx(source_info, |this| {
-                        this.ecx.operand_field(eval, field.index() as u64)
-                    })?;
-                },
-                ProjectionElem::Deref => {
-                    trace!("processing deref");
-                    eval = self.use_ecx(source_info, |this| {
-                        this.ecx.deref_operand(eval)
-                    })?.into();
-                }
-                // We could get more projections by using e.g., `operand_projection`,
-                // but we do not even have the stack frame set up properly so
-                // an `Index` projection would throw us off-track.
-                _ => return None,
-            }
-        }
-
-        Some(eval)
+        self.use_ecx(source_info, |this| {
+            this.ecx.eval_place_to_op(place, None)
+        })
     }
 
     fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
diff --git a/src/test/mir-opt/const_prop/slice_len.rs b/src/test/mir-opt/const_prop/slice_len.rs
index 5babeb195a8..05595ce147c 100644
--- a/src/test/mir-opt/const_prop/slice_len.rs
+++ b/src/test/mir-opt/const_prop/slice_len.rs
@@ -34,7 +34,7 @@ fn main() {
 //      assert(const true, "index out of bounds: the len is move _7 but the index is _6") -> bb1;
 //  }
 //  bb1: {
-//      _1 = (*_2)[_6];
+//      _1 = const 2u32;
 //      ...
 //      return;
 //  }
diff --git a/src/test/ui/consts/const-eval/issue-50814.rs b/src/test/ui/consts/const-eval/issue-50814.rs
index b85cecda16e..274967ef60d 100644
--- a/src/test/ui/consts/const-eval/issue-50814.rs
+++ b/src/test/ui/consts/const-eval/issue-50814.rs
@@ -11,6 +11,7 @@ struct Sum<A,B>(A,B);
 
 impl<A: Unsigned, B: Unsigned> Unsigned for Sum<A,B> {
     const MAX: u8 = A::MAX + B::MAX; //~ ERROR any use of this value will cause an error
+    //~| ERROR any use of this value will cause an error
 }
 
 fn foo<T>(_: T) -> &'static u8 {
diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr
index 707dfee7cd5..de3459c72dd 100644
--- a/src/test/ui/consts/const-eval/issue-50814.stderr
+++ b/src/test/ui/consts/const-eval/issue-50814.stderr
@@ -9,13 +9,21 @@ LL |     const MAX: u8 = A::MAX + B::MAX;
    = note: `#[deny(const_err)]` on by default
 
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/issue-50814.rs:17:5
+  --> $DIR/issue-50814.rs:18:5
    |
 LL |     &Sum::<U8,U8>::MAX
    |     ^-----------------
    |      |
    |      referenced constant has errors
 
-error: aborting due to 2 previous errors
+error: any use of this value will cause an error
+  --> $DIR/issue-50814.rs:13:21
+   |
+LL |     const MAX: u8 = A::MAX + B::MAX;
+   |     ----------------^^^^^^^^^^^^^^^-
+   |                     |
+   |                     attempt to add with overflow
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/issues/issue-52060.stderr
index 2f90f7f9e03..6fbc1ed52c4 100644
--- a/src/test/ui/issues/issue-52060.stderr
+++ b/src/test/ui/issues/issue-52060.stderr
@@ -6,4 +6,5 @@ LL | static B: [u32; 1] = [0; A.len()];
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0013`.
+Some errors have detailed explanations: E0013, E0080.
+For more information about an error, try `rustc --explain E0013`.