summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_dataflow/src/move_paths
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /compiler/rustc_mir_dataflow/src/move_paths
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_mir_dataflow/src/move_paths')
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs230
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/mod.rs56
2 files changed, 118 insertions, 168 deletions
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 7a5b3585d..ccf3dc794 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -1,58 +1,66 @@
use rustc_index::IndexVec;
-use rustc_middle::mir::tcx::RvalueInitializationState;
+use rustc_middle::mir::tcx::{PlaceTy, RvalueInitializationState};
use rustc_middle::mir::*;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
use smallvec::{smallvec, SmallVec};
use std::mem;
use super::abs_domain::Lift;
-use super::IllegalMoveOriginKind::*;
-use super::{Init, InitIndex, InitKind, InitLocation, LookupResult, MoveError};
+use super::{Init, InitIndex, InitKind, InitLocation, LookupResult};
use super::{
LocationMap, MoveData, MoveOut, MoveOutIndex, MovePath, MovePathIndex, MovePathLookup,
};
-struct MoveDataBuilder<'a, 'tcx> {
+struct MoveDataBuilder<'a, 'tcx, F> {
body: &'a Body<'tcx>,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
data: MoveData<'tcx>,
- errors: Vec<(Place<'tcx>, MoveError<'tcx>)>,
+ filter: F,
}
-impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
- fn new(body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
+impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
+ fn new(
+ body: &'a Body<'tcx>,
+ tcx: TyCtxt<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ filter: F,
+ ) -> Self {
let mut move_paths = IndexVec::new();
let mut path_map = IndexVec::new();
let mut init_path_map = IndexVec::new();
+ let locals = body
+ .local_decls
+ .iter_enumerated()
+ .map(|(i, l)| {
+ if l.is_deref_temp() {
+ return None;
+ }
+ if filter(l.ty) {
+ Some(new_move_path(
+ &mut move_paths,
+ &mut path_map,
+ &mut init_path_map,
+ None,
+ Place::from(i),
+ ))
+ } else {
+ None
+ }
+ })
+ .collect();
+
MoveDataBuilder {
body,
tcx,
param_env,
- errors: Vec::new(),
data: MoveData {
moves: IndexVec::new(),
loc_map: LocationMap::new(body),
rev_lookup: MovePathLookup {
- locals: body
- .local_decls
- .iter_enumerated()
- .map(|(i, l)| {
- if l.is_deref_temp() {
- MovePathIndex::MAX
- } else {
- Self::new_move_path(
- &mut move_paths,
- &mut path_map,
- &mut init_path_map,
- None,
- Place::from(i),
- )
- }
- })
- .collect(),
+ locals,
projections: Default::default(),
un_derefer: Default::default(),
},
@@ -62,35 +70,42 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
init_loc_map: LocationMap::new(body),
init_path_map,
},
+ filter,
}
}
+}
- fn new_move_path(
- move_paths: &mut IndexVec<MovePathIndex, MovePath<'tcx>>,
- path_map: &mut IndexVec<MovePathIndex, SmallVec<[MoveOutIndex; 4]>>,
- init_path_map: &mut IndexVec<MovePathIndex, SmallVec<[InitIndex; 4]>>,
- parent: Option<MovePathIndex>,
- place: Place<'tcx>,
- ) -> MovePathIndex {
- let move_path =
- move_paths.push(MovePath { next_sibling: None, first_child: None, parent, place });
+fn new_move_path<'tcx>(
+ move_paths: &mut IndexVec<MovePathIndex, MovePath<'tcx>>,
+ path_map: &mut IndexVec<MovePathIndex, SmallVec<[MoveOutIndex; 4]>>,
+ init_path_map: &mut IndexVec<MovePathIndex, SmallVec<[InitIndex; 4]>>,
+ parent: Option<MovePathIndex>,
+ place: Place<'tcx>,
+) -> MovePathIndex {
+ let move_path =
+ move_paths.push(MovePath { next_sibling: None, first_child: None, parent, place });
+
+ if let Some(parent) = parent {
+ let next_sibling = mem::replace(&mut move_paths[parent].first_child, Some(move_path));
+ move_paths[move_path].next_sibling = next_sibling;
+ }
- if let Some(parent) = parent {
- let next_sibling = mem::replace(&mut move_paths[parent].first_child, Some(move_path));
- move_paths[move_path].next_sibling = next_sibling;
- }
+ let path_map_ent = path_map.push(smallvec![]);
+ assert_eq!(path_map_ent, move_path);
- let path_map_ent = path_map.push(smallvec![]);
- assert_eq!(path_map_ent, move_path);
+ let init_path_map_ent = init_path_map.push(smallvec![]);
+ assert_eq!(init_path_map_ent, move_path);
- let init_path_map_ent = init_path_map.push(smallvec![]);
- assert_eq!(init_path_map_ent, move_path);
+ move_path
+}
- move_path
- }
+enum MovePathResult {
+ Path(MovePathIndex),
+ Union(MovePathIndex),
+ Error,
}
-impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
+impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
/// This creates a MovePath for a given place, returning an `MovePathError`
/// if that place can't be moved from.
///
@@ -98,11 +113,13 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
/// problematic for borrowck.
///
/// Maybe we should have separate "borrowck" and "moveck" modes.
- fn move_path_for(&mut self, place: Place<'tcx>) -> Result<MovePathIndex, MoveError<'tcx>> {
+ fn move_path_for(&mut self, place: Place<'tcx>) -> MovePathResult {
let data = &mut self.builder.data;
debug!("lookup({:?})", place);
- let mut base = data.rev_lookup.find_local(place.local);
+ let Some(mut base) = data.rev_lookup.find_local(place.local) else {
+ return MovePathResult::Error;
+ };
// The move path index of the first union that we find. Once this is
// some we stop creating child move paths, since moves from unions
@@ -118,12 +135,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
match elem {
ProjectionElem::Deref => match place_ty.kind() {
ty::Ref(..) | ty::RawPtr(..) => {
- return Err(MoveError::cannot_move_out_of(
- self.loc,
- BorrowedContent {
- target_place: place_ref.project_deeper(&[elem], tcx),
- },
- ));
+ return MovePathResult::Error;
}
ty::Adt(adt, _) => {
if !adt.is_box() {
@@ -143,8 +155,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
| ty::FnPtr(_)
| ty::Dynamic(_, _, _)
| ty::Closure(_, _)
- | ty::Generator(_, _, _)
- | ty::GeneratorWitness(..)
+ | ty::Coroutine(_, _, _)
+ | ty::CoroutineWitness(..)
| ty::Never
| ty::Tuple(_)
| ty::Alias(_, _)
@@ -159,16 +171,13 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
ProjectionElem::Field(_, _) => match place_ty.kind() {
ty::Adt(adt, _) => {
if adt.has_dtor(tcx) {
- return Err(MoveError::cannot_move_out_of(
- self.loc,
- InteriorOfTypeWithDestructor { container_ty: place_ty },
- ));
+ return MovePathResult::Error;
}
if adt.is_union() {
union_path.get_or_insert(base);
}
}
- ty::Closure(_, _) | ty::Generator(_, _, _) | ty::Tuple(_) => (),
+ ty::Closure(_, _) | ty::Coroutine(_, _, _) | ty::Tuple(_) => (),
ty::Bool
| ty::Char
| ty::Int(_)
@@ -183,7 +192,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::Dynamic(_, _, _)
- | ty::GeneratorWitness(..)
+ | ty::CoroutineWitness(..)
| ty::Never
| ty::Alias(_, _)
| ty::Param(_)
@@ -197,33 +206,15 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
match place_ty.kind() {
ty::Slice(_) => {
- return Err(MoveError::cannot_move_out_of(
- self.loc,
- InteriorOfSliceOrArray {
- ty: place_ty,
- is_index: matches!(elem, ProjectionElem::Index(..)),
- },
- ));
+ return MovePathResult::Error;
}
ty::Array(_, _) => (),
_ => bug!("Unexpected type {:#?}", place_ty.is_array()),
}
}
ProjectionElem::Index(_) => match place_ty.kind() {
- ty::Array(..) => {
- return Err(MoveError::cannot_move_out_of(
- self.loc,
- InteriorOfSliceOrArray { ty: place_ty, is_index: true },
- ));
- }
- ty::Slice(_) => {
- return Err(MoveError::cannot_move_out_of(
- self.loc,
- InteriorOfSliceOrArray {
- ty: place_ty,
- is_index: matches!(elem, ProjectionElem::Index(..)),
- },
- ));
+ ty::Array(..) | ty::Slice(_) => {
+ return MovePathResult::Error;
}
_ => bug!("Unexpected type {place_ty:#?}"),
},
@@ -235,11 +226,15 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
| ProjectionElem::Subtype(_)
| ProjectionElem::Downcast(_, _) => (),
}
+ let elem_ty = PlaceTy::from_ty(place_ty).projection_ty(tcx, elem).ty;
+ if !(self.builder.filter)(elem_ty) {
+ return MovePathResult::Error;
+ }
if union_path.is_none() {
// inlined from add_move_path because of a borrowck conflict with the iterator
base =
*data.rev_lookup.projections.entry((base, elem.lift())).or_insert_with(|| {
- MoveDataBuilder::new_move_path(
+ new_move_path(
&mut data.move_paths,
&mut data.path_map,
&mut data.init_path_map,
@@ -252,9 +247,9 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
if let Some(base) = union_path {
// Move out of union - always move the entire union.
- Err(MoveError::UnionMove { path: base })
+ MovePathResult::Union(base)
} else {
- Ok(base)
+ MovePathResult::Path(base)
}
}
@@ -270,13 +265,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
..
} = self.builder;
*rev_lookup.projections.entry((base, elem.lift())).or_insert_with(move || {
- MoveDataBuilder::new_move_path(
- move_paths,
- path_map,
- init_path_map,
- Some(base),
- mk_place(*tcx),
- )
+ new_move_path(move_paths, path_map, init_path_map, Some(base), mk_place(*tcx))
})
}
@@ -287,11 +276,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
}
}
-pub type MoveDat<'tcx> =
- Result<MoveData<'tcx>, (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>)>;
-
-impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
- fn finalize(self) -> MoveDat<'tcx> {
+impl<'a, 'tcx, F> MoveDataBuilder<'a, 'tcx, F> {
+ fn finalize(self) -> MoveData<'tcx> {
debug!("{}", {
debug!("moves for {:?}:", self.body.span);
for (j, mo) in self.data.moves.iter_enumerated() {
@@ -304,7 +290,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
"done dumping moves"
});
- if self.errors.is_empty() { Ok(self.data) } else { Err((self.data, self.errors)) }
+ self.data
}
}
@@ -312,8 +298,9 @@ pub(super) fn gather_moves<'tcx>(
body: &Body<'tcx>,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
-) -> MoveDat<'tcx> {
- let mut builder = MoveDataBuilder::new(body, tcx, param_env);
+ filter: impl Fn(Ty<'tcx>) -> bool,
+) -> MoveData<'tcx> {
+ let mut builder = MoveDataBuilder::new(body, tcx, param_env, filter);
builder.gather_args();
@@ -330,20 +317,20 @@ pub(super) fn gather_moves<'tcx>(
builder.finalize()
}
-impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
+impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
fn gather_args(&mut self) {
for arg in self.body.args_iter() {
- let path = self.data.rev_lookup.find_local(arg);
+ if let Some(path) = self.data.rev_lookup.find_local(arg) {
+ let init = self.data.inits.push(Init {
+ path,
+ kind: InitKind::Deep,
+ location: InitLocation::Argument(arg),
+ });
- let init = self.data.inits.push(Init {
- path,
- kind: InitKind::Deep,
- location: InitLocation::Argument(arg),
- });
+ debug!("gather_args: adding init {:?} of {:?} for argument {:?}", init, path, arg);
- debug!("gather_args: adding init {:?} of {:?} for argument {:?}", init, path, arg);
-
- self.data.init_path_map[path].push(init);
+ self.data.init_path_map[path].push(init);
+ }
}
}
@@ -358,12 +345,12 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
}
}
-struct Gatherer<'b, 'a, 'tcx> {
- builder: &'b mut MoveDataBuilder<'a, 'tcx>,
+struct Gatherer<'b, 'a, 'tcx, F> {
+ builder: &'b mut MoveDataBuilder<'a, 'tcx, F>,
loc: Location,
}
-impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
+impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
match &stmt.kind {
StatementKind::Assign(box (place, Rvalue::CopyForDeref(reffed))) => {
@@ -454,7 +441,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
| TerminatorKind::Return
| TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate(_)
- | TerminatorKind::GeneratorDrop
+ | TerminatorKind::CoroutineDrop
| TerminatorKind::Unreachable
| TerminatorKind::Drop { .. } => {}
@@ -546,13 +533,12 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
let base_place =
Place { local: place.local, projection: self.builder.tcx.mk_place_elems(base) };
let base_path = match self.move_path_for(base_place) {
- Ok(path) => path,
- Err(MoveError::UnionMove { path }) => {
+ MovePathResult::Path(path) => path,
+ MovePathResult::Union(path) => {
self.record_move(place, path);
return;
}
- Err(error @ MoveError::IllegalMove { .. }) => {
- self.builder.errors.push((base_place, error));
+ MovePathResult::Error => {
return;
}
};
@@ -572,10 +558,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
}
} else {
match self.move_path_for(place) {
- Ok(path) | Err(MoveError::UnionMove { path }) => self.record_move(place, path),
- Err(error @ MoveError::IllegalMove { .. }) => {
- self.builder.errors.push((place, error));
+ MovePathResult::Path(path) | MovePathResult::Union(path) => {
+ self.record_move(place, path)
}
+ MovePathResult::Error => {}
};
}
}
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
index 0c7aa6676..7ab1a9ed0 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
@@ -1,4 +1,3 @@
-use crate::move_paths::builder::MoveDat;
use crate::un_derefer::UnDerefer;
use rustc_data_structures::fx::FxHashMap;
use rustc_index::{IndexSlice, IndexVec};
@@ -291,7 +290,7 @@ impl Init {
/// Tables mapping from a place to its MovePathIndex.
#[derive(Debug)]
pub struct MovePathLookup<'tcx> {
- locals: IndexVec<Local, MovePathIndex>,
+ locals: IndexVec<Local, Option<MovePathIndex>>,
/// projections are made from a base-place and a projection
/// elem. The base-place will have a unique MovePathIndex; we use
@@ -318,7 +317,9 @@ impl<'tcx> MovePathLookup<'tcx> {
// unknown place, but will rather return the nearest available
// parent.
pub fn find(&self, place: PlaceRef<'tcx>) -> LookupResult {
- let mut result = self.find_local(place.local);
+ let Some(mut result) = self.find_local(place.local) else {
+ return LookupResult::Parent(None);
+ };
for (_, elem) in self.un_derefer.iter_projections(place) {
if let Some(&subpath) = self.projections.get(&(result, elem.lift())) {
@@ -332,7 +333,7 @@ impl<'tcx> MovePathLookup<'tcx> {
}
#[inline]
- pub fn find_local(&self, local: Local) -> MovePathIndex {
+ pub fn find_local(&self, local: Local) -> Option<MovePathIndex> {
self.locals[local]
}
@@ -340,46 +341,8 @@ impl<'tcx> MovePathLookup<'tcx> {
/// `MovePathIndex`es.
pub fn iter_locals_enumerated(
&self,
- ) -> impl DoubleEndedIterator<Item = (Local, MovePathIndex)> + ExactSizeIterator + '_ {
- self.locals.iter_enumerated().map(|(l, &idx)| (l, idx))
- }
-}
-
-#[derive(Debug)]
-pub struct IllegalMoveOrigin<'tcx> {
- pub location: Location,
- pub kind: IllegalMoveOriginKind<'tcx>,
-}
-
-#[derive(Debug)]
-pub enum IllegalMoveOriginKind<'tcx> {
- /// Illegal move due to attempt to move from behind a reference.
- BorrowedContent {
- /// The place the reference refers to: if erroneous code was trying to
- /// move from `(*x).f` this will be `*x`.
- target_place: Place<'tcx>,
- },
-
- /// Illegal move due to attempt to move from field of an ADT that
- /// implements `Drop`. Rust maintains invariant that all `Drop`
- /// ADT's remain fully-initialized so that user-defined destructor
- /// can safely read from all of the ADT's fields.
- InteriorOfTypeWithDestructor { container_ty: Ty<'tcx> },
-
- /// Illegal move due to attempt to move out of a slice or array.
- InteriorOfSliceOrArray { ty: Ty<'tcx>, is_index: bool },
-}
-
-#[derive(Debug)]
-pub enum MoveError<'tcx> {
- IllegalMove { cannot_move_out_of: IllegalMoveOrigin<'tcx> },
- UnionMove { path: MovePathIndex },
-}
-
-impl<'tcx> MoveError<'tcx> {
- fn cannot_move_out_of(location: Location, kind: IllegalMoveOriginKind<'tcx>) -> Self {
- let origin = IllegalMoveOrigin { location, kind };
- MoveError::IllegalMove { cannot_move_out_of: origin }
+ ) -> impl DoubleEndedIterator<Item = (Local, MovePathIndex)> + '_ {
+ self.locals.iter_enumerated().filter_map(|(l, &idx)| Some((l, idx?)))
}
}
@@ -388,8 +351,9 @@ impl<'tcx> MoveData<'tcx> {
body: &Body<'tcx>,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
- ) -> MoveDat<'tcx> {
- builder::gather_moves(body, tcx, param_env)
+ filter: impl Fn(Ty<'tcx>) -> bool,
+ ) -> MoveData<'tcx> {
+ builder::gather_moves(body, tcx, param_env, filter)
}
/// For the move path `mpi`, returns the root local variable (if any) that starts the path.