Skip to content

Commit d1c9696

Browse files
committed
bring back un_derefer and rewrite it again
1 parent 4fbd6d5 commit d1c9696

File tree

6 files changed

+107
-107
lines changed

6 files changed

+107
-107
lines changed

compiler/rustc_borrowck/src/type_check/liveness/polonius.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ struct UseFactsExtractor<'me, 'tcx> {
2020
}
2121

2222
// A Visitor to walk through the MIR and extract point-wise facts
23-
impl UseFactsExtractor<'_, '_> {
23+
impl<'tcx> UseFactsExtractor<'_, 'tcx> {
2424
fn location_to_index(&self, location: Location) -> LocationIndex {
2525
self.location_table.mid_index(location)
2626
}
@@ -45,7 +45,7 @@ impl UseFactsExtractor<'_, '_> {
4545
self.path_accessed_at_base.push((path, self.location_to_index(location)));
4646
}
4747

48-
fn place_to_mpi(&self, place: &Place<'_>) -> Option<MovePathIndex> {
48+
fn place_to_mpi(&self, place: &Place<'tcx>) -> Option<MovePathIndex> {
4949
match self.move_data.rev_lookup.find(place.as_ref()) {
5050
LookupResult::Exact(mpi) => Some(mpi),
5151
LookupResult::Parent(mmpi) => mmpi,

compiler/rustc_mir_dataflow/src/impls/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -731,11 +731,11 @@ fn switch_on_enum_discriminant<'mir, 'tcx>(
731731

732732
struct OnMutBorrow<F>(F);
733733

734-
impl<F> Visitor<'_> for OnMutBorrow<F>
734+
impl<'tcx, F> Visitor<'tcx> for OnMutBorrow<F>
735735
where
736-
F: FnMut(&mir::Place<'_>),
736+
F: FnMut(&mir::Place<'tcx>),
737737
{
738-
fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'_>, location: Location) {
738+
fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
739739
// FIXME: Does `&raw const foo` allow mutation? See #90413.
740740
match rvalue {
741741
mir::Rvalue::Ref(_, mir::BorrowKind::Mut { .. }, place)
@@ -756,7 +756,7 @@ where
756756
fn for_each_mut_borrow<'tcx>(
757757
mir: &impl MirVisitable<'tcx>,
758758
location: Location,
759-
f: impl FnMut(&mir::Place<'_>),
759+
f: impl FnMut(&mir::Place<'tcx>),
760760
) {
761761
let mut vis = OnMutBorrow(f);
762762

compiler/rustc_mir_dataflow/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub mod impls;
4343
pub mod move_paths;
4444
pub mod rustc_peek;
4545
pub mod storage;
46+
pub mod un_derefer;
4647
pub mod value_analysis;
4748

4849
fluent_messages! { "../messages.ftl" }

compiler/rustc_mir_dataflow/src/move_paths/builder.rs

+54-53
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use rustc_middle::mir::*;
44
use rustc_middle::ty::{self, TyCtxt};
55
use smallvec::{smallvec, SmallVec};
66

7-
use std::iter;
87
use std::mem;
98

109
use super::abs_domain::Lift;
@@ -55,7 +54,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
5554
})
5655
.collect(),
5756
projections: Default::default(),
58-
derefer_sidetable: Default::default(),
57+
un_derefer: Default::default(),
5958
},
6059
move_paths,
6160
path_map,
@@ -100,11 +99,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
10099
///
101100
/// Maybe we should have separate "borrowck" and "moveck" modes.
102101
fn move_path_for(&mut self, place: Place<'tcx>) -> Result<MovePathIndex, MoveError<'tcx>> {
103-
let deref_chain = self.builder.data.rev_lookup.deref_chain(place.as_ref());
102+
let data = &mut self.builder.data;
104103

105104
debug!("lookup({:?})", place);
106-
let mut base =
107-
self.builder.data.rev_lookup.find_local(deref_chain.first().unwrap_or(&place).local);
105+
let mut base = data.rev_lookup.find_local(place.local);
108106

109107
// The move path index of the first union that we find. Once this is
110108
// some we stop creating child move paths, since moves from unions
@@ -113,55 +111,60 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
113111
// from `*(u.f: &_)` isn't allowed.
114112
let mut union_path = None;
115113

116-
for place in deref_chain.into_iter().chain(iter::once(place)) {
117-
for (place_ref, elem) in place.as_ref().iter_projections() {
118-
let body = self.builder.body;
119-
let tcx = self.builder.tcx;
120-
let place_ty = place_ref.ty(body, tcx).ty;
121-
match place_ty.kind() {
122-
ty::Ref(..) | ty::RawPtr(..) => {
123-
return Err(MoveError::cannot_move_out_of(
124-
self.loc,
125-
BorrowedContent {
126-
target_place: place_ref.project_deeper(&[elem], tcx),
127-
},
128-
));
129-
}
130-
ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => {
131-
return Err(MoveError::cannot_move_out_of(
132-
self.loc,
133-
InteriorOfTypeWithDestructor { container_ty: place_ty },
134-
));
135-
}
136-
ty::Adt(adt, _) if adt.is_union() => {
137-
union_path.get_or_insert(base);
138-
}
139-
ty::Slice(_) => {
114+
for (place_ref, elem) in data.rev_lookup.un_derefer.iter_projections(place.as_ref()) {
115+
let body = self.builder.body;
116+
let tcx = self.builder.tcx;
117+
let place_ty = place_ref.ty(body, tcx).ty;
118+
match place_ty.kind() {
119+
ty::Ref(..) | ty::RawPtr(..) => {
120+
return Err(MoveError::cannot_move_out_of(
121+
self.loc,
122+
BorrowedContent { target_place: place_ref.project_deeper(&[elem], tcx) },
123+
));
124+
}
125+
ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => {
126+
return Err(MoveError::cannot_move_out_of(
127+
self.loc,
128+
InteriorOfTypeWithDestructor { container_ty: place_ty },
129+
));
130+
}
131+
ty::Adt(adt, _) if adt.is_union() => {
132+
union_path.get_or_insert(base);
133+
}
134+
ty::Slice(_) => {
135+
return Err(MoveError::cannot_move_out_of(
136+
self.loc,
137+
InteriorOfSliceOrArray {
138+
ty: place_ty,
139+
is_index: matches!(elem, ProjectionElem::Index(..)),
140+
},
141+
));
142+
}
143+
144+
ty::Array(..) => {
145+
if let ProjectionElem::Index(..) = elem {
140146
return Err(MoveError::cannot_move_out_of(
141147
self.loc,
142-
InteriorOfSliceOrArray {
143-
ty: place_ty,
144-
is_index: matches!(elem, ProjectionElem::Index(..)),
145-
},
148+
InteriorOfSliceOrArray { ty: place_ty, is_index: true },
146149
));
147150
}
151+
}
148152

149-
ty::Array(..) => {
150-
if let ProjectionElem::Index(..) = elem {
151-
return Err(MoveError::cannot_move_out_of(
152-
self.loc,
153-
InteriorOfSliceOrArray { ty: place_ty, is_index: true },
154-
));
155-
}
156-
}
157-
158-
_ => {}
159-
};
153+
_ => {}
154+
};
160155

161-
if union_path.is_none() {
162-
base = self
163-
.add_move_path(base, elem, |tcx| place_ref.project_deeper(&[elem], tcx));
164-
}
156+
if union_path.is_none() {
157+
// inlined from add_move_path because of a borrowck conflict with the iterator
158+
base =
159+
*data.rev_lookup.projections.entry((base, elem.lift())).or_insert_with(|| {
160+
MoveDataBuilder::new_move_path(
161+
&mut data.move_paths,
162+
&mut data.path_map,
163+
&mut data.init_path_map,
164+
Some(base),
165+
place_ref.project_deeper(&[elem], tcx),
166+
)
167+
})
165168
}
166169
}
167170

@@ -282,10 +285,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
282285
fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
283286
match &stmt.kind {
284287
StatementKind::Assign(box (place, Rvalue::CopyForDeref(reffed))) => {
285-
assert!(place.projection.is_empty());
286-
if self.builder.body.local_decls[place.local].is_deref_temp() {
287-
self.builder.data.rev_lookup.derefer_sidetable.insert(place.local, *reffed);
288-
}
288+
assert!(self.builder.body.local_decls[place.local].is_deref_temp());
289+
self.builder.data.rev_lookup.un_derefer.insert(place.as_local().unwrap(), *reffed);
289290
}
290291
StatementKind::Assign(box (place, rval)) => {
291292
self.create_move_path(*place);
@@ -306,7 +307,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
306307
StatementKind::StorageLive(_) => {}
307308
StatementKind::StorageDead(local) => {
308309
// DerefTemp locals (results of CopyForDeref) don't actually move anything.
309-
if !self.builder.data.rev_lookup.derefer_sidetable.contains_key(&local) {
310+
if !self.builder.body.local_decls[*local].is_deref_temp() {
310311
self.gather_move(Place::from(*local));
311312
}
312313
}

compiler/rustc_mir_dataflow/src/move_paths/mod.rs

+10-48
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::move_paths::builder::MoveDat;
2+
use crate::un_derefer::UnDerefer;
23
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
34
use rustc_index::{IndexSlice, IndexVec};
45
use rustc_middle::mir::*;
@@ -300,8 +301,7 @@ pub struct MovePathLookup<'tcx> {
300301
/// elem to the associated MovePathIndex.
301302
projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex>,
302303

303-
/// Maps `DerefTemp` locals to the `Place`s assigned to them.
304-
derefer_sidetable: FxHashMap<Local, Place<'tcx>>,
304+
un_derefer: UnDerefer<'tcx>,
305305
}
306306

307307
mod builder;
@@ -317,47 +317,24 @@ impl<'tcx> MovePathLookup<'tcx> {
317317
// alternative will *not* create a MovePath on the fly for an
318318
// unknown place, but will rather return the nearest available
319319
// parent.
320-
pub fn find(&self, place: PlaceRef<'_>) -> LookupResult {
321-
let deref_chain = self.deref_chain(place);
320+
pub fn find(&self, place: PlaceRef<'tcx>) -> LookupResult {
321+
let mut result = self.find_local(place.local);
322322

323-
let local = match deref_chain.first() {
324-
Some(place) => place.local,
325-
None => place.local,
326-
};
327-
328-
let mut result = *self.locals.get(&local).unwrap_or_else(|| {
329-
bug!("base local ({local:?}) of deref_chain should not be a deref temp")
330-
});
331-
332-
// this needs to be a closure because `place` has a different lifetime than `prefix`'s places
333-
let mut subpaths_for_place = |place: PlaceRef<'_>| {
334-
for elem in place.projection.iter() {
335-
if let Some(&subpath) = self.projections.get(&(result, elem.lift())) {
336-
result = subpath;
337-
} else {
338-
return Some(result);
339-
}
340-
}
341-
None
342-
};
343-
344-
for place in deref_chain {
345-
if let Some(result) = subpaths_for_place(place.as_ref()) {
323+
for (_, elem) in self.un_derefer.iter_projections(place) {
324+
if let Some(&subpath) = self.projections.get(&(result, elem.lift())) {
325+
result = subpath;
326+
} else {
346327
return LookupResult::Parent(Some(result));
347328
}
348329
}
349330

350-
if let Some(result) = subpaths_for_place(place) {
351-
return LookupResult::Parent(Some(result));
352-
}
353-
354331
LookupResult::Exact(result)
355332
}
356333

357334
pub fn find_local(&self, local: Local) -> MovePathIndex {
358-
let deref_chain = self.deref_chain(Place::from(local).as_ref());
335+
let deref_chain = self.un_derefer.deref_chain(local);
359336

360-
let local = match deref_chain.last() {
337+
let local = match deref_chain.first() {
361338
Some(place) => place.local,
362339
None => local,
363340
};
@@ -374,21 +351,6 @@ impl<'tcx> MovePathLookup<'tcx> {
374351
) -> impl DoubleEndedIterator<Item = (Local, MovePathIndex)> + ExactSizeIterator + '_ {
375352
self.locals.iter().map(|(&l, &idx)| (l, idx))
376353
}
377-
378-
/// Returns the chain of places behind `DerefTemp` locals in `place`
379-
pub fn deref_chain(&self, place: PlaceRef<'_>) -> Vec<Place<'tcx>> {
380-
let mut prefix = Vec::new();
381-
let mut local = place.local;
382-
383-
while let Some(&reffed) = self.derefer_sidetable.get(&local) {
384-
prefix.insert(0, reffed);
385-
local = reffed.local;
386-
}
387-
388-
debug!("deref_chain({place:?}) = {prefix:?}");
389-
390-
prefix
391-
}
392354
}
393355

394356
#[derive(Debug)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use rustc_data_structures::fx::FxHashMap;
2+
use rustc_middle::mir::*;
3+
4+
use std::iter::once;
5+
6+
/// Used for reverting changes made by `DerefSeparator`
7+
#[derive(Default, Debug)]
8+
pub struct UnDerefer<'tcx> {
9+
deref_chains: FxHashMap<Local, Vec<Place<'tcx>>>,
10+
}
11+
12+
impl<'tcx> UnDerefer<'tcx> {
13+
pub fn insert(&mut self, local: Local, reffed: Place<'tcx>) {
14+
let mut chain = self.deref_chains.remove(&reffed.local).unwrap_or_default();
15+
chain.push(reffed);
16+
self.deref_chains.insert(local, chain);
17+
}
18+
19+
/// Returns the chain of places behind `DerefTemp` locals
20+
pub fn deref_chain(&self, local: Local) -> &[Place<'tcx>] {
21+
self.deref_chains.get(&local).map(Vec::as_slice).unwrap_or_default()
22+
}
23+
24+
pub fn iter_projections(
25+
&self,
26+
place: PlaceRef<'tcx>,
27+
) -> impl Iterator<Item = (PlaceRef<'tcx>, PlaceElem<'tcx>)> + DoubleEndedIterator + '_ {
28+
let deref_chain = self.deref_chain(place.local);
29+
30+
deref_chain
31+
.iter()
32+
.map(Place::as_ref)
33+
.chain(once(place))
34+
.flat_map(|place| place.iter_projections())
35+
}
36+
}

0 commit comments

Comments
 (0)