Stop computing error info in move path builder.
This commit is contained in:
parent
90e6d29955
commit
4bedd7de6e
5 changed files with 50 additions and 89 deletions
|
@ -46,7 +46,7 @@ mod mutability_errors;
|
||||||
mod region_errors;
|
mod region_errors;
|
||||||
|
|
||||||
pub(crate) use bound_region_errors::{ToUniverseInfo, UniverseInfo};
|
pub(crate) use bound_region_errors::{ToUniverseInfo, UniverseInfo};
|
||||||
pub(crate) use move_errors::MoveError;
|
pub(crate) use move_errors::{IllegalMoveOriginKind, MoveError};
|
||||||
pub(crate) use mutability_errors::AccessKind;
|
pub(crate) use mutability_errors::AccessKind;
|
||||||
pub(crate) use outlives_suggestion::OutlivesSuggestionBuilder;
|
pub(crate) use outlives_suggestion::OutlivesSuggestionBuilder;
|
||||||
pub(crate) use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
|
pub(crate) use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty::{self, Ty};
|
||||||
use rustc_mir_dataflow::move_paths::{IllegalMoveOriginKind, LookupResult, MovePathIndex};
|
use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
|
||||||
use rustc_span::{BytePos, Span};
|
use rustc_span::{BytePos, Span};
|
||||||
|
|
||||||
use crate::diagnostics::CapturedMessageOpt;
|
use crate::diagnostics::CapturedMessageOpt;
|
||||||
|
@ -9,6 +9,25 @@ use crate::diagnostics::{DescribePlaceOpt, UseSpans};
|
||||||
use crate::prefixes::PrefixSet;
|
use crate::prefixes::PrefixSet;
|
||||||
use crate::MirBorrowckCtxt;
|
use crate::MirBorrowckCtxt;
|
||||||
|
|
||||||
|
#[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)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct MoveError<'tcx> {
|
pub(crate) struct MoveError<'tcx> {
|
||||||
place: Place<'tcx>,
|
place: Place<'tcx>,
|
||||||
|
|
|
@ -49,16 +49,14 @@ use std::rc::Rc;
|
||||||
use rustc_mir_dataflow::impls::{
|
use rustc_mir_dataflow::impls::{
|
||||||
EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
|
EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
|
||||||
};
|
};
|
||||||
use rustc_mir_dataflow::move_paths::{
|
use rustc_mir_dataflow::move_paths::{InitIndex, MoveOutIndex, MovePathIndex};
|
||||||
IllegalMoveOriginKind, InitIndex, MoveOutIndex, MovePathIndex,
|
|
||||||
};
|
|
||||||
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult, MoveData};
|
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult, MoveData};
|
||||||
use rustc_mir_dataflow::Analysis;
|
use rustc_mir_dataflow::Analysis;
|
||||||
use rustc_mir_dataflow::MoveDataParamEnv;
|
use rustc_mir_dataflow::MoveDataParamEnv;
|
||||||
|
|
||||||
use crate::session_diagnostics::VarNeedNotMut;
|
use crate::session_diagnostics::VarNeedNotMut;
|
||||||
|
|
||||||
use self::diagnostics::{AccessKind, MoveError, RegionName};
|
use self::diagnostics::{AccessKind, IllegalMoveOriginKind, MoveError, RegionName};
|
||||||
use self::location::LocationTable;
|
use self::location::LocationTable;
|
||||||
use self::prefixes::PrefixSet;
|
use self::prefixes::PrefixSet;
|
||||||
use consumers::{BodyWithBorrowckFacts, ConsumerOptions};
|
use consumers::{BodyWithBorrowckFacts, ConsumerOptions};
|
||||||
|
|
|
@ -7,8 +7,7 @@ use smallvec::{smallvec, SmallVec};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use super::abs_domain::Lift;
|
use super::abs_domain::Lift;
|
||||||
use super::IllegalMoveOriginKind::*;
|
use super::{Init, InitIndex, InitKind, InitLocation, LookupResult};
|
||||||
use super::{Init, InitIndex, InitKind, InitLocation, LookupResult, MoveError};
|
|
||||||
use super::{
|
use super::{
|
||||||
LocationMap, MoveData, MoveOut, MoveOutIndex, MovePath, MovePathIndex, MovePathLookup,
|
LocationMap, MoveData, MoveOut, MoveOutIndex, MovePath, MovePathIndex, MovePathLookup,
|
||||||
};
|
};
|
||||||
|
@ -88,6 +87,12 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum MovePathResult {
|
||||||
|
Path(MovePathIndex),
|
||||||
|
Union(MovePathIndex),
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
||||||
/// This creates a MovePath for a given place, returning an `MovePathError`
|
/// This creates a MovePath for a given place, returning an `MovePathError`
|
||||||
/// if that place can't be moved from.
|
/// if that place can't be moved from.
|
||||||
|
@ -96,12 +101,12 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
||||||
/// problematic for borrowck.
|
/// problematic for borrowck.
|
||||||
///
|
///
|
||||||
/// Maybe we should have separate "borrowck" and "moveck" modes.
|
/// 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;
|
let data = &mut self.builder.data;
|
||||||
|
|
||||||
debug!("lookup({:?})", place);
|
debug!("lookup({:?})", place);
|
||||||
let Some(mut base) = data.rev_lookup.find_local(place.local) else {
|
let Some(mut base) = data.rev_lookup.find_local(place.local) else {
|
||||||
return Err(MoveError::UntrackedLocal);
|
return MovePathResult::Error;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The move path index of the first union that we find. Once this is
|
// The move path index of the first union that we find. Once this is
|
||||||
|
@ -118,12 +123,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
||||||
match elem {
|
match elem {
|
||||||
ProjectionElem::Deref => match place_ty.kind() {
|
ProjectionElem::Deref => match place_ty.kind() {
|
||||||
ty::Ref(..) | ty::RawPtr(..) => {
|
ty::Ref(..) | ty::RawPtr(..) => {
|
||||||
return Err(MoveError::cannot_move_out_of(
|
return MovePathResult::Error;
|
||||||
self.loc,
|
|
||||||
BorrowedContent {
|
|
||||||
target_place: place_ref.project_deeper(&[elem], tcx),
|
|
||||||
},
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
ty::Adt(adt, _) => {
|
ty::Adt(adt, _) => {
|
||||||
if !adt.is_box() {
|
if !adt.is_box() {
|
||||||
|
@ -159,10 +159,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
||||||
ProjectionElem::Field(_, _) => match place_ty.kind() {
|
ProjectionElem::Field(_, _) => match place_ty.kind() {
|
||||||
ty::Adt(adt, _) => {
|
ty::Adt(adt, _) => {
|
||||||
if adt.has_dtor(tcx) {
|
if adt.has_dtor(tcx) {
|
||||||
return Err(MoveError::cannot_move_out_of(
|
return MovePathResult::Error;
|
||||||
self.loc,
|
|
||||||
InteriorOfTypeWithDestructor { container_ty: place_ty },
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
if adt.is_union() {
|
if adt.is_union() {
|
||||||
union_path.get_or_insert(base);
|
union_path.get_or_insert(base);
|
||||||
|
@ -197,33 +194,15 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
||||||
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
|
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
|
||||||
match place_ty.kind() {
|
match place_ty.kind() {
|
||||||
ty::Slice(_) => {
|
ty::Slice(_) => {
|
||||||
return Err(MoveError::cannot_move_out_of(
|
return MovePathResult::Error;
|
||||||
self.loc,
|
|
||||||
InteriorOfSliceOrArray {
|
|
||||||
ty: place_ty,
|
|
||||||
is_index: matches!(elem, ProjectionElem::Index(..)),
|
|
||||||
},
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
ty::Array(_, _) => (),
|
ty::Array(_, _) => (),
|
||||||
_ => bug!("Unexpected type {:#?}", place_ty.is_array()),
|
_ => bug!("Unexpected type {:#?}", place_ty.is_array()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ProjectionElem::Index(_) => match place_ty.kind() {
|
ProjectionElem::Index(_) => match place_ty.kind() {
|
||||||
ty::Array(..) => {
|
ty::Array(..) | ty::Slice(_) => {
|
||||||
return Err(MoveError::cannot_move_out_of(
|
return MovePathResult::Error;
|
||||||
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(..)),
|
|
||||||
},
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
_ => bug!("Unexpected type {place_ty:#?}"),
|
_ => bug!("Unexpected type {place_ty:#?}"),
|
||||||
},
|
},
|
||||||
|
@ -252,9 +231,9 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
||||||
|
|
||||||
if let Some(base) = union_path {
|
if let Some(base) = union_path {
|
||||||
// Move out of union - always move the entire union.
|
// Move out of union - always move the entire union.
|
||||||
Err(MoveError::UnionMove { path: base })
|
MovePathResult::Union(base)
|
||||||
} else {
|
} else {
|
||||||
Ok(base)
|
MovePathResult::Path(base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,12 +522,14 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
||||||
let base_place =
|
let base_place =
|
||||||
Place { local: place.local, projection: self.builder.tcx.mk_place_elems(base) };
|
Place { local: place.local, projection: self.builder.tcx.mk_place_elems(base) };
|
||||||
let base_path = match self.move_path_for(base_place) {
|
let base_path = match self.move_path_for(base_place) {
|
||||||
Ok(path) => path,
|
MovePathResult::Path(path) => path,
|
||||||
Err(MoveError::UnionMove { path }) => {
|
MovePathResult::Union(path) => {
|
||||||
self.record_move(place, path);
|
self.record_move(place, path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Err(MoveError::IllegalMove { .. } | MoveError::UntrackedLocal) => return,
|
MovePathResult::Error => {
|
||||||
|
return;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty;
|
let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty;
|
||||||
let len: u64 = match base_ty.kind() {
|
let len: u64 = match base_ty.kind() {
|
||||||
|
@ -566,8 +547,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match self.move_path_for(place) {
|
match self.move_path_for(place) {
|
||||||
Ok(path) | Err(MoveError::UnionMove { path }) => self.record_move(place, path),
|
MovePathResult::Path(path) | MovePathResult::Union(path) => {
|
||||||
Err(MoveError::IllegalMove { .. } | MoveError::UntrackedLocal) => {}
|
self.record_move(place, path)
|
||||||
|
}
|
||||||
|
MovePathResult::Error => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::un_derefer::UnDerefer;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_index::{IndexSlice, IndexVec};
|
use rustc_index::{IndexSlice, IndexVec};
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
|
use rustc_middle::ty::{ParamEnv, TyCtxt};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
|
@ -346,45 +346,6 @@ impl<'tcx> MovePathLookup<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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 },
|
|
||||||
UntrackedLocal,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> MoveError<'tcx> {
|
|
||||||
pub fn cannot_move_out_of(location: Location, kind: IllegalMoveOriginKind<'tcx>) -> Self {
|
|
||||||
let origin = IllegalMoveOrigin { location, kind };
|
|
||||||
MoveError::IllegalMove { cannot_move_out_of: origin }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> MoveData<'tcx> {
|
impl<'tcx> MoveData<'tcx> {
|
||||||
pub fn gather_moves(
|
pub fn gather_moves(
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue