Skip to content

Commit a4e6b77

Browse files
committed
Extend handling of moved_locals in mir building to some unwind paths
1 parent b286722 commit a4e6b77

File tree

4 files changed

+23
-34
lines changed

4 files changed

+23
-34
lines changed

compiler/rustc_mir_build/src/build/expr/as_rvalue.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
738738
this.diverge_from(block);
739739
block = success;
740740
}
741-
this.record_operands_moved(&[Spanned { node: value_operand, span: DUMMY_SP }]);
741+
this.record_operands_moved(&[value_operand]);
742742
}
743743
block.and(Rvalue::Aggregate(Box::new(AggregateKind::Array(elem_ty)), IndexVec::new()))
744744
}

compiler/rustc_mir_build/src/build/expr/into.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -239,27 +239,26 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
239239
}
240240
ExprKind::Call { ty: _, fun, ref args, from_hir_call, fn_span } => {
241241
let fun = unpack!(block = this.as_local_operand(block, fun));
242-
let args: Box<[_]> = args
242+
let spanned_args: Box<[_]> = args
243243
.into_iter()
244244
.copied()
245245
.map(|arg| Spanned {
246246
node: unpack!(block = this.as_local_call_operand(block, arg)),
247247
span: this.thir.exprs[arg].span,
248248
})
249249
.collect();
250+
let args: Vec<_> = spanned_args.iter().map(|arg| arg.node.clone()).collect();
250251

251252
let success = this.cfg.start_new_block();
252253

253-
this.record_operands_moved(&args);
254-
255254
debug!("expr_into_dest: fn_span={:?}", fn_span);
256255

257256
this.cfg.terminate(
258257
block,
259258
source_info,
260259
TerminatorKind::Call {
261260
func: fun,
262-
args,
261+
args: spanned_args,
263262
unwind: UnwindAction::Continue,
264263
destination,
265264
// The presence or absence of a return edge affects control-flow sensitive
@@ -279,6 +278,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
279278
},
280279
);
281280
this.diverge_from(block);
281+
282+
// This is here and not before `diverge_from` to avoid breaking
283+
// the example in #80949.
284+
// FIXME(matthewjasper): Look at this again if Polonius is
285+
// stabilized.
286+
this.record_operands_moved(&args);
282287
success.unit()
283288
}
284289
ExprKind::Use { source } => this.expr_into_dest(destination, block, source),

compiler/rustc_mir_build/src/build/expr/stmt.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
106106

107107
this.in_scope((region_scope, source_info), lint_level, |this| {
108108
let fun = unpack!(block = this.as_local_operand(block, fun));
109-
let args: Box<[_]> = args
109+
let spanned_args: Box<[_]> = args
110110
.into_iter()
111111
.copied()
112112
.map(|arg| Spanned {
113113
node: unpack!(block = this.as_local_call_operand(block, arg)),
114114
span: this.thir.exprs[arg].span,
115115
})
116116
.collect();
117+
let args: Vec<_> = spanned_args.iter().map(|arg| arg.node.clone()).collect();
117118

118119
this.record_operands_moved(&args);
119120

@@ -124,7 +125,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
124125
this.cfg.terminate(
125126
block,
126127
source_info,
127-
TerminatorKind::TailCall { func: fun, args, fn_span },
128+
TerminatorKind::TailCall { func: fun, args: spanned_args, fn_span },
128129
);
129130

130131
this.cfg.start_new_block().unit()

compiler/rustc_mir_build/src/build/scope.rs

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ use rustc_middle::mir::*;
9292
use rustc_middle::thir::{ExprId, LintLevel};
9393
use rustc_middle::{bug, span_bug};
9494
use rustc_session::lint::Level;
95-
use rustc_span::source_map::Spanned;
9695
use rustc_span::{Span, DUMMY_SP};
9796
use tracing::{debug, instrument};
9897

@@ -128,8 +127,6 @@ struct Scope {
128127
/// end of the vector (top of the stack) first.
129128
drops: Vec<DropData>,
130129

131-
moved_locals: Vec<Local>,
132-
133130
/// The drop index that will drop everything in and below this scope on an
134131
/// unwind path.
135132
cached_unwind_block: Option<DropIdx>,
@@ -445,7 +442,6 @@ impl<'tcx> Scopes<'tcx> {
445442
source_scope: vis_scope,
446443
region_scope: region_scope.0,
447444
drops: vec![],
448-
moved_locals: vec![],
449445
cached_unwind_block: None,
450446
cached_coroutine_drop_block: None,
451447
});
@@ -752,13 +748,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
752748
pub(crate) fn break_for_tail_call(
753749
&mut self,
754750
mut block: BasicBlock,
755-
args: &[Spanned<Operand<'tcx>>],
751+
args: &[Operand<'tcx>],
756752
source_info: SourceInfo,
757753
) -> BlockAnd<()> {
758754
let arg_drops: Vec<_> = args
759755
.iter()
760756
.rev()
761-
.filter_map(|arg| match &arg.node {
757+
.filter_map(|arg| match arg {
762758
Operand::Copy(_) => bug!("copy op in tail call args"),
763759
Operand::Move(place) => {
764760
let local =
@@ -1102,14 +1098,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
11021098
span_bug!(span, "region scope {:?} not in scope to drop {:?}", region_scope, local);
11031099
}
11041100

1105-
/// Indicates that the "local operand" stored in `local` is
1101+
/// Indicates that the "local operands" stored in `local` are
11061102
/// *moved* at some point during execution (see `local_scope` for
11071103
/// more information about what a "local operand" is -- in short,
11081104
/// it's an intermediate operand created as part of preparing some
11091105
/// MIR instruction). We use this information to suppress
1110-
/// redundant drops on the non-unwind paths. This results in less
1111-
/// MIR, but also avoids spurious borrow check errors
1112-
/// (c.f. #64391).
1106+
/// redundant drops. This results in less MIR, but also avoids spurious
1107+
/// borrow check errors (c.f. #64391).
11131108
///
11141109
/// Example: when compiling the call to `foo` here:
11151110
///
@@ -1138,27 +1133,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
11381133
/// spurious borrow-check errors -- the problem, ironically, is
11391134
/// not the `DROP(_X)` itself, but the (spurious) unwind pathways
11401135
/// that it creates. See #64391 for an example.
1141-
pub(crate) fn record_operands_moved(&mut self, operands: &[Spanned<Operand<'tcx>>]) {
1136+
pub(crate) fn record_operands_moved(&mut self, operands: &[Operand<'tcx>]) {
11421137
let local_scope = self.local_scope();
11431138
let scope = self.scopes.scopes.last_mut().unwrap();
11441139

11451140
assert_eq!(scope.region_scope, local_scope, "local scope is not the topmost scope!",);
11461141

11471142
// look for moves of a local variable, like `MOVE(_X)`
1148-
let locals_moved = operands.iter().flat_map(|operand| match operand.node {
1143+
let locals_moved = operands.iter().flat_map(|operand| match operand {
11491144
Operand::Copy(_) | Operand::Constant(_) => None,
11501145
Operand::Move(place) => place.as_local(),
11511146
});
11521147

11531148
for local in locals_moved {
1154-
// check if we have a Drop for this operand and -- if so
1155-
// -- add it to the list of moved operands. Note that this
1156-
// local might not have been an operand created for this
1157-
// call, it could come from other places too.
1158-
if scope.drops.iter().any(|drop| drop.local == local && drop.kind == DropKind::Value) {
1159-
scope.moved_locals.push(local);
1160-
}
1149+
// Unschedule drops from the scope.
1150+
scope.drops.retain(|drop| drop.local != local || drop.kind != DropKind::Value);
11611151
}
1152+
scope.invalidate_cache();
11621153
}
11631154

11641155
// Other
@@ -1382,14 +1373,6 @@ fn build_scope_drops<'tcx>(
13821373
debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind);
13831374
unwind_to = unwind_drops.drops[unwind_to].next;
13841375

1385-
// If the operand has been moved, and we are not on an unwind
1386-
// path, then don't generate the drop. (We only take this into
1387-
// account for non-unwind paths so as not to disturb the
1388-
// caching mechanism.)
1389-
if scope.moved_locals.iter().any(|&o| o == local) {
1390-
continue;
1391-
}
1392-
13931376
unwind_drops.add_entry_point(block, unwind_to);
13941377

13951378
let next = cfg.start_new_block();

0 commit comments

Comments
 (0)