Skip to content

Commit 274c85f

Browse files
Don't cache result of in_any_value_of_ty for locals
This was needed by an early version of dataflow-based const qualification where `QualifCursor` needed to return a full `BitSet` with the current state.
1 parent a75c792 commit 274c85f

File tree

1 file changed

+51
-53
lines changed

1 file changed

+51
-53
lines changed

src/librustc_mir/transform/check_consts/validation.rs

Lines changed: 51 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
use rustc_errors::struct_span_err;
44
use rustc_hir::lang_items;
55
use rustc_hir::{def_id::DefId, HirId};
6-
use rustc_index::bit_set::BitSet;
76
use rustc_infer::infer::TyCtxtInferExt;
87
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
98
use rustc_middle::mir::*;
@@ -31,67 +30,59 @@ use crate::dataflow::{self, Analysis};
3130
type IndirectlyMutableResults<'mir, 'tcx> =
3231
dataflow::ResultsCursor<'mir, 'tcx, MaybeMutBorrowedLocals<'mir, 'tcx>>;
3332

34-
struct QualifCursor<'a, 'mir, 'tcx, Q: Qualif> {
35-
cursor: dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'a, 'mir, 'tcx, Q>>,
36-
in_any_value_of_ty: BitSet<Local>,
37-
}
38-
39-
impl<Q: Qualif> QualifCursor<'a, 'mir, 'tcx, Q> {
40-
pub fn new(q: Q, ccx: &'a ConstCx<'mir, 'tcx>) -> Self {
41-
let cursor = FlowSensitiveAnalysis::new(q, ccx)
42-
.into_engine(ccx.tcx, ccx.body, ccx.def_id)
43-
.iterate_to_fixpoint()
44-
.into_results_cursor(ccx.body);
45-
46-
let mut in_any_value_of_ty = BitSet::new_empty(ccx.body.local_decls.len());
47-
for (local, decl) in ccx.body.local_decls.iter_enumerated() {
48-
if Q::in_any_value_of_ty(ccx, decl.ty) {
49-
in_any_value_of_ty.insert(local);
50-
}
51-
}
52-
53-
QualifCursor { cursor, in_any_value_of_ty }
54-
}
55-
}
33+
type QualifResults<'mir, 'tcx, Q> =
34+
dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
5635

57-
pub struct Qualifs<'a, 'mir, 'tcx> {
58-
has_mut_interior: QualifCursor<'a, 'mir, 'tcx, HasMutInterior>,
59-
needs_drop: QualifCursor<'a, 'mir, 'tcx, NeedsDrop>,
36+
pub struct Qualifs<'mir, 'tcx> {
37+
has_mut_interior: QualifResults<'mir, 'tcx, HasMutInterior>,
38+
needs_drop: QualifResults<'mir, 'tcx, NeedsDrop>,
6039
indirectly_mutable: IndirectlyMutableResults<'mir, 'tcx>,
6140
}
6241

63-
impl Qualifs<'a, 'mir, 'tcx> {
64-
fn indirectly_mutable(&mut self, local: Local, location: Location) -> bool {
42+
impl Qualifs<'mir, 'tcx> {
43+
fn indirectly_mutable(
44+
&mut self,
45+
_: &Item<'mir, 'tcx>,
46+
local: Local,
47+
location: Location,
48+
) -> bool {
6549
self.indirectly_mutable.seek_before(location);
6650
self.indirectly_mutable.get().contains(local)
6751
}
6852

6953
/// Returns `true` if `local` is `NeedsDrop` at the given `Location`.
7054
///
7155
/// Only updates the cursor if absolutely necessary
72-
fn needs_drop(&mut self, local: Local, location: Location) -> bool {
73-
if !self.needs_drop.in_any_value_of_ty.contains(local) {
56+
fn needs_drop(&mut self, item: &Item<'mir, 'tcx>, local: Local, location: Location) -> bool {
57+
let ty = item.body.local_decls[local].ty;
58+
if !NeedsDrop::in_any_value_of_ty(item, ty) {
7459
return false;
7560
}
7661

77-
self.needs_drop.cursor.seek_before(location);
78-
self.needs_drop.cursor.get().contains(local) || self.indirectly_mutable(local, location)
62+
self.needs_drop.seek_before(location);
63+
self.needs_drop.get().contains(local) || self.indirectly_mutable(item, local, location)
7964
}
8065

8166
/// Returns `true` if `local` is `HasMutInterior` at the given `Location`.
8267
///
8368
/// Only updates the cursor if absolutely necessary.
84-
fn has_mut_interior(&mut self, local: Local, location: Location) -> bool {
85-
if !self.has_mut_interior.in_any_value_of_ty.contains(local) {
69+
fn has_mut_interior(
70+
&mut self,
71+
item: &Item<'mir, 'tcx>,
72+
local: Local,
73+
location: Location,
74+
) -> bool {
75+
let ty = ccx.body.local_decls[local].ty;
76+
if !HasMutInterior::in_any_value_of_ty(ccx, ty) {
8677
return false;
8778
}
8879

89-
self.has_mut_interior.cursor.seek_before(location);
90-
self.has_mut_interior.cursor.get().contains(local)
91-
|| self.indirectly_mutable(local, location)
80+
self.has_mut_interior.seek_before(location);
81+
self.has_mut_interior.get().contains(local)
82+
|| self.indirectly_mutable(item, local, location)
9283
}
9384

94-
fn in_return_place(&mut self, ccx: &ConstCx<'_, 'tcx>) -> ConstQualifs {
85+
fn in_return_place(&mut self, item: &Item<'mir, 'tcx>) -> ConstQualifs {
9586
// Find the `Return` terminator if one exists.
9687
//
9788
// If no `Return` terminator exists, this MIR is divergent. Just return the conservative
@@ -114,34 +105,31 @@ impl Qualifs<'a, 'mir, 'tcx> {
114105
let return_loc = ccx.body.terminator_loc(return_block);
115106

116107
ConstQualifs {
117-
needs_drop: self.needs_drop(RETURN_PLACE, return_loc),
118-
has_mut_interior: self.has_mut_interior(RETURN_PLACE, return_loc),
108+
needs_drop: self.needs_drop(ccx, RETURN_PLACE, return_loc),
109+
has_mut_interior: self.has_mut_interior(ccx, RETURN_PLACE, return_loc),
119110
}
120111
}
121112
}
122113

123-
pub struct Validator<'a, 'mir, 'tcx> {
124-
ccx: &'a ConstCx<'mir, 'tcx>,
125-
qualifs: Qualifs<'a, 'mir, 'tcx>,
114+
pub struct Validator<'mir, 'tcx> {
115+
ccx: &'mir ConstCx<'mir, 'tcx>,
116+
qualifs: Qualifs<'mir, 'tcx>,
126117

127118
/// The span of the current statement.
128119
span: Span,
129120
}
130121

131-
impl Deref for Validator<'_, 'mir, 'tcx> {
122+
impl Deref for Validator<'mir, 'tcx> {
132123
type Target = ConstCx<'mir, 'tcx>;
133124

134125
fn deref(&self) -> &Self::Target {
135126
&self.ccx
136127
}
137128
}
138129

139-
impl Validator<'a, 'mir, 'tcx> {
140-
pub fn new(ccx: &'a ConstCx<'mir, 'tcx>) -> Self {
141-
let ConstCx { tcx, body, def_id, param_env, .. } = *ccx;
142-
143-
let needs_drop = QualifCursor::new(NeedsDrop, ccx);
144-
let has_mut_interior = QualifCursor::new(HasMutInterior, ccx);
130+
impl Validator<'mir, 'tcx> {
131+
pub fn new(item: &'mir Item<'mir, 'tcx>) -> Self {
132+
let Item { tcx, body, def_id, param_env, .. } = *item;
145133

146134
// We can use `unsound_ignore_borrow_on_drop` here because custom drop impls are not
147135
// allowed in a const.
@@ -154,6 +142,16 @@ impl Validator<'a, 'mir, 'tcx> {
154142
.iterate_to_fixpoint()
155143
.into_results_cursor(body);
156144

145+
let needs_drop = FlowSensitiveAnalysis::new(NeedsDrop, item)
146+
.into_engine(item.tcx, &item.body, item.def_id)
147+
.iterate_to_fixpoint()
148+
.into_results_cursor(*item.body);
149+
150+
let has_mut_interior = FlowSensitiveAnalysis::new(HasMutInterior, item)
151+
.into_engine(item.tcx, &item.body, item.def_id)
152+
.iterate_to_fixpoint()
153+
.into_results_cursor(*item.body);
154+
157155
let qualifs = Qualifs { needs_drop, has_mut_interior, indirectly_mutable };
158156

159157
Validator { span: ccx.body.span, ccx, qualifs }
@@ -239,7 +237,7 @@ impl Validator<'a, 'mir, 'tcx> {
239237
}
240238
}
241239

242-
impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
240+
impl Visitor<'tcx> for Validator<'mir, 'tcx> {
243241
fn visit_basic_block_data(&mut self, bb: BasicBlock, block: &BasicBlockData<'tcx>) {
244242
trace!("visit_basic_block_data: bb={:?} is_cleanup={:?}", bb, block.is_cleanup);
245243

@@ -345,7 +343,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
345343
| Rvalue::AddressOf(Mutability::Not, ref place) => {
346344
let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>(
347345
&self.ccx,
348-
&mut |local| self.qualifs.has_mut_interior(local, location),
346+
&mut |local| self.qualifs.has_mut_interior(self.ccx, local, location),
349347
place.as_ref(),
350348
);
351349

@@ -571,7 +569,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
571569
let needs_drop = if let Some(local) = dropped_place.as_local() {
572570
// Use the span where the local was declared as the span of the drop error.
573571
err_span = self.body.local_decls[local].source_info.span;
574-
self.qualifs.needs_drop(local, location)
572+
self.qualifs.needs_drop(self.ccx, local, location)
575573
} else {
576574
true
577575
};

0 commit comments

Comments
 (0)