Skip to content

Commit 2b6fd1b

Browse files
committed
Extend handling of moved_locals in mir building to some unwind paths
1 parent 27529d5 commit 2b6fd1b

File tree

3 files changed

+18
-30
lines changed

3 files changed

+18
-30
lines changed

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

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

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

+9-4
Original file line numberDiff line numberDiff line change
@@ -235,27 +235,26 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
235235
}
236236
ExprKind::Call { ty: _, fun, ref args, from_hir_call, fn_span } => {
237237
let fun = unpack!(block = this.as_local_operand(block, fun));
238-
let args: Vec<_> = args
238+
let spanned_args: Vec<_> = args
239239
.into_iter()
240240
.copied()
241241
.map(|arg| Spanned {
242242
node: unpack!(block = this.as_local_call_operand(block, arg)),
243243
span: this.thir.exprs[arg].span,
244244
})
245245
.collect();
246+
let args: Vec<_> = spanned_args.iter().map(|arg| arg.node.clone()).collect();
246247

247248
let success = this.cfg.start_new_block();
248249

249-
this.record_operands_moved(&args);
250-
251250
debug!("expr_into_dest: fn_span={:?}", fn_span);
252251

253252
this.cfg.terminate(
254253
block,
255254
source_info,
256255
TerminatorKind::Call {
257256
func: fun,
258-
args,
257+
args: spanned_args,
259258
unwind: UnwindAction::Continue,
260259
destination,
261260
// The presence or absence of a return edge affects control-flow sensitive
@@ -275,6 +274,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
275274
},
276275
);
277276
this.diverge_from(block);
277+
278+
// This is here and not before `diverge_from` to avoid breaking
279+
// the example in #80949.
280+
// FIXME(matthewjasper): Look at this again if Polonius is
281+
// stabilized.
282+
this.record_operands_moved(&args);
278283
success.unit()
279284
}
280285
ExprKind::Use { source } => this.expr_into_dest(destination, block, source),

compiler/rustc_mir_build/src/build/scope.rs

+8-25
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
});
@@ -1017,14 +1013,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
10171013
span_bug!(span, "region scope {:?} not in scope to drop {:?}", region_scope, local);
10181014
}
10191015

1020-
/// Indicates that the "local operand" stored in `local` is
1016+
/// Indicates that the "local operands" stored in `local` are
10211017
/// *moved* at some point during execution (see `local_scope` for
10221018
/// more information about what a "local operand" is -- in short,
10231019
/// it's an intermediate operand created as part of preparing some
10241020
/// MIR instruction). We use this information to suppress
1025-
/// redundant drops on the non-unwind paths. This results in less
1026-
/// MIR, but also avoids spurious borrow check errors
1027-
/// (c.f. #64391).
1021+
/// redundant drops. This results in less MIR, but also avoids spurious
1022+
/// borrow check errors (c.f. #64391).
10281023
///
10291024
/// Example: when compiling the call to `foo` here:
10301025
///
@@ -1053,27 +1048,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
10531048
/// spurious borrow-check errors -- the problem, ironically, is
10541049
/// not the `DROP(_X)` itself, but the (spurious) unwind pathways
10551050
/// that it creates. See #64391 for an example.
1056-
pub(crate) fn record_operands_moved(&mut self, operands: &[Spanned<Operand<'tcx>>]) {
1051+
pub(crate) fn record_operands_moved(&mut self, operands: &[Operand<'tcx>]) {
10571052
let local_scope = self.local_scope();
10581053
let scope = self.scopes.scopes.last_mut().unwrap();
10591054

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

10621057
// look for moves of a local variable, like `MOVE(_X)`
1063-
let locals_moved = operands.iter().flat_map(|operand| match operand.node {
1058+
let locals_moved = operands.iter().flat_map(|operand| match operand {
10641059
Operand::Copy(_) | Operand::Constant(_) => None,
10651060
Operand::Move(place) => place.as_local(),
10661061
});
10671062

10681063
for local in locals_moved {
1069-
// check if we have a Drop for this operand and -- if so
1070-
// -- add it to the list of moved operands. Note that this
1071-
// local might not have been an operand created for this
1072-
// call, it could come from other places too.
1073-
if scope.drops.iter().any(|drop| drop.local == local && drop.kind == DropKind::Value) {
1074-
scope.moved_locals.push(local);
1075-
}
1064+
// Unschedule drops from the scope.
1065+
scope.drops.retain(|drop| drop.local != local || drop.kind != DropKind::Value);
10761066
}
1067+
scope.invalidate_cache();
10771068
}
10781069

10791070
// Other
@@ -1297,14 +1288,6 @@ fn build_scope_drops<'tcx>(
12971288
debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind);
12981289
unwind_to = unwind_drops.drops[unwind_to].next;
12991290

1300-
// If the operand has been moved, and we are not on an unwind
1301-
// path, then don't generate the drop. (We only take this into
1302-
// account for non-unwind paths so as not to disturb the
1303-
// caching mechanism.)
1304-
if scope.moved_locals.iter().any(|&o| o == local) {
1305-
continue;
1306-
}
1307-
13081291
unwind_drops.add_entry_point(block, unwind_to);
13091292

13101293
let next = cfg.start_new_block();

0 commit comments

Comments
 (0)