From 9329957d321a3612fe9c95cf58a67115b0bbda5f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 18 Jul 2018 14:23:07 +0200 Subject: [PATCH] Const-propagate casts --- src/librustc_mir/transform/const_prop.rs | 48 +++++++++++++------ src/test/run-pass/cast-rfc0401.rs | 7 ++- src/test/ui/const-eval/promoted_errors.rs | 3 ++ src/test/ui/const-eval/promoted_errors.stderr | 18 +++++++ 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::{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( 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; 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 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 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 + -- 2.44.0