Skip to content

Commit 1d6332d

Browse files
committed
rustc_mir: avoid having an Option around each local qualification in qualify_consts.
1 parent 2de5b38 commit 1d6332d

File tree

1 file changed

+48
-59
lines changed

1 file changed

+48
-59
lines changed

src/librustc_mir/transform/qualify_consts.rs

Lines changed: 48 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,7 @@ struct Qualifier<'a, 'tcx> {
117117
mode: Mode,
118118
mir: &'a Mir<'tcx>,
119119

120-
local_qualif: &'a IndexVec<Local, Option<Qualif>>,
121-
temp_promotion_state: &'a IndexVec<Local, TempState>,
120+
local_qualif: &'a IndexVec<Local, Qualif>,
122121
}
123122

124123
impl<'a, 'tcx> Qualifier<'a, 'tcx> {
@@ -127,24 +126,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx> {
127126
}
128127

129128
fn qualify_local(&self, local: Local) -> Qualif {
130-
let kind = self.mir.local_kind(local);
131-
match kind {
132-
LocalKind::ReturnPointer => Qualif::NOT_CONST,
133-
LocalKind::Var if self.mode == Mode::Fn => Qualif::NOT_CONST,
134-
135-
LocalKind::Var |
136-
LocalKind::Arg |
137-
LocalKind::Temp => {
138-
let mut qualif = self.local_qualif[local]
139-
.unwrap_or(Qualif::NOT_CONST);
140-
141-
if !self.temp_promotion_state[local].is_promotable() {
142-
qualif = qualif | Qualif::NOT_PROMOTABLE;
143-
}
144-
145-
qualif
146-
}
147-
}
129+
self.local_qualif[local]
148130
}
149131

150132
fn qualify_projection_elem(&self, proj: &PlaceElem<'tcx>) -> Qualif {
@@ -467,7 +449,7 @@ struct Checker<'a, 'tcx> {
467449
mir: &'a Mir<'tcx>,
468450
rpo: ReversePostorder<'a, 'tcx>,
469451

470-
local_qualif: IndexVec<Local, Option<Qualif>>,
452+
local_qualif: IndexVec<Local, Qualif>,
471453
temp_promotion_state: IndexVec<Local, TempState>,
472454
promotion_candidates: Vec<Candidate>,
473455
}
@@ -494,11 +476,22 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
494476

495477
let param_env = tcx.param_env(def_id);
496478

497-
let mut local_qualif = IndexVec::from_elem(None, &mir.local_decls);
498-
for arg in mir.args_iter() {
499-
let qualif = Qualif::any_value_of_ty(mir.local_decls[arg].ty, tcx, param_env);
500-
local_qualif[arg] = Some(Qualif::NOT_PROMOTABLE | qualif);
501-
}
479+
let local_qualif = mir.local_decls.iter_enumerated().map(|(local, decl)| {
480+
match mir.local_kind(local) {
481+
LocalKind::Arg => {
482+
Qualif::any_value_of_ty(decl.ty, tcx, param_env) |
483+
Qualif::NOT_PROMOTABLE
484+
}
485+
486+
LocalKind::Var if mode == Mode::Fn => Qualif::NOT_CONST,
487+
488+
LocalKind::Temp if !temps[local].is_promotable() => {
489+
Qualif::NOT_PROMOTABLE
490+
}
491+
492+
_ => Qualif::empty(),
493+
}
494+
}).collect();
502495

503496
Checker {
504497
mode,
@@ -521,7 +514,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
521514
mode: self.mode,
522515
mir: self.mir,
523516
local_qualif: &self.local_qualif,
524-
temp_promotion_state: &self.temp_promotion_state,
525517
}
526518
}
527519

@@ -559,10 +551,10 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
559551
&& self.temp_promotion_state[index].is_promotable() {
560552
debug!("store to promotable temp {:?} ({:?})", index, qualif);
561553
let slot = &mut self.local_qualif[index];
562-
if slot.is_some() {
554+
if !slot.is_empty() {
563555
span_bug!(self.span, "multiple assignments to {:?}", dest);
564556
}
565-
*slot = Some(qualif);
557+
*slot = qualif;
566558
}
567559
}
568560
return;
@@ -605,7 +597,18 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
605597
// aggregates where we overwrite all fields via assignments, which would not get
606598
// that feature.
607599
let slot = &mut self.local_qualif[index];
608-
*slot = Some(slot.unwrap_or(Qualif::empty()) | qualif);
600+
*slot = *slot | qualif;
601+
602+
// Ensure we keep the `NOT_PROMOTABLE` flag is preserved.
603+
// NOTE(eddyb) this is actually unnecessary right now, as
604+
// we never replace the local's qualif (but we might in
605+
// the future) - also, if `NOT_PROMOTABLE` only matters
606+
// for `Mode::Fn`, then this is also pointless.
607+
if self.mir.local_kind(index) == LocalKind::Temp {
608+
if !self.temp_promotion_state[index].is_promotable() {
609+
*slot = *slot | Qualif::NOT_PROMOTABLE;
610+
}
611+
}
609612
}
610613

611614
/// Check a whole const, static initializer or const fn.
@@ -661,7 +664,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
661664
}
662665
}
663666

664-
let mut qualif = self.local_qualif[RETURN_PLACE].unwrap_or(Qualif::NOT_CONST);
667+
let mut qualif = self.local_qualif[RETURN_PLACE];
665668

666669
// Account for errors in consts by using the
667670
// conservative type qualification instead.
@@ -698,16 +701,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
698701
/// For functions (constant or not), it also records
699702
/// candidates for promotion in `promotion_candidates`.
700703
impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
701-
fn visit_local(&mut self,
702-
&local: &Local,
703-
_: PlaceContext<'tcx>,
704-
_: Location) {
705-
debug!("visit_local: local={:?}", local);
706-
if self.local_qualif[local].is_none() {
707-
self.not_const();
708-
}
709-
}
710-
711704
fn visit_place(&mut self,
712705
place: &Place<'tcx>,
713706
context: PlaceContext<'tcx>,
@@ -833,9 +826,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
833826
Operand::Move(ref place) => {
834827
// Mark the consumed locals to indicate later drops are noops.
835828
if let Place::Local(local) = *place {
836-
self.local_qualif[local] = self.local_qualif[local].map(|q|
837-
q - Qualif::NEEDS_DROP
838-
);
829+
let slot = &mut self.local_qualif[local];
830+
*slot = *slot - Qualif::NEEDS_DROP;
839831
}
840832
}
841833
Operand::Copy(_) |
@@ -1137,9 +1129,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
11371129
// HACK(eddyb): emulate a bit of dataflow analysis,
11381130
// conservatively, that drop elaboration will do.
11391131
let needs_drop = if let Place::Local(local) = *place {
1140-
let local_needs_drop = self.local_qualif[local]
1141-
.map_or(true, |q| q.contains(Qualif::NEEDS_DROP));
1142-
if local_needs_drop {
1132+
if self.local_qualif[local].contains(Qualif::NEEDS_DROP) {
11431133
Some(self.mir.local_decls[local].source_info.span)
11441134
} else {
11451135
None
@@ -1223,18 +1213,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
12231213
if let Place::Local(local) = *place {
12241214
if self.mir.local_kind(local) == LocalKind::Temp {
12251215
debug!("qualify_consts: promotion candidate: local={:?}", local);
1226-
if let Some(qualif) = self.local_qualif[local] {
1227-
// The borrowed place doesn't have `MUTABLE_INTERIOR`
1228-
// (from `qualify_rvalue`), so we can safely ignore
1229-
// `MUTABLE_INTERIOR` from the local's qualifications.
1230-
// This allows borrowing fields which don't have
1231-
// `MUTABLE_INTERIOR`, from a type that does, e.g.:
1232-
// `let _: &'static _ = &(Cell::new(1), 2).1;`
1233-
debug!("qualify_consts: promotion candidate: qualif={:?}", qualif);
1234-
if (qualif - Qualif::MUTABLE_INTERIOR).is_empty() {
1235-
debug!("qualify_consts: promotion candidate: {:?}", candidate);
1236-
self.promotion_candidates.push(candidate);
1237-
}
1216+
let qualif = self.local_qualif[local];
1217+
// The borrowed place doesn't have `MUTABLE_INTERIOR`
1218+
// (from `qualify_rvalue`), so we can safely ignore
1219+
// `MUTABLE_INTERIOR` from the local's qualifications.
1220+
// This allows borrowing fields which don't have
1221+
// `MUTABLE_INTERIOR`, from a type that does, e.g.:
1222+
// `let _: &'static _ = &(Cell::new(1), 2).1;`
1223+
debug!("qualify_consts: promotion candidate: qualif={:?}", qualif);
1224+
if (qualif - Qualif::MUTABLE_INTERIOR).is_empty() {
1225+
debug!("qualify_consts: promotion candidate: {:?}", candidate);
1226+
self.promotion_candidates.push(candidate);
12381227
}
12391228
}
12401229
}

0 commit comments

Comments
 (0)