Skip to content

Commit 16fe8cc

Browse files
committed
Remove the self.mir field from ConstPropagator
1 parent 758dc9a commit 16fe8cc

File tree

2 files changed

+80
-56
lines changed

2 files changed

+80
-56
lines changed

src/librustc_mir/transform/const_prop.rs

+71-53
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
//! Propagates constants for early reporting of statically known
22
//! assertion failures
33
4-
54
use rustc::hir::def::Def;
6-
use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local};
7-
use rustc::mir::{NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind};
8-
use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
5+
use rustc::mir::{
6+
Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local,
7+
NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind,
8+
TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem,
9+
SourceScope, SourceScopeLocalData, LocalDecl, Promoted,
10+
};
911
use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
1012
use rustc::mir::interpret::{InterpError, Scalar, GlobalId, EvalResult};
11-
use rustc::ty::{self, Instance, Ty, TyCtxt};
12-
use syntax::source_map::{Span, DUMMY_SP};
13+
use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
14+
use syntax::source_map::DUMMY_SP;
1315
use rustc::ty::subst::InternalSubsts;
1416
use rustc_data_structures::indexed_vec::IndexVec;
15-
use rustc::ty::ParamEnv;
1617
use rustc::ty::layout::{
1718
LayoutOf, TyLayout, LayoutError,
1819
HasTyCtxt, TargetDataLayout, HasDataLayout,
@@ -62,21 +63,33 @@ impl MirPass for ConstProp {
6263
let mut optimization_finder = ConstPropagator::new(mir, tcx, source);
6364
optimization_finder.visit_mir(mir);
6465

66+
// put back the data we stole from `mir`
67+
std::mem::replace(
68+
&mut mir.source_scope_local_data,
69+
optimization_finder.source_scope_local_data
70+
);
71+
std::mem::replace(
72+
&mut mir.promoted,
73+
optimization_finder.promoted
74+
);
75+
6576
trace!("ConstProp done for {:?}", source.def_id());
6677
}
6778
}
6879

69-
type Const<'tcx> = (OpTy<'tcx>, Span);
80+
type Const<'tcx> = OpTy<'tcx>;
7081

7182
/// Finds optimization opportunities on the MIR.
7283
struct ConstPropagator<'a, 'mir, 'tcx:'a+'mir> {
7384
ecx: InterpretCx<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
74-
mir: &'mir Mir<'tcx>,
7585
tcx: TyCtxt<'a, 'tcx, 'tcx>,
7686
source: MirSource<'tcx>,
7787
places: IndexVec<Local, Option<Const<'tcx>>>,
7888
can_const_prop: IndexVec<Local, bool>,
7989
param_env: ParamEnv<'tcx>,
90+
source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
91+
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
92+
promoted: IndexVec<Promoted, Mir<'tcx>>,
8093
}
8194

8295
impl<'a, 'b, 'tcx> LayoutOf for ConstPropagator<'a, 'b, 'tcx> {
@@ -104,20 +117,33 @@ impl<'a, 'b, 'tcx> HasTyCtxt<'tcx> for ConstPropagator<'a, 'b, 'tcx> {
104117

105118
impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
106119
fn new(
107-
mir: &'mir Mir<'tcx>,
120+
mir: &mut Mir<'tcx>,
108121
tcx: TyCtxt<'a, 'tcx, 'tcx>,
109122
source: MirSource<'tcx>,
110123
) -> ConstPropagator<'a, 'mir, 'tcx> {
111124
let param_env = tcx.param_env(source.def_id());
112125
let ecx = mk_eval_cx(tcx, tcx.def_span(source.def_id()), param_env);
126+
let can_const_prop = CanConstProp::check(mir);
127+
let source_scope_local_data = std::mem::replace(
128+
&mut mir.source_scope_local_data,
129+
ClearCrossCrate::Clear
130+
);
131+
let promoted = std::mem::replace(
132+
&mut mir.promoted,
133+
IndexVec::new()
134+
);
135+
113136
ConstPropagator {
114137
ecx,
115-
mir,
116138
tcx,
117139
source,
118140
param_env,
119-
can_const_prop: CanConstProp::check(mir),
141+
can_const_prop,
120142
places: IndexVec::from_elem(None, &mir.local_decls),
143+
source_scope_local_data,
144+
//FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_mir()` needs it
145+
local_decls: mir.local_decls.clone(),
146+
promoted,
121147
}
122148
}
123149

@@ -130,7 +156,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
130156
F: FnOnce(&mut Self) -> EvalResult<'tcx, T>,
131157
{
132158
self.ecx.tcx.span = source_info.span;
133-
let lint_root = match self.mir.source_scope_local_data {
159+
let lint_root = match self.source_scope_local_data {
134160
ClearCrossCrate::Set(ref ivs) => {
135161
//FIXME(#51314): remove this check
136162
if source_info.scope.index() >= ivs.len() {
@@ -252,12 +278,11 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
252278
fn eval_constant(
253279
&mut self,
254280
c: &Constant<'tcx>,
255-
source_info: SourceInfo,
256281
) -> Option<Const<'tcx>> {
257-
self.ecx.tcx.span = source_info.span;
282+
self.ecx.tcx.span = c.span;
258283
match self.ecx.eval_const_to_op(*c.literal, None) {
259284
Ok(op) => {
260-
Some((op, c.span))
285+
Some(op)
261286
},
262287
Err(error) => {
263288
let err = error_to_const_error(&self.ecx, error);
@@ -273,11 +298,11 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
273298
Place::Projection(ref proj) => match proj.elem {
274299
ProjectionElem::Field(field, _) => {
275300
trace!("field proj on {:?}", proj.base);
276-
let (base, span) = self.eval_place(&proj.base, source_info)?;
301+
let base = self.eval_place(&proj.base, source_info)?;
277302
let res = self.use_ecx(source_info, |this| {
278303
this.ecx.operand_field(base, field.index() as u64)
279304
})?;
280-
Some((res, span))
305+
Some(res)
281306
},
282307
// We could get more projections by using e.g., `operand_projection`,
283308
// but we do not even have the stack frame set up properly so
@@ -301,19 +326,19 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
301326
// cannot use `const_eval` here, because that would require having the MIR
302327
// for the current function available, but we're producing said MIR right now
303328
let res = self.use_ecx(source_info, |this| {
304-
let mir = &this.mir.promoted[promoted];
329+
let mir = &this.promoted[promoted];
305330
eval_promoted(this.tcx, cid, mir, this.param_env)
306331
})?;
307332
trace!("evaluated promoted {:?} to {:?}", promoted, res);
308-
Some((res.into(), source_info.span))
333+
Some(res.into())
309334
},
310335
_ => None,
311336
}
312337
}
313338

314339
fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
315340
match *op {
316-
Operand::Constant(ref c) => self.eval_constant(c, source_info),
341+
Operand::Constant(ref c) => self.eval_constant(c),
317342
| Operand::Move(ref place)
318343
| Operand::Copy(ref place) => self.eval_place(place, source_info),
319344
}
@@ -337,18 +362,18 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
337362
Rvalue::Discriminant(..) => None,
338363

339364
Rvalue::Cast(kind, ref operand, _) => {
340-
let (op, span) = self.eval_operand(operand, source_info)?;
365+
let op = self.eval_operand(operand, source_info)?;
341366
self.use_ecx(source_info, |this| {
342367
let dest = this.ecx.allocate(place_layout, MemoryKind::Stack);
343368
this.ecx.cast(op, kind, dest.into())?;
344-
Ok((dest.into(), span))
369+
Ok(dest.into())
345370
})
346371
}
347372

348373
// FIXME(oli-obk): evaluate static/constant slice lengths
349374
Rvalue::Len(_) => None,
350375
Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
351-
type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some((
376+
type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some(
352377
ImmTy {
353378
imm: Immediate::Scalar(
354379
Scalar::Bits {
@@ -357,9 +382,8 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
357382
}.into()
358383
),
359384
layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
360-
}.into(),
361-
span,
362-
)))
385+
}.into()
386+
))
363387
}
364388
Rvalue::UnaryOp(op, ref arg) => {
365389
let def_id = if self.tcx.is_closure(self.source.def_id()) {
@@ -373,7 +397,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
373397
return None;
374398
}
375399

376-
let (arg, _) = self.eval_operand(arg, source_info)?;
400+
let arg = self.eval_operand(arg, source_info)?;
377401
let val = self.use_ecx(source_info, |this| {
378402
let prim = this.ecx.read_immediate(arg)?;
379403
match op {
@@ -395,7 +419,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
395419
imm: Immediate::Scalar(val.into()),
396420
layout: place_layout,
397421
};
398-
Some((res.into(), span))
422+
Some(res.into())
399423
}
400424
Rvalue::CheckedBinaryOp(op, ref left, ref right) |
401425
Rvalue::BinaryOp(op, ref left, ref right) => {
@@ -413,20 +437,20 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
413437
}
414438

415439
let r = self.use_ecx(source_info, |this| {
416-
this.ecx.read_immediate(right.0)
440+
this.ecx.read_immediate(right)
417441
})?;
418442
if op == BinOp::Shr || op == BinOp::Shl {
419-
let left_ty = left.ty(self.mir, self.tcx);
443+
let left_ty = left.ty(&self.local_decls, self.tcx);
420444
let left_bits = self
421445
.tcx
422446
.layout_of(self.param_env.and(left_ty))
423447
.unwrap()
424448
.size
425449
.bits();
426-
let right_size = right.0.layout.size;
450+
let right_size = right.layout.size;
427451
let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
428452
if r_bits.ok().map_or(false, |b| b >= left_bits as u128) {
429-
let source_scope_local_data = match self.mir.source_scope_local_data {
453+
let source_scope_local_data = match self.source_scope_local_data {
430454
ClearCrossCrate::Set(ref data) => data,
431455
ClearCrossCrate::Clear => return None,
432456
};
@@ -446,7 +470,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
446470
}
447471
let left = self.eval_operand(left, source_info)?;
448472
let l = self.use_ecx(source_info, |this| {
449-
this.ecx.read_immediate(left.0)
473+
this.ecx.read_immediate(left)
450474
})?;
451475
trace!("const evaluating {:?} for {:?} and {:?}", op, left, right);
452476
let (val, overflow) = self.use_ecx(source_info, |this| {
@@ -469,7 +493,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
469493
imm: val,
470494
layout: place_layout,
471495
};
472-
Some((res.into(), span))
496+
Some(res.into())
473497
},
474498
}
475499
}
@@ -544,8 +568,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
544568
) {
545569
trace!("visit_constant: {:?}", constant);
546570
self.super_constant(constant, location);
547-
let source_info = *self.mir.source_info(location);
548-
self.eval_constant(constant, source_info);
571+
self.eval_constant(constant);
549572
}
550573

551574
fn visit_statement(
@@ -556,7 +579,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
556579
trace!("visit_statement: {:?}", statement);
557580
if let StatementKind::Assign(ref place, ref rval) = statement.kind {
558581
let place_ty: Ty<'tcx> = place
559-
.ty(&self.mir.local_decls, self.tcx)
582+
.ty(&self.local_decls, self.tcx)
560583
.ty;
561584
if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
562585
if let Some(value) = self.const_prop(rval, place_layout, statement.source_info) {
@@ -574,18 +597,18 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
574597
self.super_statement(statement, location);
575598
}
576599

577-
fn visit_terminator_kind(
600+
fn visit_terminator(
578601
&mut self,
579-
kind: &TerminatorKind<'tcx>,
602+
terminator: &Terminator<'tcx>,
580603
location: Location,
581604
) {
582-
self.super_terminator_kind(kind, location);
583-
let source_info = *self.mir.source_info(location);
584-
if let TerminatorKind::Assert { expected, msg, cond, .. } = kind {
585-
if let Some(value) = self.eval_operand(cond, source_info) {
605+
self.super_terminator(terminator, location);
606+
let source_info = terminator.source_info;;
607+
if let TerminatorKind::Assert { expected, msg, cond, .. } = &terminator.kind {
608+
if let Some(value) = self.eval_operand(&cond, source_info) {
586609
trace!("assertion on {:?} should be {:?}", value, expected);
587610
let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected));
588-
if expected != self.ecx.read_scalar(value.0).unwrap() {
611+
if expected != self.ecx.read_scalar(value).unwrap() {
589612
// poison all places this operand references so that further code
590613
// doesn't use the invalid value
591614
match cond {
@@ -600,12 +623,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
600623
},
601624
Operand::Constant(_) => {}
602625
}
603-
let span = self.mir[location.block]
604-
.terminator
605-
.as_ref()
606-
.unwrap()
607-
.source_info
608-
.span;
626+
let span = terminator.source_info.span;
609627
let hir_id = self
610628
.tcx
611629
.hir()
@@ -621,7 +639,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
621639
let len = self
622640
.eval_operand(len, source_info)
623641
.expect("len must be const");
624-
let len = match self.ecx.read_scalar(len.0) {
642+
let len = match self.ecx.read_scalar(len) {
625643
Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
626644
bits, ..
627645
})) => bits,
@@ -630,7 +648,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
630648
let index = self
631649
.eval_operand(index, source_info)
632650
.expect("index must be const");
633-
let index = match self.ecx.read_scalar(index.0) {
651+
let index = match self.ecx.read_scalar(index) {
634652
Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
635653
bits, ..
636654
})) => bits,

src/test/ui/consts/const-err.stderr

+9-3
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,17 @@ LL | #![warn(const_err)]
1313
| ^^^^^^^^^
1414

1515
error[E0080]: erroneous constant used
16-
--> $DIR/const-err.rs:14:15
16+
--> $DIR/const-err.rs:14:16
1717
|
1818
LL | black_box((FOO, FOO));
19-
| ^^^^^^^^^^ referenced constant has errors
19+
| ^^^ referenced constant has errors
2020

21-
error: aborting due to previous error
21+
error[E0080]: erroneous constant used
22+
--> $DIR/const-err.rs:14:21
23+
|
24+
LL | black_box((FOO, FOO));
25+
| ^^^ referenced constant has errors
26+
27+
error: aborting due to 2 previous errors
2228

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

0 commit comments

Comments
 (0)