Skip to content

Commit b3b8760

Browse files
committed
Auto merge of #55385 - davidtwco:issue-55288, r=oli-obk
NLL: cast causes failure to promote to static Fixes #55288. See commit messages for more details. r? @oli-obk cc @nikomatsakis cc @pnkfelix cc @RalfJung
2 parents f32f111 + 6208bd8 commit b3b8760

File tree

14 files changed

+356
-194
lines changed

14 files changed

+356
-194
lines changed

src/librustc/mir/visit.rs

+191-99
Large diffs are not rendered by default.

src/librustc_codegen_llvm/mir/analyze.rs

+32-17
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_data_structures::bit_set::BitSet;
1515
use rustc_data_structures::graph::dominators::Dominators;
1616
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
1717
use rustc::mir::{self, Location, TerminatorKind};
18-
use rustc::mir::visit::{Visitor, PlaceContext};
18+
use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
1919
use rustc::mir::traversal;
2020
use rustc::ty;
2121
use rustc::ty::layout::LayoutOf;
@@ -116,7 +116,11 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
116116
self.not_ssa(index);
117117
}
118118
} else {
119-
self.visit_place(place, PlaceContext::Store, location);
119+
self.visit_place(
120+
place,
121+
PlaceContext::MutatingUse(MutatingUseContext::Store),
122+
location
123+
);
120124
}
121125

122126
self.visit_rvalue(rvalue, location);
@@ -142,7 +146,11 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
142146
// is not guaranteed to be statically dominated by the
143147
// definition of x, so x must always be in an alloca.
144148
if let mir::Operand::Move(ref place) = args[0] {
145-
self.visit_place(place, PlaceContext::Drop, location);
149+
self.visit_place(
150+
place,
151+
PlaceContext::MutatingUse(MutatingUseContext::Drop),
152+
location
153+
);
146154
}
147155
}
148156
}
@@ -160,7 +168,8 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
160168
if let mir::Place::Projection(ref proj) = *place {
161169
// Allow uses of projections that are ZSTs or from scalar fields.
162170
let is_consume = match context {
163-
PlaceContext::Copy | PlaceContext::Move => true,
171+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
172+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true,
164173
_ => false
165174
};
166175
if is_consume {
@@ -190,7 +199,11 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
190199

191200
// A deref projection only reads the pointer, never needs the place.
192201
if let mir::ProjectionElem::Deref = proj.elem {
193-
return self.visit_place(&proj.base, PlaceContext::Copy, location);
202+
return self.visit_place(
203+
&proj.base,
204+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
205+
location
206+
);
194207
}
195208
}
196209

@@ -202,16 +215,14 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
202215
context: PlaceContext<'tcx>,
203216
location: Location) {
204217
match context {
205-
PlaceContext::Call => {
218+
PlaceContext::MutatingUse(MutatingUseContext::Call) => {
206219
self.assign(local, location);
207220
}
208221

209-
PlaceContext::StorageLive |
210-
PlaceContext::StorageDead |
211-
PlaceContext::Validate => {}
222+
PlaceContext::NonUse(_) => {}
212223

213-
PlaceContext::Copy |
214-
PlaceContext::Move => {
224+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
225+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => {
215226
// Reads from uninitialized variables (e.g. in dead code, after
216227
// optimizations) require locals to be in (uninitialized) memory.
217228
// NB: there can be uninitialized reads of a local visited after
@@ -227,15 +238,19 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
227238
}
228239
}
229240

230-
PlaceContext::Inspect |
231-
PlaceContext::Store |
232-
PlaceContext::AsmOutput |
233-
PlaceContext::Borrow { .. } |
234-
PlaceContext::Projection(..) => {
241+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) |
242+
PlaceContext::MutatingUse(MutatingUseContext::Store) |
243+
PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) |
244+
PlaceContext::MutatingUse(MutatingUseContext::Borrow(..)) |
245+
PlaceContext::MutatingUse(MutatingUseContext::Projection) |
246+
PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) |
247+
PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow(..)) |
248+
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) |
249+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => {
235250
self.not_ssa(local);
236251
}
237252

238-
PlaceContext::Drop => {
253+
PlaceContext::MutatingUse(MutatingUseContext::Drop) => {
239254
let ty = mir::Place::Local(local).ty(self.fx.mir, self.fx.cx.tcx);
240255
let ty = self.fx.monomorphize(&ty.to_ty(self.fx.cx.tcx));
241256

src/librustc_mir/borrow_check/borrow_set.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ use borrow_check::place_ext::PlaceExt;
1212
use dataflow::indexes::BorrowIndex;
1313
use dataflow::move_paths::MoveData;
1414
use rustc::mir::traversal;
15-
use rustc::mir::visit::{PlaceContext, Visitor};
15+
use rustc::mir::visit::{
16+
PlaceContext, Visitor, NonUseContext, MutatingUseContext, NonMutatingUseContext
17+
};
1618
use rustc::mir::{self, Location, Mir, Place, Local};
1719
use rustc::ty::{Region, TyCtxt};
1820
use rustc::util::nodemap::{FxHashMap, FxHashSet};
@@ -116,7 +118,7 @@ impl LocalsStateAtExit {
116118

117119
impl<'tcx> Visitor<'tcx> for HasStorageDead {
118120
fn visit_local(&mut self, local: &Local, ctx: PlaceContext<'tcx>, _: Location) {
119-
if ctx == PlaceContext::StorageDead {
121+
if ctx == PlaceContext::NonUse(NonUseContext::StorageDead) {
120122
self.0.insert(*local);
121123
}
122124
}
@@ -266,7 +268,9 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
266268

267269
// Watch out: the use of TMP in the borrow itself
268270
// doesn't count as an activation. =)
269-
if borrow_data.reserve_location == location && context == PlaceContext::Store {
271+
if borrow_data.reserve_location == location &&
272+
context == PlaceContext::MutatingUse(MutatingUseContext::Store)
273+
{
270274
return;
271275
}
272276

@@ -287,10 +291,9 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
287291
borrow_data.activation_location = match context {
288292
// The use of TMP in a shared borrow does not
289293
// count as an actual activation.
290-
PlaceContext::Borrow { kind: mir::BorrowKind::Shared, .. }
291-
| PlaceContext::Borrow { kind: mir::BorrowKind::Shallow, .. } => {
292-
TwoPhaseActivation::NotActivated
293-
}
294+
PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) |
295+
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) =>
296+
TwoPhaseActivation::NotActivated,
294297
_ => {
295298
// Double check: This borrow is indeed a two-phase borrow (that is,
296299
// we are 'transitioning' from `NotActivated` to `ActivatedAt`) and

src/librustc_mir/borrow_check/nll/type_check/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use rustc::infer::outlives::env::RegionBoundPairs;
3535
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
3636
use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
3737
use rustc::mir::tcx::PlaceTy;
38-
use rustc::mir::visit::{PlaceContext, Visitor};
38+
use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
3939
use rustc::mir::*;
4040
use rustc::traits::query::type_op;
4141
use rustc::traits::query::type_op::custom::CustomTypeOp;
@@ -472,9 +472,9 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
472472
}
473473
Place::Projection(ref proj) => {
474474
let base_context = if context.is_mutating_use() {
475-
PlaceContext::Projection(Mutability::Mut)
475+
PlaceContext::MutatingUse(MutatingUseContext::Projection)
476476
} else {
477-
PlaceContext::Projection(Mutability::Not)
477+
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
478478
};
479479
let base_ty = self.sanitize_place(&proj.base, location, base_context);
480480
if let PlaceTy::Ty { ty } = base_ty {
@@ -488,7 +488,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
488488
self.sanitize_projection(base_ty, &proj.elem, place, location)
489489
}
490490
};
491-
if let PlaceContext::Copy = context {
491+
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
492492
let tcx = self.tcx();
493493
let trait_ref = ty::TraitRef {
494494
def_id: tcx.lang_items().copy_trait().unwrap(),

src/librustc_mir/borrow_check/used_muts.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use rustc::mir::{Local, Location, Place};
1414
use rustc_data_structures::fx::FxHashSet;
1515

1616
use borrow_check::MirBorrowckCtxt;
17-
use util::collect_writes::is_place_assignment;
1817

1918
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
2019
/// Walks the MIR looking for assignments to a set of locals, as part of the unused mutable
@@ -46,7 +45,7 @@ impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'c
4645
return;
4746
}
4847

49-
if is_place_assignment(&place_context) {
48+
if place_context.is_place_assignment() {
5049
// Propagate the Local assigned at this Location as a used mutable local variable
5150
for moi in &self.mbcx.move_data.loc_map[location] {
5251
let mpi = &self.mbcx.move_data.moves[*moi].path;

src/librustc_mir/transform/check_unsafety.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rustc::hir::Node;
1919
use rustc::hir::def_id::DefId;
2020
use rustc::lint::builtin::{SAFE_EXTERN_STATICS, SAFE_PACKED_BORROWS, UNUSED_UNSAFE};
2121
use rustc::mir::*;
22-
use rustc::mir::visit::{PlaceContext, Visitor};
22+
use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext};
2323

2424
use syntax::ast;
2525
use syntax::symbol::Symbol;
@@ -152,7 +152,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
152152
place: &Place<'tcx>,
153153
context: PlaceContext<'tcx>,
154154
location: Location) {
155-
if let PlaceContext::Borrow { .. } = context {
155+
if context.is_borrow() {
156156
if util::is_disaligned(self.tcx, self.mir, self.param_env, place) {
157157
let source_info = self.source_info;
158158
let lint_root =
@@ -193,9 +193,11 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
193193
}
194194
ty::Adt(adt, _) => {
195195
if adt.is_union() {
196-
if context == PlaceContext::Store ||
197-
context == PlaceContext::AsmOutput ||
198-
context == PlaceContext::Drop
196+
if context == PlaceContext::MutatingUse(MutatingUseContext::Store) ||
197+
context == PlaceContext::MutatingUse(MutatingUseContext::Drop) ||
198+
context == PlaceContext::MutatingUse(
199+
MutatingUseContext::AsmOutput
200+
)
199201
{
200202
let elem_ty = match elem {
201203
&ProjectionElem::Field(_, ty) => ty,

src/librustc_mir/transform/const_prop.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc::hir::def::Def;
1616
use rustc::mir::{Constant, Location, Place, Mir, Operand, Rvalue, Local};
1717
use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind};
1818
use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
19-
use rustc::mir::visit::{Visitor, PlaceContext};
19+
use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
2020
use rustc::mir::interpret::{
2121
ConstEvalErr, EvalErrorKind, Scalar, GlobalId, EvalResult,
2222
};
@@ -533,17 +533,18 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
533533
// Constants must have at most one write
534534
// FIXME(oli-obk): we could be more powerful here, if the multiple writes
535535
// only occur in independent execution paths
536-
Store => if self.found_assignment[local] {
536+
MutatingUse(MutatingUseContext::Store) => if self.found_assignment[local] {
537537
self.can_const_prop[local] = false;
538538
} else {
539539
self.found_assignment[local] = true
540540
},
541541
// Reading constants is allowed an arbitrary number of times
542-
Copy | Move |
543-
StorageDead | StorageLive |
544-
Validate |
545-
Projection(_) |
546-
Inspect => {},
542+
NonMutatingUse(NonMutatingUseContext::Copy) |
543+
NonMutatingUse(NonMutatingUseContext::Move) |
544+
NonMutatingUse(NonMutatingUseContext::Inspect) |
545+
NonMutatingUse(NonMutatingUseContext::Projection) |
546+
MutatingUse(MutatingUseContext::Projection) |
547+
NonUse(_) => {},
547548
_ => self.can_const_prop[local] = false,
548549
}
549550
}

src/librustc_mir/transform/promote_consts.rs

+15-10
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
//! move analysis runs after promotion on broken MIR.
2424
2525
use rustc::mir::*;
26-
use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor};
26+
use rustc::mir::visit::{PlaceContext, MutatingUseContext, MutVisitor, Visitor};
2727
use rustc::mir::traversal::ReversePostorder;
2828
use rustc::ty::TyCtxt;
2929
use syntax_pos::Span;
@@ -53,6 +53,7 @@ pub enum TempState {
5353

5454
impl TempState {
5555
pub fn is_promotable(&self) -> bool {
56+
debug!("is_promotable: self={:?}", self);
5657
if let TempState::Defined { uses, .. } = *self {
5758
uses > 0
5859
} else {
@@ -88,24 +89,30 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
8889
&index: &Local,
8990
context: PlaceContext<'tcx>,
9091
location: Location) {
92+
debug!("visit_local: index={:?} context={:?} location={:?}", index, context, location);
9193
// We're only interested in temporaries
9294
if self.mir.local_kind(index) != LocalKind::Temp {
9395
return;
9496
}
9597

9698
// Ignore drops, if the temp gets promoted,
9799
// then it's constant and thus drop is noop.
98-
// Storage live ranges are also irrelevant.
99-
if context.is_drop() || context.is_storage_marker() {
100+
// Non-uses are also irrelevent.
101+
if context.is_drop() || !context.is_use() {
102+
debug!(
103+
"visit_local: context.is_drop={:?} context.is_use={:?}",
104+
context.is_drop(), context.is_use(),
105+
);
100106
return;
101107
}
102108

103109
let temp = &mut self.temps[index];
110+
debug!("visit_local: temp={:?}", temp);
104111
if *temp == TempState::Undefined {
105112
match context {
106-
PlaceContext::Store |
107-
PlaceContext::AsmOutput |
108-
PlaceContext::Call => {
113+
PlaceContext::MutatingUse(MutatingUseContext::Store) |
114+
PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) |
115+
PlaceContext::MutatingUse(MutatingUseContext::Call) => {
109116
*temp = TempState::Defined {
110117
location,
111118
uses: 0
@@ -117,10 +124,8 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
117124
} else if let TempState::Defined { ref mut uses, .. } = *temp {
118125
// We always allow borrows, even mutable ones, as we need
119126
// to promote mutable borrows of some ZSTs e.g. `&mut []`.
120-
let allowed_use = match context {
121-
PlaceContext::Borrow {..} => true,
122-
_ => context.is_nonmutating_use()
123-
};
127+
let allowed_use = context.is_borrow() || context.is_nonmutating_use();
128+
debug!("visit_local: allowed_use={:?}", allowed_use);
124129
if allowed_use {
125130
*uses += 1;
126131
return;

0 commit comments

Comments
 (0)