Skip to content

Commit

Permalink
Const-propagate casts
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Jul 18, 2018
1 parent 1f4e210 commit 9329957
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 15 deletions.
48 changes: 34 additions & 14 deletions src/librustc_mir/transform/const_prop.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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
},
};
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 6 additions & 1 deletion src/test/run-pass/cast-rfc0401.rs
Expand Up @@ -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

Expand Down
3 changes: 3 additions & 0 deletions src/test/ui/const-eval/promoted_errors.rs
Expand Up @@ -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
}
18 changes: 18 additions & 0 deletions src/test/ui/const-eval/promoted_errors.stderr
Expand Up @@ -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

0 comments on commit 9329957

Please sign in to comment.