Skip to content

Commit cd674d6

Browse files
committed
Auto merge of #116300 - cjgillot:split-move, r=petrochenkov
Separate move path tracking between borrowck and drop elaboration. The primary goal of this PR is to skip creating a `MovePathIndex` for path that do not need dropping in drop elaboration. The 2 first commits are cleanups. The next 2 commits displace `move` errors from move-path builder to borrowck. Move-path builder keeps the same logic, but does not carry error information any more. The remaining commits allow to filter `MovePathIndex` creation according to types. This is used in drop elaboration, to avoid computing dataflow for paths that do not need dropping.
2 parents f654229 + c8f33ec commit cd674d6

19 files changed

+558
-536
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -2633,9 +2633,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
26332633
/* Check if the mpi is initialized as an argument */
26342634
let mut is_argument = false;
26352635
for arg in self.body.args_iter() {
2636-
let path = self.move_data.rev_lookup.find_local(arg);
2637-
if mpis.contains(&path) {
2638-
is_argument = true;
2636+
if let Some(path) = self.move_data.rev_lookup.find_local(arg) {
2637+
if mpis.contains(&path) {
2638+
is_argument = true;
2639+
}
26392640
}
26402641
}
26412642

compiler/rustc_borrowck/src/diagnostics/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ mod mutability_errors;
4646
mod region_errors;
4747

4848
pub(crate) use bound_region_errors::{ToUniverseInfo, UniverseInfo};
49+
pub(crate) use move_errors::{IllegalMoveOriginKind, MoveError};
4950
pub(crate) use mutability_errors::AccessKind;
5051
pub(crate) use outlives_suggestion::OutlivesSuggestionBuilder;
5152
pub(crate) use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};

compiler/rustc_borrowck/src/diagnostics/move_errors.rs

+90-66
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,50 @@
11
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
22
use rustc_middle::mir::*;
3-
use rustc_middle::ty;
4-
use rustc_mir_dataflow::move_paths::{
5-
IllegalMoveOrigin, IllegalMoveOriginKind, LookupResult, MoveError, MovePathIndex,
6-
};
3+
use rustc_middle::ty::{self, Ty};
4+
use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
75
use rustc_span::{BytePos, Span};
86

97
use crate::diagnostics::CapturedMessageOpt;
108
use crate::diagnostics::{DescribePlaceOpt, UseSpans};
119
use crate::prefixes::PrefixSet;
1210
use crate::MirBorrowckCtxt;
1311

12+
#[derive(Debug)]
13+
pub enum IllegalMoveOriginKind<'tcx> {
14+
/// Illegal move due to attempt to move from behind a reference.
15+
BorrowedContent {
16+
/// The place the reference refers to: if erroneous code was trying to
17+
/// move from `(*x).f` this will be `*x`.
18+
target_place: Place<'tcx>,
19+
},
20+
21+
/// Illegal move due to attempt to move from field of an ADT that
22+
/// implements `Drop`. Rust maintains invariant that all `Drop`
23+
/// ADT's remain fully-initialized so that user-defined destructor
24+
/// can safely read from all of the ADT's fields.
25+
InteriorOfTypeWithDestructor { container_ty: Ty<'tcx> },
26+
27+
/// Illegal move due to attempt to move out of a slice or array.
28+
InteriorOfSliceOrArray { ty: Ty<'tcx>, is_index: bool },
29+
}
30+
31+
#[derive(Debug)]
32+
pub(crate) struct MoveError<'tcx> {
33+
place: Place<'tcx>,
34+
location: Location,
35+
kind: IllegalMoveOriginKind<'tcx>,
36+
}
37+
38+
impl<'tcx> MoveError<'tcx> {
39+
pub(crate) fn new(
40+
place: Place<'tcx>,
41+
location: Location,
42+
kind: IllegalMoveOriginKind<'tcx>,
43+
) -> Self {
44+
MoveError { place, location, kind }
45+
}
46+
}
47+
1448
// Often when desugaring a pattern match we may have many individual moves in
1549
// MIR that are all part of one operation from the user's point-of-view. For
1650
// example:
@@ -53,87 +87,77 @@ enum GroupedMoveError<'tcx> {
5387
}
5488

5589
impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
56-
pub(crate) fn report_move_errors(&mut self, move_errors: Vec<(Place<'tcx>, MoveError<'tcx>)>) {
57-
let grouped_errors = self.group_move_errors(move_errors);
90+
pub(crate) fn report_move_errors(&mut self) {
91+
let grouped_errors = self.group_move_errors();
5892
for error in grouped_errors {
5993
self.report(error);
6094
}
6195
}
6296

63-
fn group_move_errors(
64-
&self,
65-
errors: Vec<(Place<'tcx>, MoveError<'tcx>)>,
66-
) -> Vec<GroupedMoveError<'tcx>> {
97+
fn group_move_errors(&mut self) -> Vec<GroupedMoveError<'tcx>> {
6798
let mut grouped_errors = Vec::new();
68-
for (original_path, error) in errors {
69-
self.append_to_grouped_errors(&mut grouped_errors, original_path, error);
99+
let errors = std::mem::take(&mut self.move_errors);
100+
for error in errors {
101+
self.append_to_grouped_errors(&mut grouped_errors, error);
70102
}
71103
grouped_errors
72104
}
73105

74106
fn append_to_grouped_errors(
75107
&self,
76108
grouped_errors: &mut Vec<GroupedMoveError<'tcx>>,
77-
original_path: Place<'tcx>,
78109
error: MoveError<'tcx>,
79110
) {
80-
match error {
81-
MoveError::UnionMove { .. } => {
82-
unimplemented!("don't know how to report union move errors yet.")
83-
}
84-
MoveError::IllegalMove { cannot_move_out_of: IllegalMoveOrigin { location, kind } } => {
85-
// Note: that the only time we assign a place isn't a temporary
86-
// to a user variable is when initializing it.
87-
// If that ever stops being the case, then the ever initialized
88-
// flow could be used.
89-
if let Some(StatementKind::Assign(box (
90-
place,
91-
Rvalue::Use(Operand::Move(move_from)),
92-
))) = self.body.basic_blocks[location.block]
93-
.statements
94-
.get(location.statement_index)
95-
.map(|stmt| &stmt.kind)
111+
let MoveError { place: original_path, location, kind } = error;
112+
113+
// Note: that the only time we assign a place isn't a temporary
114+
// to a user variable is when initializing it.
115+
// If that ever stops being the case, then the ever initialized
116+
// flow could be used.
117+
if let Some(StatementKind::Assign(box (place, Rvalue::Use(Operand::Move(move_from))))) =
118+
self.body.basic_blocks[location.block]
119+
.statements
120+
.get(location.statement_index)
121+
.map(|stmt| &stmt.kind)
122+
{
123+
if let Some(local) = place.as_local() {
124+
let local_decl = &self.body.local_decls[local];
125+
// opt_match_place is the
126+
// match_span is the span of the expression being matched on
127+
// match *x.y { ... } match_place is Some(*x.y)
128+
// ^^^^ match_span is the span of *x.y
129+
//
130+
// opt_match_place is None for let [mut] x = ... statements,
131+
// whether or not the right-hand side is a place expression
132+
if let LocalInfo::User(BindingForm::Var(VarBindingForm {
133+
opt_match_place: Some((opt_match_place, match_span)),
134+
binding_mode: _,
135+
opt_ty_info: _,
136+
pat_span: _,
137+
})) = *local_decl.local_info()
96138
{
97-
if let Some(local) = place.as_local() {
98-
let local_decl = &self.body.local_decls[local];
99-
// opt_match_place is the
100-
// match_span is the span of the expression being matched on
101-
// match *x.y { ... } match_place is Some(*x.y)
102-
// ^^^^ match_span is the span of *x.y
103-
//
104-
// opt_match_place is None for let [mut] x = ... statements,
105-
// whether or not the right-hand side is a place expression
106-
if let LocalInfo::User(BindingForm::Var(VarBindingForm {
107-
opt_match_place: Some((opt_match_place, match_span)),
108-
binding_mode: _,
109-
opt_ty_info: _,
110-
pat_span: _,
111-
})) = *local_decl.local_info()
112-
{
113-
let stmt_source_info = self.body.source_info(location);
114-
self.append_binding_error(
115-
grouped_errors,
116-
kind,
117-
original_path,
118-
*move_from,
119-
local,
120-
opt_match_place,
121-
match_span,
122-
stmt_source_info.span,
123-
);
124-
return;
125-
}
126-
}
139+
let stmt_source_info = self.body.source_info(location);
140+
self.append_binding_error(
141+
grouped_errors,
142+
kind,
143+
original_path,
144+
*move_from,
145+
local,
146+
opt_match_place,
147+
match_span,
148+
stmt_source_info.span,
149+
);
150+
return;
127151
}
128-
129-
let move_spans = self.move_spans(original_path.as_ref(), location);
130-
grouped_errors.push(GroupedMoveError::OtherIllegalMove {
131-
use_spans: move_spans,
132-
original_path,
133-
kind,
134-
});
135152
}
136153
}
154+
155+
let move_spans = self.move_spans(original_path.as_ref(), location);
156+
grouped_errors.push(GroupedMoveError::OtherIllegalMove {
157+
use_spans: move_spans,
158+
original_path,
159+
kind,
160+
});
137161
}
138162

139163
fn append_binding_error(

0 commit comments

Comments
 (0)