about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorOliver Schneider <github35764891676564198441@oli-obk.de>2018-07-18 14:23:07 +0200
committerOliver Schneider <github35764891676564198441@oli-obk.de>2018-07-18 18:52:43 +0200
commit9329957d321a3612fe9c95cf58a67115b0bbda5f (patch)
treee2d1fb7fb1508f6d00bde640f2a5df837c30c89d /src
parent1f4e21028d34c0aeccc4c7b21e0d9ce044c5646c (diff)
downloadrust-9329957d321a3612fe9c95cf58a67115b0bbda5f.tar.gz
rust-9329957d321a3612fe9c95cf58a67115b0bbda5f.zip
Const-propagate casts
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/transform/const_prop.rs48
-rw-r--r--src/test/run-pass/cast-rfc0401.rs7
-rw-r--r--src/test/ui/const-eval/promoted_errors.rs3
-rw-r--r--src/test/ui/const-eval/promoted_errors.stderr18
4 files changed, 61 insertions, 15 deletions
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 3b3c28f6ae2..d15dd14084a 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -17,7 +17,7 @@ use rustc::mir::{Constant, Literal, Location, Place, Mir, Operand, Rvalue, Local
 use rustc::mir::{NullOp, StatementKind, Statement, BasicBlock, LocalKind};
 use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
 use rustc::mir::visit::{Visitor, PlaceContext};
-use rustc::mir::interpret::ConstEvalErr;
+use rustc::mir::interpret::{ConstEvalErr, EvalErrorKind};
 use rustc::ty::{TyCtxt, self, Instance};
 use rustc::mir::interpret::{Value, Scalar, GlobalId, EvalResult};
 use interpret::EvalContext;
@@ -145,17 +145,23 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
         let r = match f(self) {
             Ok(val) => Some(val),
             Err(err) => {
-                let (frames, span) = self.ecx.generate_stacktrace(None);
-                let err = ConstEvalErr {
-                    span,
-                    error: err,
-                    stacktrace: frames,
-                };
-                err.report_as_lint(
-                    self.ecx.tcx,
-                    "this expression will panic at runtime",
-                    lint_root,
-                );
+                match err.kind {
+                    // don't report these, they make no sense in a const prop context
+                    EvalErrorKind::MachineError(_) => {},
+                    _ => {
+                        let (frames, span) = self.ecx.generate_stacktrace(None);
+                        let err = ConstEvalErr {
+                            span,
+                            error: err,
+                            stacktrace: frames,
+                        };
+                        err.report_as_lint(
+                            self.ecx.tcx,
+                            "this expression will panic at runtime",
+                            lint_root,
+                        );
+                    }
+                }
                 None
             },
         };
@@ -257,10 +263,25 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
             },
             Rvalue::Repeat(..) |
             Rvalue::Ref(..) |
-            Rvalue::Cast(..) |
             Rvalue::Aggregate(..) |
             Rvalue::NullaryOp(NullOp::Box, _) |
             Rvalue::Discriminant(..) => None,
+
+            Rvalue::Cast(kind, ref operand, _) => {
+                let (value, ty, span) = self.eval_operand(operand, source_info)?;
+                self.use_ecx(source_info, |this| {
+                    let dest_ptr = this.ecx.alloc_ptr(place_ty)?;
+                    let place_align = this.ecx.layout_of(place_ty)?.align;
+                    let dest = ::interpret::Place::from_ptr(dest_ptr, place_align);
+                    this.ecx.cast(ValTy { value, ty }, kind, place_ty, dest)?;
+                    Ok((
+                        Value::ByRef(dest_ptr.into(), place_align),
+                        place_ty,
+                        span,
+                    ))
+                })
+            }
+
             // FIXME(oli-obk): evaluate static/constant slice lengths
             Rvalue::Len(_) => None,
             Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
@@ -354,7 +375,6 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
                     )
                 } else {
                     if overflow {
-                        use rustc::mir::interpret::EvalErrorKind;
                         let err = EvalErrorKind::Overflow(op).into();
                         let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
                         return None;
diff --git a/src/test/run-pass/cast-rfc0401.rs b/src/test/run-pass/cast-rfc0401.rs
index 5b6f6ccc627..022ed6c28c3 100644
--- a/src/test/run-pass/cast-rfc0401.rs
+++ b/src/test/run-pass/cast-rfc0401.rs
@@ -166,7 +166,12 @@ fn main()
 
     assert!(foo as usize != bar as usize);
 
-    assert_eq!(foo as i16, foo as usize as i16);
+    // Taking a few bits of a function's address is totally pointless and we detect that
+    // Disabling the lint to ensure that the assertion can still be run
+    #[allow(const_err)]
+    {
+        assert_eq!(foo as i16, foo as usize as i16);
+    }
 
     // fptr-ptr-cast
 
diff --git a/src/test/ui/const-eval/promoted_errors.rs b/src/test/ui/const-eval/promoted_errors.rs
index a39afb9bdd4..04e9bfbc03e 100644
--- a/src/test/ui/const-eval/promoted_errors.rs
+++ b/src/test/ui/const-eval/promoted_errors.rs
@@ -24,5 +24,8 @@ fn main() {
     //~| WARN const_err
     println!("{}", 1/(false as u32));
     //~^ WARN const_err
+    //~| WARN const_err
     let _x = 1/(false as u32);
+    //~^ WARN const_err
+    //~| WARN const_err
 }
diff --git a/src/test/ui/const-eval/promoted_errors.stderr b/src/test/ui/const-eval/promoted_errors.stderr
index a4c1c48a03d..9afe5f20af3 100644
--- a/src/test/ui/const-eval/promoted_errors.stderr
+++ b/src/test/ui/const-eval/promoted_errors.stderr
@@ -34,9 +34,27 @@ warning: this expression will panic at runtime
 LL |     let _x = 1/(1-1);
    |              ^^^^^^^ attempt to divide by zero
 
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:25:20
+   |
+LL |     println!("{}", 1/(false as u32));
+   |                    ^^^^^^^^^^^^^^^^
+
 warning: this expression will panic at runtime
   --> $DIR/promoted_errors.rs:25:20
    |
 LL |     println!("{}", 1/(false as u32));
    |                    ^^^^^^^^^^^^^^^^ attempt to divide by zero
 
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:28:14
+   |
+LL |     let _x = 1/(false as u32);
+   |              ^^^^^^^^^^^^^^^^
+
+warning: this expression will panic at runtime
+  --> $DIR/promoted_errors.rs:28:14
+   |
+LL |     let _x = 1/(false as u32);
+   |              ^^^^^^^^^^^^^^^^ attempt to divide by zero
+