Skip to content

Commit a89eab9

Browse files
authored
Rollup merge of #83521 - sexxi-goose:quick-diagnostic-fix, r=nikomatsakis
2229: Fix diagnostic issue when using FakeReads in closures This PR fixes a diagnostic issue caused by #82536. A temporary work around was used in this merged PR which involved feature gating the addition of FakeReads introduced as a result of pattern matching in closures. The fix involves adding an optional closure DefId to ForLet and ForMatchedPlace FakeReadCauses. This DefId will only be added if a closure pattern matches a Place starting with an Upvar. r? ```@nikomatsakis```
2 parents 6c13556 + c29dc12 commit a89eab9

File tree

39 files changed

+133
-92
lines changed

39 files changed

+133
-92
lines changed

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1482,7 +1482,7 @@ pub enum StatementKind<'tcx> {
14821482
///
14831483
/// Note that this also is emitted for regular `let` bindings to ensure that locals that are
14841484
/// never accessed still get some sanity checks for, e.g., `let x: ! = ..;`
1485-
FakeRead(FakeReadCause, Box<Place<'tcx>>),
1485+
FakeRead(Box<(FakeReadCause, Place<'tcx>)>),
14861486

14871487
/// Write the discriminant for a variant to the enum Place.
14881488
SetDiscriminant { place: Box<Place<'tcx>>, variant_index: VariantIdx },
@@ -1575,7 +1575,12 @@ pub enum FakeReadCause {
15751575

15761576
/// `let x: !; match x {}` doesn't generate any read of x so we need to
15771577
/// generate a read of x to check that it is initialized and safe.
1578-
ForMatchedPlace,
1578+
///
1579+
/// If a closure pattern matches a Place starting with an Upvar, then we introduce a
1580+
/// FakeRead for that Place outside the closure, in such a case this option would be
1581+
/// Some(closure_def_id).
1582+
/// Otherwise, the value of the optional DefId will be None.
1583+
ForMatchedPlace(Option<DefId>),
15791584

15801585
/// A fake read of the RefWithinGuard version of a bind-by-value variable
15811586
/// in a match guard to ensure that it's value hasn't change by the time
@@ -1594,7 +1599,12 @@ pub enum FakeReadCause {
15941599
/// but in some cases it can affect the borrow checker, as in #53695.
15951600
/// Therefore, we insert a "fake read" here to ensure that we get
15961601
/// appropriate errors.
1597-
ForLet,
1602+
///
1603+
/// If a closure pattern matches a Place starting with an Upvar, then we introduce a
1604+
/// FakeRead for that Place outside the closure, in such a case this option would be
1605+
/// Some(closure_def_id).
1606+
/// Otherwise, the value of the optional DefId will be None.
1607+
ForLet(Option<DefId>),
15981608

15991609
/// If we have an index expression like
16001610
///
@@ -1618,7 +1628,9 @@ impl Debug for Statement<'_> {
16181628
use self::StatementKind::*;
16191629
match self.kind {
16201630
Assign(box (ref place, ref rv)) => write!(fmt, "{:?} = {:?}", place, rv),
1621-
FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place),
1631+
FakeRead(box (ref cause, ref place)) => {
1632+
write!(fmt, "FakeRead({:?}, {:?})", cause, place)
1633+
}
16221634
Retag(ref kind, ref place) => write!(
16231635
fmt,
16241636
"Retag({}{:?})",

compiler/rustc_middle/src/mir/visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ macro_rules! make_mir_visitor {
380380
) => {
381381
self.visit_assign(place, rvalue, location);
382382
}
383-
StatementKind::FakeRead(_, place) => {
383+
StatementKind::FakeRead(box (_, place)) => {
384384
self.visit_place(
385385
place,
386386
PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),

compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1728,7 +1728,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
17281728
impl<'tcx> Visitor<'tcx> for FakeReadCauseFinder<'tcx> {
17291729
fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) {
17301730
match statement {
1731-
Statement { kind: StatementKind::FakeRead(cause, box place), .. }
1731+
Statement { kind: StatementKind::FakeRead(box (cause, place)), .. }
17321732
if *place == self.place =>
17331733
{
17341734
self.cause = Some(*cause);

compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
515515
let block = &self.body.basic_blocks()[location.block];
516516

517517
let kind = if let Some(&Statement {
518-
kind: StatementKind::FakeRead(FakeReadCause::ForLet, _),
518+
kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), _)),
519519
..
520520
}) = block.statements.get(location.statement_index)
521521
{

compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use rustc_hir::def_id::DefId;
77
use rustc_hir::lang_items::LangItemGroup;
88
use rustc_hir::GeneratorKind;
99
use rustc_middle::mir::{
10-
AggregateKind, Constant, Field, Local, LocalInfo, LocalKind, Location, Operand, Place,
11-
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
10+
AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand,
11+
Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
1212
};
1313
use rustc_middle::ty::print::Print;
1414
use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
@@ -795,6 +795,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
795795
}
796796
}
797797

798+
// StatementKind::FakeRead only contains a def_id if they are introduced as a result
799+
// of pattern matching within a closure.
800+
if let StatementKind::FakeRead(box (cause, ref place)) = stmt.kind {
801+
match cause {
802+
FakeReadCause::ForMatchedPlace(Some(closure_def_id))
803+
| FakeReadCause::ForLet(Some(closure_def_id)) => {
804+
debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place);
805+
let places = &[Operand::Move(*place)];
806+
if let Some((args_span, generator_kind, var_span)) =
807+
self.closure_span(closure_def_id, moved_place, places)
808+
{
809+
return ClosureUse { generator_kind, args_span, var_span };
810+
}
811+
}
812+
_ => {}
813+
}
814+
}
815+
798816
let normal_ret =
799817
if moved_place.projection.iter().any(|p| matches!(p, ProjectionElem::Downcast(..))) {
800818
PatUse(stmt.source_info.span)

compiler/rustc_mir/src/borrow_check/invalidation.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
6363

6464
self.mutate_place(location, *lhs, Shallow(None), JustWrite);
6565
}
66-
StatementKind::FakeRead(_, _) => {
66+
StatementKind::FakeRead(box (_, _)) => {
6767
// Only relevant for initialized/liveness/safety checks.
6868
}
6969
StatementKind::SetDiscriminant { place, variant_index: _ } => {

compiler/rustc_mir/src/borrow_check/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc
574574

575575
self.mutate_place(location, (*lhs, span), Shallow(None), JustWrite, flow_state);
576576
}
577-
StatementKind::FakeRead(_, box ref place) => {
577+
StatementKind::FakeRead(box (_, ref place)) => {
578578
// Read for match doesn't access any memory and is used to
579579
// assert that a place is safe and live. So we don't have to
580580
// do any checks here.

compiler/rustc_mir/src/dataflow/move_paths/builder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
293293
}
294294
self.gather_rvalue(rval);
295295
}
296-
StatementKind::FakeRead(_, place) => {
297-
self.create_move_path(**place);
296+
StatementKind::FakeRead(box (_, place)) => {
297+
self.create_move_path(*place);
298298
}
299299
StatementKind::LlvmInlineAsm(ref asm) => {
300300
for (output, kind) in iter::zip(&*asm.outputs, &asm.asm.outputs) {

compiler/rustc_mir/src/transform/coverage/spans.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -683,10 +683,10 @@ pub(super) fn filtered_statement_span(
683683
// and `_1` is the `Place` for `somenum`.
684684
//
685685
// If and when the Issue is resolved, remove this special case match pattern:
686-
StatementKind::FakeRead(cause, _) if cause == FakeReadCause::ForGuardBinding => None,
686+
StatementKind::FakeRead(box (cause, _)) if cause == FakeReadCause::ForGuardBinding => None,
687687

688688
// Retain spans from all other statements
689-
StatementKind::FakeRead(_, _) // Not including `ForGuardBinding`
689+
StatementKind::FakeRead(box (_, _)) // Not including `ForGuardBinding`
690690
| StatementKind::CopyNonOverlapping(..)
691691
| StatementKind::Assign(_)
692692
| StatementKind::SetDiscriminant { .. }

compiler/rustc_mir_build/src/build/cfg.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl<'tcx> CFG<'tcx> {
8080
cause: FakeReadCause,
8181
place: Place<'tcx>,
8282
) {
83-
let kind = StatementKind::FakeRead(cause, box place);
83+
let kind = StatementKind::FakeRead(box (cause, place));
8484
let stmt = Statement { source_info, kind };
8585
self.push(block, stmt);
8686
}

0 commit comments

Comments
 (0)