]> git.lizzy.rs Git - rust.git/commitdiff
Const-propagate casts
authorOliver Schneider <github35764891676564198441@oli-obk.de>
Wed, 18 Jul 2018 12:23:07 +0000 (14:23 +0200)
committerOliver Schneider <github35764891676564198441@oli-obk.de>
Wed, 18 Jul 2018 16:52:43 +0000 (18:52 +0200)
src/librustc_mir/transform/const_prop.rs
src/test/run-pass/cast-rfc0401.rs
src/test/ui/const-eval/promoted_errors.rs
src/test/ui/const-eval/promoted_errors.stderr

index 3b3c28f6ae2655c2dbd9df61e247ad1be3e33b81..d15dd14084aad5faf2521d3e91942d012bf6ff8d 100644 (file)
@@ -17,7 +17,7 @@
 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 @@ fn use_ecx<F, T>(
         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 @@ fn const_prop(
             },
             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 @@ fn const_prop(
                     )
                 } 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;
index 5b6f6ccc627a41f4c245799df9f2fe7763e3fe39..022ed6c28c3bdf8400f205951a08f4f6ec14955a 100644 (file)
@@ -166,7 +166,12 @@ fn bar() {
 
     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
 
index a39afb9bdd4a477e3f14c5a741ee46e8182fb0c1..04e9bfbc03e27bbe6267d0e851674c3dc3643b9d 100644 (file)
@@ -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
 }
index a4c1c48a03dfe30f1a5a5f6f3076b9e7ccd884a8..9afe5f20af39402071ba632d149c00d671821bde 100644 (file)
@@ -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
+