Skip to content

Commit 9329957

Browse files
committed
Const-propagate casts
1 parent 1f4e210 commit 9329957

File tree

4 files changed

+61
-15
lines changed

4 files changed

+61
-15
lines changed

src/librustc_mir/transform/const_prop.rs

+34-14
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc::mir::{Constant, Literal, Location, Place, Mir, Operand, Rvalue, Local
1717
use rustc::mir::{NullOp, StatementKind, Statement, BasicBlock, LocalKind};
1818
use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
1919
use rustc::mir::visit::{Visitor, PlaceContext};
20-
use rustc::mir::interpret::ConstEvalErr;
20+
use rustc::mir::interpret::{ConstEvalErr, EvalErrorKind};
2121
use rustc::ty::{TyCtxt, self, Instance};
2222
use rustc::mir::interpret::{Value, Scalar, GlobalId, EvalResult};
2323
use interpret::EvalContext;
@@ -145,17 +145,23 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
145145
let r = match f(self) {
146146
Ok(val) => Some(val),
147147
Err(err) => {
148-
let (frames, span) = self.ecx.generate_stacktrace(None);
149-
let err = ConstEvalErr {
150-
span,
151-
error: err,
152-
stacktrace: frames,
153-
};
154-
err.report_as_lint(
155-
self.ecx.tcx,
156-
"this expression will panic at runtime",
157-
lint_root,
158-
);
148+
match err.kind {
149+
// don't report these, they make no sense in a const prop context
150+
EvalErrorKind::MachineError(_) => {},
151+
_ => {
152+
let (frames, span) = self.ecx.generate_stacktrace(None);
153+
let err = ConstEvalErr {
154+
span,
155+
error: err,
156+
stacktrace: frames,
157+
};
158+
err.report_as_lint(
159+
self.ecx.tcx,
160+
"this expression will panic at runtime",
161+
lint_root,
162+
);
163+
}
164+
}
159165
None
160166
},
161167
};
@@ -257,10 +263,25 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
257263
},
258264
Rvalue::Repeat(..) |
259265
Rvalue::Ref(..) |
260-
Rvalue::Cast(..) |
261266
Rvalue::Aggregate(..) |
262267
Rvalue::NullaryOp(NullOp::Box, _) |
263268
Rvalue::Discriminant(..) => None,
269+
270+
Rvalue::Cast(kind, ref operand, _) => {
271+
let (value, ty, span) = self.eval_operand(operand, source_info)?;
272+
self.use_ecx(source_info, |this| {
273+
let dest_ptr = this.ecx.alloc_ptr(place_ty)?;
274+
let place_align = this.ecx.layout_of(place_ty)?.align;
275+
let dest = ::interpret::Place::from_ptr(dest_ptr, place_align);
276+
this.ecx.cast(ValTy { value, ty }, kind, place_ty, dest)?;
277+
Ok((
278+
Value::ByRef(dest_ptr.into(), place_align),
279+
place_ty,
280+
span,
281+
))
282+
})
283+
}
284+
264285
// FIXME(oli-obk): evaluate static/constant slice lengths
265286
Rvalue::Len(_) => None,
266287
Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
@@ -354,7 +375,6 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
354375
)
355376
} else {
356377
if overflow {
357-
use rustc::mir::interpret::EvalErrorKind;
358378
let err = EvalErrorKind::Overflow(op).into();
359379
let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
360380
return None;

src/test/run-pass/cast-rfc0401.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,12 @@ fn main()
166166

167167
assert!(foo as usize != bar as usize);
168168

169-
assert_eq!(foo as i16, foo as usize as i16);
169+
// Taking a few bits of a function's address is totally pointless and we detect that
170+
// Disabling the lint to ensure that the assertion can still be run
171+
#[allow(const_err)]
172+
{
173+
assert_eq!(foo as i16, foo as usize as i16);
174+
}
170175

171176
// fptr-ptr-cast
172177

src/test/ui/const-eval/promoted_errors.rs

+3
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,8 @@ fn main() {
2424
//~| WARN const_err
2525
println!("{}", 1/(false as u32));
2626
//~^ WARN const_err
27+
//~| WARN const_err
2728
let _x = 1/(false as u32);
29+
//~^ WARN const_err
30+
//~| WARN const_err
2831
}

src/test/ui/const-eval/promoted_errors.stderr

+18
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,27 @@ warning: this expression will panic at runtime
3434
LL | let _x = 1/(1-1);
3535
| ^^^^^^^ attempt to divide by zero
3636

37+
warning: attempt to divide by zero
38+
--> $DIR/promoted_errors.rs:25:20
39+
|
40+
LL | println!("{}", 1/(false as u32));
41+
| ^^^^^^^^^^^^^^^^
42+
3743
warning: this expression will panic at runtime
3844
--> $DIR/promoted_errors.rs:25:20
3945
|
4046
LL | println!("{}", 1/(false as u32));
4147
| ^^^^^^^^^^^^^^^^ attempt to divide by zero
4248

49+
warning: attempt to divide by zero
50+
--> $DIR/promoted_errors.rs:28:14
51+
|
52+
LL | let _x = 1/(false as u32);
53+
| ^^^^^^^^^^^^^^^^
54+
55+
warning: this expression will panic at runtime
56+
--> $DIR/promoted_errors.rs:28:14
57+
|
58+
LL | let _x = 1/(false as u32);
59+
| ^^^^^^^^^^^^^^^^ attempt to divide by zero
60+

0 commit comments

Comments
 (0)