Skip to content

Commit 13fdf4c

Browse files
committed
Add DesugaringKind::Replace
Add DesugaringKind::Replace to emit better diagnostic messages. At the moment it is used for drop and replaces and only the spans that actually contain a `Drop` terminator are marked as such. As there are no explicit drop correspondents in the HIR, marking happens during MIR build.
1 parent 63a692a commit 13fdf4c

File tree

4 files changed

+43
-50
lines changed

4 files changed

+43
-50
lines changed

compiler/rustc_borrowck/src/lib.rs

+20-34
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
3535
use rustc_middle::ty::query::Providers;
3636
use rustc_middle::ty::{self, CapturedPlace, ParamEnv, RegionVid, TyCtxt};
3737
use rustc_session::lint::builtin::UNUSED_MUT;
38-
use rustc_span::{Span, Symbol};
38+
use rustc_span::{DesugaringKind, Span, Symbol};
3939

4040
use either::Either;
4141
use smallvec::SmallVec;
@@ -340,7 +340,6 @@ fn do_mir_borrowck<'tcx>(
340340
next_region_name: RefCell::new(1),
341341
polonius_output: None,
342342
errors,
343-
replaces: Default::default(),
344343
};
345344
promoted_mbcx.report_move_errors(move_errors);
346345
errors = promoted_mbcx.errors;
@@ -372,7 +371,6 @@ fn do_mir_borrowck<'tcx>(
372371
next_region_name: RefCell::new(1),
373372
polonius_output,
374373
errors,
375-
replaces: Default::default(),
376374
};
377375

378376
// Compute and report region errors, if any.
@@ -555,10 +553,6 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
555553
polonius_output: Option<Rc<PoloniusOutput>>,
556554

557555
errors: error::BorrowckErrors<'tcx>,
558-
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>,
562556
}
563557

564558
// Check that:
@@ -583,10 +577,8 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
583577
match &stmt.kind {
584578
StatementKind::Assign(box (lhs, rhs)) => {
585579
self.consume_rvalue(location, (rhs, span), flow_state);
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);
580+
581+
self.mutate_place(location, (*lhs, span), AccessDepth::Shallow(None), flow_state);
590582
}
591583
StatementKind::FakeRead(box (_, place)) => {
592584
// Read for match doesn't access any memory and is used to
@@ -652,28 +644,13 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
652644
TerminatorKind::SwitchInt { discr, targets: _ } => {
653645
self.consume_operand(loc, (discr, span), flow_state);
654646
}
655-
TerminatorKind::Drop { place, target, unwind, is_replace } => {
647+
TerminatorKind::Drop { place, target: _, unwind: _, is_replace: _ } => {
656648
debug!(
657649
"visit_terminator_drop \
658650
loc: {:?} term: {:?} place: {:?} span: {:?}",
659651
loc, term, place, span
660652
);
661653

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 });
673-
}
674-
return;
675-
}
676-
677654
self.access_place(
678655
loc,
679656
(*place, span),
@@ -1112,13 +1089,22 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
11121089
this.report_conflicting_borrow(location, place_span, bk, borrow);
11131090
this.buffer_error(err);
11141091
}
1115-
WriteKind::StorageDeadOrDrop => this
1116-
.report_borrowed_value_does_not_live_long_enough(
1117-
location,
1118-
borrow,
1119-
place_span,
1120-
Some(kind),
1121-
),
1092+
WriteKind::StorageDeadOrDrop => {
1093+
if let Some(DesugaringKind::Replace) = place_span.1.desugaring_kind() {
1094+
// If this is a drop triggered by a reassignment, it's more user friendly
1095+
// to report a problem with the explicit assignment than the implicit drop.
1096+
this.report_illegal_mutation_of_borrowed(
1097+
location, place_span, borrow,
1098+
)
1099+
} else {
1100+
this.report_borrowed_value_does_not_live_long_enough(
1101+
location,
1102+
borrow,
1103+
place_span,
1104+
Some(kind),
1105+
)
1106+
}
1107+
}
11221108
WriteKind::Mutate => {
11231109
this.report_illegal_mutation_of_borrowed(location, place_span, borrow)
11241110
}

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

+18-10
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
33
use rustc_middle::middle::region;
44
use rustc_middle::mir::*;
55
use rustc_middle::thir::*;
6+
use rustc_span::DesugaringKind;
67

78
impl<'a, 'tcx> Builder<'a, 'tcx> {
89
/// Builds a block of MIR statements to evaluate the THIR `expr`.
@@ -28,7 +29,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2829
ExprKind::Assign { lhs, rhs } => {
2930
let lhs = &this.thir[lhs];
3031
let rhs = &this.thir[rhs];
31-
let lhs_span = lhs.span;
3232

3333
// Note: we evaluate assignments right-to-left. This
3434
// is better for borrowck interaction with overloaded
@@ -42,17 +42,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
4242
let needs_drop = lhs.ty.needs_drop(this.tcx, this.param_env);
4343
let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
4444
let lhs = unpack!(block = this.as_place(block, lhs));
45-
if needs_drop {
46-
unpack!(
47-
block = this.build_drop_and_replace(
48-
block,
49-
source_info,
50-
lhs_span,
51-
lhs,
52-
rhs.clone()
45+
46+
let source_info = if needs_drop {
47+
let span = this.tcx.with_stable_hashing_context(|hcx| {
48+
expr_span.mark_with_reason(
49+
None,
50+
DesugaringKind::Replace,
51+
this.tcx.sess.edition(),
52+
hcx,
5353
)
54+
});
55+
let source_info = this.source_info(span);
56+
unpack!(
57+
block = this.build_drop_and_replace(block, source_info, lhs, rhs.clone())
5458
);
55-
}
59+
source_info
60+
} else {
61+
source_info
62+
};
63+
5664
this.cfg.push_assign(block, source_info, lhs, rhs);
5765
this.block_context.pop();
5866
block.unit()

compiler/rustc_mir_build/src/build/scope.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -1125,20 +1125,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
11251125
pub(crate) fn build_drop_and_replace(
11261126
&mut self,
11271127
block: BasicBlock,
1128-
statement_source_info: SourceInfo,
1129-
span: Span,
1128+
source_info: SourceInfo,
11301129
place: Place<'tcx>,
11311130
value: Rvalue<'tcx>,
11321131
) -> BlockAnd<()> {
1133-
let source_info = self.source_info(span);
11341132
let next_target = self.cfg.start_new_block();
11351133

11361134
let assign = self.cfg.start_new_cleanup_block();
1137-
self.cfg.push_assign(assign, statement_source_info, place, value.clone());
1135+
self.cfg.push_assign(assign, source_info, place, value.clone());
11381136
// We still have to build the scope drops so we don't know which block will follow.
11391137
// This terminator will be overwritten once the unwind drop tree builder runs.
1140-
self.cfg.terminate(assign, statement_source_info, TerminatorKind::Unreachable);
1141-
1138+
self.cfg.terminate(assign, source_info, TerminatorKind::Unreachable);
11421139
self.cfg.terminate(
11431140
block,
11441141
source_info,

compiler/rustc_span/src/hygiene.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1151,6 +1151,7 @@ pub enum DesugaringKind {
11511151
Await,
11521152
ForLoop,
11531153
WhileLoop,
1154+
Replace,
11541155
}
11551156

11561157
impl DesugaringKind {
@@ -1166,6 +1167,7 @@ impl DesugaringKind {
11661167
DesugaringKind::OpaqueTy => "`impl Trait`",
11671168
DesugaringKind::ForLoop => "`for` loop",
11681169
DesugaringKind::WhileLoop => "`while` loop",
1170+
DesugaringKind::Replace => "drop and replace",
11691171
}
11701172
}
11711173
}

0 commit comments

Comments
 (0)