Skip to content

Commit 12438dd

Browse files
committed
Skip borrowck access check for a drop in a replace op
1 parent 5dd4ed6 commit 12438dd

File tree

2 files changed

+39
-71
lines changed

2 files changed

+39
-71
lines changed

compiler/rustc_borrowck/src/invalidation.rs

Lines changed: 10 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use rustc_middle::ty::TyCtxt;
1010

1111
use crate::{
1212
borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, path_utils::*, AccessDepth,
13-
Activation, ArtificialField, BorrowIndex, Deep, FxHashSet, LocalMutationIsAllowed, Read,
14-
ReadKind, ReadOrWrite, Reservation, Shallow, Write, WriteKind,
13+
Activation, ArtificialField, BorrowIndex, Deep, LocalMutationIsAllowed, Read, ReadKind,
14+
ReadOrWrite, Reservation, Shallow, Write, WriteKind,
1515
};
1616

1717
pub(super) fn generate_invalidates<'tcx>(
@@ -36,7 +36,6 @@ pub(super) fn generate_invalidates<'tcx>(
3636
location_table,
3737
body: &body,
3838
dominators,
39-
to_skip: Default::default(),
4039
};
4140
ig.visit_body(body);
4241
}
@@ -49,7 +48,6 @@ struct InvalidationGenerator<'cx, 'tcx> {
4948
body: &'cx Body<'tcx>,
5049
dominators: Dominators<BasicBlock>,
5150
borrow_set: &'cx BorrowSet<'tcx>,
52-
to_skip: FxHashSet<Location>,
5351
}
5452

5553
/// Visits the whole MIR and generates `invalidates()` facts.
@@ -61,9 +59,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
6159
match &statement.kind {
6260
StatementKind::Assign(box (lhs, rhs)) => {
6361
self.consume_rvalue(location, rhs);
64-
if !self.to_skip.contains(&location) {
65-
self.mutate_place(location, *lhs, Shallow(None));
66-
}
62+
self.mutate_place(location, *lhs, Shallow(None));
6763
}
6864
StatementKind::FakeRead(box (_, _)) => {
6965
// Only relevant for initialized/liveness/safety checks.
@@ -112,36 +108,13 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
112108
TerminatorKind::SwitchInt { discr, targets: _ } => {
113109
self.consume_operand(location, discr);
114110
}
115-
TerminatorKind::Drop { place: drop_place, target, unwind, is_replace } => {
116-
let next_statement = if *is_replace {
117-
self.body
118-
.basic_blocks
119-
.get(*target)
120-
.expect("MIR should be complete at this point")
121-
.statements
122-
.first()
123-
} else {
124-
None
125-
};
126-
127-
match next_statement {
128-
Some(Statement { kind: StatementKind::Assign(_), source_info: _ }) => {
129-
// this is a drop from a replace operation, for better diagnostic report
130-
// here possible conflicts and mute the assign statement errors
131-
self.to_skip.insert(Location { block: *target, statement_index: 0 });
132-
self.to_skip
133-
.insert(Location { block: unwind.unwrap(), statement_index: 0 });
134-
self.mutate_place(location, *drop_place, AccessDepth::Deep);
135-
}
136-
_ => {
137-
self.access_place(
138-
location,
139-
*drop_place,
140-
(AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)),
141-
LocalMutationIsAllowed::Yes,
142-
);
143-
}
144-
}
111+
TerminatorKind::Drop { place: drop_place, target: _, unwind: _, is_replace: _ } => {
112+
self.access_place(
113+
location,
114+
*drop_place,
115+
(AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)),
116+
LocalMutationIsAllowed::Yes,
117+
);
145118
}
146119
TerminatorKind::Call {
147120
func,

compiler/rustc_borrowck/src/lib.rs

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ fn do_mir_borrowck<'tcx>(
340340
next_region_name: RefCell::new(1),
341341
polonius_output: None,
342342
errors,
343-
to_skip: Default::default(),
343+
replaces: Default::default(),
344344
};
345345
promoted_mbcx.report_move_errors(move_errors);
346346
errors = promoted_mbcx.errors;
@@ -372,7 +372,7 @@ fn do_mir_borrowck<'tcx>(
372372
next_region_name: RefCell::new(1),
373373
polonius_output,
374374
errors,
375-
to_skip: Default::default(),
375+
replaces: Default::default(),
376376
};
377377

378378
// Compute and report region errors, if any.
@@ -556,7 +556,9 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
556556

557557
errors: error::BorrowckErrors<'tcx>,
558558

559-
to_skip: FxHashSet<Location>,
559+
/// Record the places were a replace happens so that we can use the
560+
/// correct access depth in the assignment for better diagnostic
561+
replaces: FxHashSet<Location>,
560562
}
561563

562564
// Check that:
@@ -581,9 +583,10 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
581583
match &stmt.kind {
582584
StatementKind::Assign(box (lhs, rhs)) => {
583585
self.consume_rvalue(location, (rhs, span), flow_state);
584-
if !self.to_skip.contains(&location) {
585-
self.mutate_place(location, (*lhs, span), Shallow(None), flow_state);
586-
}
586+
// In case of a replace the drop access check is skipped for better diagnostic but we need
587+
// to use a stricter access depth here
588+
let access_depth = if self.replaces.contains(&location) {AccessDepth::Drop} else {Shallow(None)};
589+
self.mutate_place(location, (*lhs, span), access_depth, flow_state);
587590
}
588591
StatementKind::FakeRead(box (_, place)) => {
589592
// Read for match doesn't access any memory and is used to
@@ -656,36 +659,28 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
656659
loc, term, place, span
657660
);
658661

659-
let next_statement = if *is_replace {
660-
self.body()
661-
.basic_blocks
662-
.get(*target)
663-
.expect("MIR should be complete at this point")
664-
.statements
665-
.first()
666-
} else {
667-
None
668-
};
669-
670-
match next_statement {
671-
Some(Statement { kind: StatementKind::Assign(_), source_info: _ }) => {
672-
// this is a drop from a replace operation, for better diagnostic report
673-
// here possible conflicts and mute the assign statement errors
674-
self.to_skip.insert(Location { block: *target, statement_index: 0 });
675-
self.to_skip
676-
.insert(Location { block: unwind.unwrap(), statement_index: 0 });
677-
self.mutate_place(loc, (*place, span), AccessDepth::Deep, flow_state);
678-
}
679-
_ => {
680-
self.access_place(
681-
loc,
682-
(*place, span),
683-
(AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)),
684-
LocalMutationIsAllowed::Yes,
685-
flow_state,
686-
);
662+
// In case of a replace, it's more user friendly to report a problem with the explicit
663+
// assignment than the implicit drop.
664+
// Simply skip this access and rely on the assignment to report any error.
665+
if *is_replace {
666+
// An assignment `x = ...` is usually a shallow access, but in the case of a replace
667+
// the drop could access internal references depending on the drop implementation.
668+
// Since we're skipping the drop access, we need to mark the access depth
669+
// of the assignment as AccessDepth::Drop.
670+
self.replaces.insert(Location { block: *target, statement_index: 0 });
671+
if let Some(unwind) = unwind {
672+
self.replaces.insert(Location { block: *unwind, statement_index: 0 });
687673
}
674+
return;
688675
}
676+
677+
self.access_place(
678+
loc,
679+
(*place, span),
680+
(AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)),
681+
LocalMutationIsAllowed::Yes,
682+
flow_state,
683+
)
689684
}
690685
TerminatorKind::Call {
691686
func,

0 commit comments

Comments
 (0)