Skip to content

Commit bc17936

Browse files
committed
[const-prop] Replace eval_place() with use of InterpCx
1 parent 59367b0 commit bc17936

File tree

9 files changed

+43
-57
lines changed

9 files changed

+43
-57
lines changed

src/librustc/mir/interpret/error.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,14 @@ pub enum UnsupportedOpInfo<'tcx> {
389389
/// Free-form case. Only for errors that are never caught!
390390
Unsupported(String),
391391

392+
/// Error used by the `ConstProp` pass when an attempt is made
393+
/// to read an uninitialized local.
394+
UninitializedLocal,
395+
396+
/// Error used by the `ConstProp` pass to prevent reading statics
397+
/// while evaluating `const` items.
398+
ReadOfStaticInConst,
399+
392400
// -- Everything below is not categorized yet --
393401
FunctionAbiMismatch(Abi, Abi),
394402
FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
@@ -511,6 +519,8 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
511519
addresses, e.g., comparing pointers into different allocations"),
512520
DeadLocal =>
513521
write!(f, "tried to access a dead local variable"),
522+
UninitializedLocal =>
523+
write!(f, "tried to access an uninitialized local variable"),
514524
DerefFunctionPointer =>
515525
write!(f, "tried to dereference a function pointer"),
516526
ExecuteMemory =>
@@ -552,6 +562,8 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
552562
not a power of two"),
553563
Unsupported(ref msg) =>
554564
write!(f, "{}", msg),
565+
ReadOfStaticInConst =>
566+
write!(f, "tried to read from a static during const evaluation"),
555567
}
556568
}
557569
}

src/librustc_mir/interpret/eval_context.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,7 @@ impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
134134
pub fn access(&self) -> InterpResult<'tcx, Operand<Tag>> {
135135
match self.value {
136136
LocalValue::Dead => throw_unsup!(DeadLocal),
137-
LocalValue::Uninitialized =>
138-
bug!("The type checker should prevent reading from a never-written local"),
137+
LocalValue::Uninitialized => throw_unsup!(UninitializedLocal),
139138
LocalValue::Live(val) => Ok(val),
140139
}
141140
}

src/librustc_mir/interpret/operand.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
481481

482482
// Evaluate a place with the goal of reading from it. This lets us sometimes
483483
// avoid allocations.
484-
pub(super) fn eval_place_to_op(
484+
pub fn eval_place_to_op(
485485
&self,
486486
place: &mir::Place<'tcx>,
487487
layout: Option<TyLayout<'tcx>>,

src/librustc_mir/interpret/place.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,15 @@ where
597597
}
598598

599599
StaticKind::Static => {
600+
//if the first frame on the stack isn't a static item, then we shouldn't
601+
//eval any static places (unless -Z unleash-the-miri-inside-of-you is on)
602+
if let ty::InstanceDef::Item(item_def_id) = self.stack[0].instance.def {
603+
if !self.tcx.is_static(item_def_id) &&
604+
!self.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you {
605+
trace!("eval_static_to_mplace: can't eval static in constant");
606+
throw_unsup!(ReadOfStaticInConst);
607+
}
608+
}
600609
let ty = place_static.ty;
601610
assert!(!ty.needs_subst());
602611
let layout = self.layout_of(ty)?;

src/librustc_mir/transform/const_prop.rs

Lines changed: 6 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ use std::cell::Cell;
66
use rustc::hir::def::DefKind;
77
use rustc::mir::{
88
AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue,
9-
Local, NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind,
10-
TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem,
9+
Local, NullOp, UnOp, StatementKind, Statement, LocalKind,
10+
TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp,
1111
SourceScope, SourceScopeLocalData, LocalDecl,
1212
};
1313
use rustc::mir::visit::{
1414
Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext,
1515
};
16-
use rustc::mir::interpret::{Scalar, GlobalId, InterpResult, PanicInfo};
16+
use rustc::mir::interpret::{Scalar, InterpResult, PanicInfo};
1717
use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
1818
use syntax_pos::{Span, DUMMY_SP};
1919
use rustc::ty::subst::InternalSubsts;
@@ -282,53 +282,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
282282

283283
fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
284284
trace!("eval_place(place={:?})", place);
285-
let mut eval = match place.base {
286-
PlaceBase::Local(loc) => self.get_const(loc).clone()?,
287-
PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted, _), ..}) => {
288-
let generics = self.tcx.generics_of(self.source.def_id());
289-
if generics.requires_monomorphization(self.tcx) {
290-
// FIXME: can't handle code with generics
291-
return None;
292-
}
293-
let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
294-
let instance = Instance::new(self.source.def_id(), substs);
295-
let cid = GlobalId {
296-
instance,
297-
promoted: Some(promoted),
298-
};
299-
let res = self.use_ecx(source_info, |this| {
300-
this.ecx.const_eval_raw(cid)
301-
})?;
302-
trace!("evaluated promoted {:?} to {:?}", promoted, res);
303-
res.into()
304-
}
305-
_ => return None,
306-
};
307-
308-
for (i, elem) in place.projection.iter().enumerate() {
309-
let proj_base = &place.projection[..i];
310-
311-
match elem {
312-
ProjectionElem::Field(field, _) => {
313-
trace!("field proj on {:?}", proj_base);
314-
eval = self.use_ecx(source_info, |this| {
315-
this.ecx.operand_field(eval, field.index() as u64)
316-
})?;
317-
},
318-
ProjectionElem::Deref => {
319-
trace!("processing deref");
320-
eval = self.use_ecx(source_info, |this| {
321-
this.ecx.deref_operand(eval)
322-
})?.into();
323-
}
324-
// We could get more projections by using e.g., `operand_projection`,
325-
// but we do not even have the stack frame set up properly so
326-
// an `Index` projection would throw us off-track.
327-
_ => return None,
328-
}
329-
}
330-
331-
Some(eval)
285+
self.use_ecx(source_info, |this| {
286+
this.ecx.eval_place_to_op(place, None)
287+
})
332288
}
333289

334290
fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {

src/test/mir-opt/const_prop/slice_len.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ fn main() {
3434
// assert(const true, "index out of bounds: the len is move _7 but the index is _6") -> bb1;
3535
// }
3636
// bb1: {
37-
// _1 = (*_2)[_6];
37+
// _1 = const 2u32;
3838
// ...
3939
// return;
4040
// }

src/test/ui/consts/const-eval/issue-50814.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ struct Sum<A,B>(A,B);
1111

1212
impl<A: Unsigned, B: Unsigned> Unsigned for Sum<A,B> {
1313
const MAX: u8 = A::MAX + B::MAX; //~ ERROR any use of this value will cause an error
14+
//~| ERROR any use of this value will cause an error
1415
}
1516

1617
fn foo<T>(_: T) -> &'static u8 {

src/test/ui/consts/const-eval/issue-50814.stderr

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,21 @@ LL | const MAX: u8 = A::MAX + B::MAX;
99
= note: `#[deny(const_err)]` on by default
1010

1111
error[E0080]: evaluation of constant expression failed
12-
--> $DIR/issue-50814.rs:17:5
12+
--> $DIR/issue-50814.rs:18:5
1313
|
1414
LL | &Sum::<U8,U8>::MAX
1515
| ^-----------------
1616
| |
1717
| referenced constant has errors
1818

19-
error: aborting due to 2 previous errors
19+
error: any use of this value will cause an error
20+
--> $DIR/issue-50814.rs:13:21
21+
|
22+
LL | const MAX: u8 = A::MAX + B::MAX;
23+
| ----------------^^^^^^^^^^^^^^^-
24+
| |
25+
| attempt to add with overflow
26+
27+
error: aborting due to 3 previous errors
2028

2129
For more information about this error, try `rustc --explain E0080`.

src/test/ui/issues/issue-52060.stderr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ LL | static B: [u32; 1] = [0; A.len()];
66

77
error: aborting due to previous error
88

9-
For more information about this error, try `rustc --explain E0013`.
9+
Some errors have detailed explanations: E0013, E0080.
10+
For more information about an error, try `rustc --explain E0013`.

0 commit comments

Comments
 (0)