Skip to content

Commit 732a2dc

Browse files
committed
rustc_mir: split off some qualify_consts::Checker fields into a State struct.
1 parent a5e4d1a commit 732a2dc

File tree

1 file changed

+73
-61
lines changed

1 file changed

+73
-61
lines changed

src/librustc_mir/transform/qualify_consts.rs

Lines changed: 73 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,31 @@ impl fmt::Display for Mode {
9494
}
9595
}
9696

97-
struct Checker<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
97+
struct State {
98+
local_qualif: IndexVec<Local, Option<Qualif>>,
99+
100+
qualif: Qualif,
101+
}
102+
103+
impl State {
104+
/// Add the given qualification to self.qualif.
105+
fn add(&mut self, qualif: Qualif) {
106+
self.qualif = self.qualif | qualif;
107+
}
108+
}
109+
110+
struct Checker<'a, 'gcx, 'tcx> {
111+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
112+
param_env: ty::ParamEnv<'tcx>,
98113
mode: Mode,
99114
span: Span,
100115
def_id: DefId,
101116
mir: &'a Mir<'tcx>,
102117
rpo: ReversePostorder<'a, 'tcx>,
103-
tcx: TyCtxt<'a, 'gcx, 'tcx>,
104-
param_env: ty::ParamEnv<'tcx>,
105-
local_qualif: IndexVec<Local, Option<Qualif>>,
106-
qualif: Qualif,
118+
119+
state: State,
107120
temp_promotion_state: IndexVec<Local, TempState>,
108-
promotion_candidates: Vec<Candidate>
121+
promotion_candidates: Vec<Candidate>,
109122
}
110123

111124
macro_rules! unleash_miri {
@@ -145,8 +158,10 @@ impl<'a, 'tcx> Checker<'a, 'tcx, 'tcx> {
145158
rpo,
146159
tcx,
147160
param_env,
148-
local_qualif,
149-
qualif: Qualif::empty(),
161+
state: State {
162+
local_qualif,
163+
qualif: Qualif::empty(),
164+
},
150165
temp_promotion_state: temps,
151166
promotion_candidates: vec![]
152167
}
@@ -157,7 +172,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx, 'tcx> {
157172
// slightly pointless (even with feature-gating).
158173
fn not_const(&mut self) {
159174
unleash_miri!(self);
160-
self.add(Qualif::NOT_CONST);
175+
self.state.add(Qualif::NOT_CONST);
161176
if self.mode != Mode::Fn {
162177
let mut err = struct_span_err!(
163178
self.tcx.sess,
@@ -176,31 +191,26 @@ impl<'a, 'tcx> Checker<'a, 'tcx, 'tcx> {
176191
}
177192
}
178193

179-
/// Adds the given qualification to `self.qualif`.
180-
fn add(&mut self, qualif: Qualif) {
181-
self.qualif = self.qualif | qualif;
182-
}
183-
184-
/// Adds the given type's qualification to `self.qualif`.
194+
/// Adds the given type's qualification to self.state.qualif.
185195
fn add_type(&mut self, ty: Ty<'tcx>) {
186-
self.add(Qualif::MUTABLE_INTERIOR | Qualif::NEEDS_DROP);
187-
self.qualif.restrict(ty, self.tcx, self.param_env);
196+
self.state.add(Qualif::MUTABLE_INTERIOR | Qualif::NEEDS_DROP);
197+
self.state.qualif.restrict(ty, self.tcx, self.param_env);
188198
}
189199

190-
/// Within the provided closure, `self.qualif` will start
200+
/// Within the provided closure, `self.state.qualif` will start
191201
/// out empty, and its value after the closure returns will
192202
/// be combined with the value before the call to nest.
193203
fn nest<F: FnOnce(&mut Self)>(&mut self, f: F) {
194-
let original = self.qualif;
195-
self.qualif = Qualif::empty();
204+
let original = self.state.qualif;
205+
self.state.qualif = Qualif::empty();
196206
f(self);
197-
self.add(original);
207+
self.state.add(original);
198208
}
199209

200210
/// Assign the current qualification to the given destination.
201211
fn assign(&mut self, dest: &Place<'tcx>, location: Location) {
202212
trace!("assign: {:?}", dest);
203-
let qualif = self.qualif;
213+
let qualif = self.state.qualif;
204214
let span = self.span;
205215
let store = |slot: &mut Option<Qualif>| {
206216
if slot.is_some() {
@@ -215,7 +225,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx, 'tcx> {
215225
if self.mir.local_kind(index) == LocalKind::Temp
216226
&& self.temp_promotion_state[index].is_promotable() {
217227
debug!("store to promotable temp {:?} ({:?})", index, qualif);
218-
store(&mut self.local_qualif[index]);
228+
store(&mut self.state.local_qualif[index]);
219229
}
220230
}
221231
return;
@@ -253,14 +263,14 @@ impl<'a, 'tcx> Checker<'a, 'tcx, 'tcx> {
253263
}
254264
};
255265
debug!("store to var {:?}", index);
256-
match &mut self.local_qualif[index] {
266+
match &mut self.state.local_qualif[index] {
257267
// this is overly restrictive, because even full assignments do not clear the qualif
258268
// While we could special case full assignments, this would be inconsistent with
259269
// aggregates where we overwrite all fields via assignments, which would not get
260270
// that feature.
261-
Some(ref mut qualif) => *qualif = *qualif | self.qualif,
271+
Some(ref mut qualif) => *qualif = *qualif | self.state.qualif,
262272
// insert new qualification
263-
qualif @ None => *qualif = Some(self.qualif),
273+
qualif @ None => *qualif = Some(self.state.qualif),
264274
}
265275
}
266276

@@ -317,12 +327,12 @@ impl<'a, 'tcx> Checker<'a, 'tcx, 'tcx> {
317327
}
318328
}
319329

320-
self.qualif = self.local_qualif[RETURN_PLACE].unwrap_or(Qualif::NOT_CONST);
330+
self.state.qualif = self.state.local_qualif[RETURN_PLACE].unwrap_or(Qualif::NOT_CONST);
321331

322332
// Account for errors in consts by using the
323333
// conservative type qualification instead.
324-
if self.qualif.intersects(Qualif::CONST_ERROR) {
325-
self.qualif = Qualif::empty();
334+
if self.state.qualif.intersects(Qualif::CONST_ERROR) {
335+
self.state.qualif = Qualif::empty();
326336
let return_ty = mir.return_ty();
327337
self.add_type(return_ty);
328338
}
@@ -346,7 +356,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx, 'tcx> {
346356
}
347357
}
348358

349-
(self.qualif, Lrc::new(promoted_temps))
359+
(self.state.qualif, Lrc::new(promoted_temps))
350360
}
351361

352362
fn is_const_panic_fn(&self, def_id: DefId) -> bool {
@@ -355,7 +365,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx, 'tcx> {
355365
}
356366
}
357367

358-
/// Accumulates an Rvalue or Call's effects in self.qualif.
368+
/// Accumulates an Rvalue or Call's effects in self.state.qualif.
359369
/// For functions (constant or not), it also records
360370
/// candidates for promotion in promotion_candidates.
361371
impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
@@ -370,22 +380,22 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
370380
self.not_const();
371381
}
372382
LocalKind::Var if self.mode == Mode::Fn => {
373-
self.add(Qualif::NOT_CONST);
383+
self.state.add(Qualif::NOT_CONST);
374384
}
375385
LocalKind::Var |
376386
LocalKind::Arg |
377387
LocalKind::Temp => {
378388
if let LocalKind::Arg = kind {
379-
self.add(Qualif::FN_ARGUMENT);
389+
self.state.add(Qualif::FN_ARGUMENT);
380390
}
381391

382392
if !self.temp_promotion_state[local].is_promotable() {
383393
debug!("visit_local: (not promotable) local={:?}", local);
384-
self.add(Qualif::NOT_PROMOTABLE);
394+
self.state.add(Qualif::NOT_PROMOTABLE);
385395
}
386396

387-
if let Some(qualif) = self.local_qualif[local] {
388-
self.add(qualif);
397+
if let Some(qualif) = self.state.local_qualif[local] {
398+
self.state.add(qualif);
389399
} else {
390400
self.not_const();
391401
}
@@ -411,7 +421,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
411421
"thread-local statics cannot be \
412422
accessed at compile-time");
413423
}
414-
self.add(Qualif::NOT_CONST);
424+
self.state.add(Qualif::NOT_CONST);
415425
return;
416426
}
417427

@@ -430,7 +440,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
430440
return;
431441
}
432442
unleash_miri!(self);
433-
self.add(Qualif::NOT_CONST);
443+
self.state.add(Qualif::NOT_CONST);
434444

435445
if self.mode != Mode::Fn {
436446
let mut err = struct_span_err!(self.tcx.sess, self.span, E0013,
@@ -458,7 +468,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
458468
this.not_const()
459469
} else {
460470
// just make sure this doesn't get promoted
461-
this.add(Qualif::NOT_CONST);
471+
this.state.add(Qualif::NOT_CONST);
462472
}
463473
let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
464474
match this.mode {
@@ -508,7 +518,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
508518
}
509519

510520
let ty = place.ty(this.mir, this.tcx).to_ty(this.tcx);
511-
this.qualif.restrict(ty, this.tcx, this.param_env);
521+
this.state.qualif.restrict(ty, this.tcx, this.param_env);
512522
}
513523

514524
ProjectionElem::Downcast(..) => {
@@ -529,7 +539,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
529539
Operand::Move(_) => {
530540
// Mark the consumed locals to indicate later drops are noops.
531541
if let Operand::Move(Place::Local(local)) = *operand {
532-
self.local_qualif[local] = self.local_qualif[local].map(|q|
542+
self.state.local_qualif[local] = self.state.local_qualif[local].map(|q|
533543
q - Qualif::NEEDS_DROP
534544
);
535545
}
@@ -543,12 +553,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
543553
let (bits, _) = self.tcx.at(constant.span).mir_const_qualif(*def_id);
544554

545555
let qualif = Qualif::from_bits(bits).expect("invalid mir_const_qualif");
546-
self.add(qualif);
556+
self.state.add(qualif);
547557

548558
// Just in case the type is more specific than
549559
// the definition, e.g., impl associated const
550560
// with type parameters, take it into account.
551-
self.qualif.restrict(constant.ty, self.tcx, self.param_env);
561+
self.state.qualif.restrict(constant.ty, self.tcx, self.param_env);
552562
}
553563
}
554564
}
@@ -630,7 +640,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
630640

631641
if forbidden_mut {
632642
unleash_miri!(self);
633-
self.add(Qualif::NOT_CONST);
643+
self.state.add(Qualif::NOT_CONST);
634644
if self.mode != Mode::Fn {
635645
let mut err = struct_span_err!(self.tcx.sess, self.span, E0017,
636646
"references in {}s may only refer \
@@ -654,11 +664,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
654664
// Constants cannot be borrowed if they contain interior mutability as
655665
// it means that our "silent insertion of statics" could change
656666
// initializer values (very bad).
657-
if self.qualif.contains(Qualif::MUTABLE_INTERIOR) {
667+
if self.state.qualif.contains(Qualif::MUTABLE_INTERIOR) {
658668
// A reference of a MUTABLE_INTERIOR place is instead
659669
// NOT_CONST (see `if forbidden_mut` below), to avoid
660670
// duplicate errors (from reborrowing, for example).
661-
self.qualif = self.qualif - Qualif::MUTABLE_INTERIOR;
671+
self.state.qualif = self.state.qualif - Qualif::MUTABLE_INTERIOR;
662672
if self.mode != Mode::Fn {
663673
span_err!(self.tcx.sess, self.span, E0492,
664674
"cannot borrow a constant which may contain \
@@ -673,7 +683,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
673683
debug!("visit_rvalue: forbidden_mut={:?}", forbidden_mut);
674684
if forbidden_mut {
675685
unleash_miri!(self);
676-
self.add(Qualif::NOT_CONST);
686+
self.state.add(Qualif::NOT_CONST);
677687
} else {
678688
// We might have a candidate for promotion.
679689
let candidate = Candidate::Ref(location);
@@ -689,7 +699,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
689699
if let Place::Local(local) = *place {
690700
if self.mir.local_kind(local) == LocalKind::Temp {
691701
debug!("visit_rvalue: local={:?}", local);
692-
if let Some(qualif) = self.local_qualif[local] {
702+
if let Some(qualif) = self.state.local_qualif[local] {
693703
// `forbidden_mut` is false, so we can safely ignore
694704
// `MUTABLE_INTERIOR` from the local's qualifications.
695705
// This allows borrowing fields which don't have
@@ -716,7 +726,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
716726
unleash_miri!(self);
717727
if let Mode::Fn = self.mode {
718728
// in normal functions, mark such casts as not promotable
719-
self.add(Qualif::NOT_CONST);
729+
self.state.add(Qualif::NOT_CONST);
720730
} else if !self.tcx.features().const_raw_ptr_to_usize_cast {
721731
// in const fn and constants require the feature gate
722732
// FIXME: make it unsafe inside const fn and constants
@@ -744,7 +754,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
744754
unleash_miri!(self);
745755
if let Mode::Fn = self.mode {
746756
// raw pointer operations are not allowed inside promoteds
747-
self.add(Qualif::NOT_CONST);
757+
self.state.add(Qualif::NOT_CONST);
748758
} else if !self.tcx.features().const_compare_raw_pointers {
749759
// require the feature gate inside constants and const fn
750760
// FIXME: make it unsafe to use these operations
@@ -761,7 +771,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
761771

762772
Rvalue::NullaryOp(NullOp::Box, _) => {
763773
unleash_miri!(self);
764-
self.add(Qualif::NOT_CONST);
774+
self.state.add(Qualif::NOT_CONST);
765775
if self.mode != Mode::Fn {
766776
let mut err = struct_span_err!(self.tcx.sess, self.span, E0010,
767777
"allocations are not allowed in {}s", self.mode);
@@ -781,13 +791,13 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
781791
Rvalue::Aggregate(ref kind, _) => {
782792
if let AggregateKind::Adt(def, ..) = **kind {
783793
if def.has_dtor(self.tcx) {
784-
self.add(Qualif::NEEDS_DROP);
794+
self.state.add(Qualif::NEEDS_DROP);
785795
}
786796

787797
if Some(def.did) == self.tcx.lang_items().unsafe_cell_type() {
788798
let ty = rvalue.ty(self.mir, self.tcx);
789799
self.add_type(ty);
790-
assert!(self.qualif.contains(Qualif::MUTABLE_INTERIOR));
800+
assert!(self.state.qualif.contains(Qualif::MUTABLE_INTERIOR));
791801
}
792802
}
793803
}
@@ -983,7 +993,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
983993
}
984994
let candidate = Candidate::Argument { bb, index: i };
985995
if is_shuffle && i == 2 {
986-
if this.qualif.is_empty() {
996+
if this.state.qualif.is_empty() {
987997
debug!("visit_terminator_kind: candidate={:?}", candidate);
988998
this.promotion_candidates.push(candidate);
989999
} else {
@@ -1010,7 +1020,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
10101020
// which happens even without the user requesting it.
10111021
// We can error out with a hard error if the argument is not
10121022
// constant here.
1013-
if (this.qualif - Qualif::NOT_PROMOTABLE).is_empty() {
1023+
if (this.state.qualif - Qualif::NOT_PROMOTABLE).is_empty() {
10141024
debug!("visit_terminator_kind: candidate={:?}", candidate);
10151025
this.promotion_candidates.push(candidate);
10161026
} else {
@@ -1023,7 +1033,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
10231033

10241034
// non-const fn calls
10251035
if !is_const_fn {
1026-
self.qualif = Qualif::NOT_CONST;
1036+
self.state.qualif = Qualif::NOT_CONST;
10271037
if self.mode != Mode::Fn {
10281038
self.tcx.sess.delay_span_bug(
10291039
self.span,
@@ -1034,16 +1044,16 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
10341044

10351045
if let Some((ref dest, _)) = *destination {
10361046
// Avoid propagating irrelevant callee/argument qualifications.
1037-
if self.qualif.intersects(Qualif::CONST_ERROR) {
1038-
self.qualif = Qualif::NOT_CONST;
1047+
if self.state.qualif.intersects(Qualif::CONST_ERROR) {
1048+
self.state.qualif = Qualif::NOT_CONST;
10391049
} else {
10401050
// Be conservative about the returned value of a const fn.
10411051
let tcx = self.tcx;
10421052
let ty = dest.ty(self.mir, tcx).to_ty(tcx);
10431053
if is_const_fn && !is_promotable_const_fn && self.mode == Mode::Fn {
1044-
self.qualif = Qualif::NOT_PROMOTABLE;
1054+
self.state.qualif = Qualif::NOT_PROMOTABLE;
10451055
} else {
1046-
self.qualif = Qualif::empty();
1056+
self.state.qualif = Qualif::empty();
10471057
}
10481058
self.add_type(ty);
10491059
}
@@ -1058,7 +1068,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx, 'tcx> {
10581068
// HACK(eddyb): emulate a bit of dataflow analysis,
10591069
// conservatively, that drop elaboration will do.
10601070
let needs_drop = if let Place::Local(local) = *place {
1061-
if self.local_qualif[local].map_or(true, |q| q.contains(Qualif::NEEDS_DROP)) {
1071+
let local_needs_drop = self.state.local_qualif[local]
1072+
.map_or(true, |q| q.contains(Qualif::NEEDS_DROP));
1073+
if local_needs_drop {
10621074
Some(self.mir.local_decls[local].source_info.span)
10631075
} else {
10641076
None

0 commit comments

Comments
 (0)