From 2fb1fb7634b79d93d48749ee1f84d4ba552b186f Mon Sep 17 00:00:00 2001
From: Roxane <roxane.fruytier@hotmail.com>
Date: Thu, 25 Mar 2021 23:03:12 -0400
Subject: [PATCH] Fix diagnostic issue when using FakeReads in closures

---
 compiler/rustc_middle/src/mir/mod.rs          | 16 ++++++++--
 .../diagnostics/explain_borrow.rs             |  2 +-
 .../src/borrow_check/diagnostics/mod.rs       | 22 ++++++++++++--
 .../src/build/expr/as_rvalue.rs               | 30 ++++++++-----------
 .../rustc_mir_build/src/build/matches/mod.rs  |  6 ++--
 compiler/rustc_typeck/src/expr_use_visitor.rs | 21 +++++++++++--
 ..._of_reborrow.SimplifyCfg-initial.after.mir | 28 ++++++++---------
 ...row_and_cast.SimplifyCfg-initial.after.mir |  6 ++--
 ...ignment.main.SimplifyCfg-initial.after.mir |  4 +--
 ....match_tuple.SimplifyCfg-initial.after.mir |  2 +-
 ...e_38669.main.SimplifyCfg-initial.after.mir |  2 +-
 .../mir-opt/issue_49232.main.mir_map.0.mir    |  4 +--
 .../issue_72181.main.mir_map.0.32bit.mir      |  2 +-
 .../issue_72181.main.mir_map.0.64bit.mir      |  2 +-
 .../mir-opt/issue_72181_1.f.mir_map.0.mir     |  2 +-
 .../mir-opt/issue_72181_1.main.mir_map.0.mir  |  2 +-
 ....main.SimplifyCfg-promote-consts.after.mir |  2 +-
 ...fg-initial.after-ElaborateDrops.after.diff |  2 +-
 ...s.full_tested_match.PromoteTemps.after.mir |  2 +-
 ...full_tested_match2.PromoteTemps.before.mir |  2 +-
 ...h_false_edges.main.PromoteTemps.before.mir |  2 +-
 ...ch_test.main.SimplifyCfg-initial.after.mir |  6 ++--
 ...egion_subtyping_basic.main.nll.0.32bit.mir |  6 ++--
 ...egion_subtyping_basic.main.nll.0.64bit.mir |  6 ++--
 ...receiver_ptr_mutability.main.mir_map.0.mir |  4 +--
 ...tch_guard.CleanupNonCodegenStatements.diff |  2 +-
 ...imple_match.match_bool.mir_map.0.32bit.mir |  2 +-
 ...imple_match.match_bool.mir_map.0.64bit.mir |  2 +-
 .../mir-opt/storage_ranges.main.nll.0.mir     |  6 ++--
 ...ove_out.move_out_by_subslice.mir_map.0.mir |  2 +-
 ...y_move_out.move_out_from_end.mir_map.0.mir |  2 +-
 31 files changed, 119 insertions(+), 80 deletions(-)

diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index b2cf1aab112..1f7e12db47a 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1452,7 +1452,7 @@ pub struct Statement<'tcx> {
 
 // `Statement` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(Statement<'_>, 32);
+static_assert_size!(Statement<'_>, 40);
 
 impl Statement<'_> {
     /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
@@ -1575,7 +1575,12 @@ pub enum FakeReadCause {
 
     /// `let x: !; match x {}` doesn't generate any read of x so we need to
     /// generate a read of x to check that it is initialized and safe.
-    ForMatchedPlace,
+    ///
+    /// If a closure pattern matches a Place starting with an Upvar, then we introduce a
+    /// FakeRead for that Place outside the closure, in such a case this option would be
+    /// Some(closure_def_id).
+    /// Otherwise, the value of the optional DefId will be None.
+    ForMatchedPlace(Option<DefId>),
 
     /// A fake read of the RefWithinGuard version of a bind-by-value variable
     /// in a match guard to ensure that it's value hasn't change by the time
@@ -1594,7 +1599,12 @@ pub enum FakeReadCause {
     /// but in some cases it can affect the borrow checker, as in #53695.
     /// Therefore, we insert a "fake read" here to ensure that we get
     /// appropriate errors.
-    ForLet,
+    ///
+    /// If a closure pattern matches a Place starting with an Upvar, then we introduce a
+    /// FakeRead for that Place outside the closure, in such a case this option would be
+    /// Some(closure_def_id).
+    /// Otherwise, the value of the optional DefId will be None.
+    ForLet(Option<DefId>),
 
     /// If we have an index expression like
     ///
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
index 06e3f4b91f6..4ab0fe08259 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
@@ -515,7 +515,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 let block = &self.body.basic_blocks()[location.block];
 
                 let kind = if let Some(&Statement {
-                    kind: StatementKind::FakeRead(FakeReadCause::ForLet, _),
+                    kind: StatementKind::FakeRead(FakeReadCause::ForLet(_), _),
                     ..
                 }) = block.statements.get(location.statement_index)
                 {
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
index 6ea0ba0a8e1..6a457487348 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
@@ -7,8 +7,8 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItemGroup;
 use rustc_hir::GeneratorKind;
 use rustc_middle::mir::{
-    AggregateKind, Constant, Field, Local, LocalInfo, LocalKind, Location, Operand, Place,
-    PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
+    AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand,
+    Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
 };
 use rustc_middle::ty::print::Print;
 use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
@@ -795,6 +795,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
         }
 
+        // StatementKind::FakeRead only contains a def_id if they are introduced as a result
+        // of pattern matching within a closure.
+        if let StatementKind::FakeRead(cause, box ref place) = stmt.kind {
+            match cause {
+                FakeReadCause::ForMatchedPlace(Some(closure_def_id))
+                | FakeReadCause::ForLet(Some(closure_def_id)) => {
+                    debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place);
+                    let places = &[Operand::Move(*place)];
+                    if let Some((args_span, generator_kind, var_span)) =
+                        self.closure_span(closure_def_id, moved_place, places)
+                    {
+                        return ClosureUse { generator_kind, args_span, var_span };
+                    }
+                }
+                _ => {}
+            }
+        }
+
         let normal_ret =
             if moved_place.projection.iter().any(|p| matches!(p, ProjectionElem::Downcast(..))) {
                 PatUse(stmt.source_info.span)
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 7f24a41b00b..822fbd91c94 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -179,24 +179,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 //     match x { _ => () } // fake read of `x`
                 // };
                 // ```
-                // FIXME(RFC2229): Remove feature gate once diagnostics are improved
-                if this.tcx.features().capture_disjoint_fields {
-                    for (thir_place, cause, hir_id) in fake_reads.into_iter() {
-                        let place_builder =
-                            unpack!(block = this.as_place_builder(block, thir_place));
+                for (thir_place, cause, hir_id) in fake_reads.into_iter() {
+                    let place_builder = unpack!(block = this.as_place_builder(block, thir_place));
 
-                        if let Ok(place_builder_resolved) =
-                            place_builder.try_upvars_resolved(this.tcx, this.typeck_results)
-                        {
-                            let mir_place =
-                                place_builder_resolved.into_place(this.tcx, this.typeck_results);
-                            this.cfg.push_fake_read(
-                                block,
-                                this.source_info(this.tcx.hir().span(*hir_id)),
-                                *cause,
-                                mir_place,
-                            );
-                        }
+                    if let Ok(place_builder_resolved) =
+                        place_builder.try_upvars_resolved(this.tcx, this.typeck_results)
+                    {
+                        let mir_place =
+                            place_builder_resolved.into_place(this.tcx, this.typeck_results);
+                        this.cfg.push_fake_read(
+                            block,
+                            this.source_info(this.tcx.hir().span(*hir_id)),
+                            *cause,
+                            mir_place,
+                        );
                     }
                 }
 
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 73fd3f0feb5..0e422dc3c63 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -139,7 +139,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // uninhabited value. If we get never patterns, those will check that
         // the place is initialized, and so this read would only be used to
         // check safety.
-        let cause_matched_place = FakeReadCause::ForMatchedPlace;
+        let cause_matched_place = FakeReadCause::ForMatchedPlace(None);
         let source_info = self.source_info(scrutinee_span);
 
         if let Ok(scrutinee_builder) =
@@ -400,7 +400,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                 // Inject a fake read, see comments on `FakeReadCause::ForLet`.
                 let source_info = self.source_info(irrefutable_pat.span);
-                self.cfg.push_fake_read(block, source_info, FakeReadCause::ForLet, place);
+                self.cfg.push_fake_read(block, source_info, FakeReadCause::ForLet(None), place);
 
                 self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard);
                 block.unit()
@@ -435,7 +435,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                 // Inject a fake read, see comments on `FakeReadCause::ForLet`.
                 let pattern_source_info = self.source_info(irrefutable_pat.span);
-                let cause_let = FakeReadCause::ForLet;
+                let cause_let = FakeReadCause::ForLet(None);
                 self.cfg.push_fake_read(block, pattern_source_info, cause_let, place);
 
                 let ty_source_info = self.source_info(user_ty_span);
diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs
index ab286bacd81..02510cb6a44 100644
--- a/compiler/rustc_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_typeck/src/expr_use_visitor.rs
@@ -280,9 +280,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                 if needs_to_be_read {
                     self.borrow_expr(&discr, ty::ImmBorrow);
                 } else {
+                    let closure_def_id = match discr_place.place.base {
+                        PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id.to_def_id()),
+                        _ => None,
+                    };
+
                     self.delegate.fake_read(
                         discr_place.place.clone(),
-                        FakeReadCause::ForMatchedPlace,
+                        FakeReadCause::ForMatchedPlace(closure_def_id),
                         discr_place.hir_id,
                     );
 
@@ -578,9 +583,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
     }
 
     fn walk_arm(&mut self, discr_place: &PlaceWithHirId<'tcx>, arm: &hir::Arm<'_>) {
+        let closure_def_id = match discr_place.place.base {
+            PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id.to_def_id()),
+            _ => None,
+        };
+
         self.delegate.fake_read(
             discr_place.place.clone(),
-            FakeReadCause::ForMatchedPlace,
+            FakeReadCause::ForMatchedPlace(closure_def_id),
             discr_place.hir_id,
         );
         self.walk_pat(discr_place, &arm.pat);
@@ -595,9 +605,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
     /// Walks a pat that occurs in isolation (i.e., top-level of fn argument or
     /// let binding, and *not* a match arm or nested pat.)
     fn walk_irrefutable_pat(&mut self, discr_place: &PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>) {
+        let closure_def_id = match discr_place.place.base {
+            PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id.to_def_id()),
+            _ => None,
+        };
+
         self.delegate.fake_read(
             discr_place.place.clone(),
-            FakeReadCause::ForLet,
+            FakeReadCause::ForLet(closure_def_id),
             discr_place.hir_id,
         );
         self.walk_pat(discr_place, pat);
diff --git a/src/test/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir b/src/test/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir
index a9568112620..9fa478f8a82 100644
--- a/src/test/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir
@@ -130,12 +130,12 @@ fn address_of_reborrow() -> () {
         StorageLive(_2);                 // scope 0 at $DIR/address-of.rs:4:14: 4:21
         _2 = [const 0_i32; 10];          // scope 0 at $DIR/address-of.rs:4:14: 4:21
         _1 = &_2;                        // scope 0 at $DIR/address-of.rs:4:13: 4:21
-        FakeRead(ForLet, _1);            // scope 0 at $DIR/address-of.rs:4:9: 4:10
+        FakeRead(ForLet(None), _1);      // scope 0 at $DIR/address-of.rs:4:9: 4:10
         StorageLive(_3);                 // scope 1 at $DIR/address-of.rs:5:9: 5:14
         StorageLive(_4);                 // scope 1 at $DIR/address-of.rs:5:22: 5:29
         _4 = [const 0_i32; 10];          // scope 1 at $DIR/address-of.rs:5:22: 5:29
         _3 = &mut _4;                    // scope 1 at $DIR/address-of.rs:5:17: 5:29
-        FakeRead(ForLet, _3);            // scope 1 at $DIR/address-of.rs:5:9: 5:14
+        FakeRead(ForLet(None), _3);      // scope 1 at $DIR/address-of.rs:5:9: 5:14
         StorageLive(_5);                 // scope 2 at $DIR/address-of.rs:7:5: 7:18
         StorageLive(_6);                 // scope 2 at $DIR/address-of.rs:7:5: 7:18
         _6 = &raw const (*_1);           // scope 2 at $DIR/address-of.rs:7:5: 7:6
@@ -170,25 +170,25 @@ fn address_of_reborrow() -> () {
         StorageDead(_13);                // scope 2 at $DIR/address-of.rs:11:20: 11:21
         StorageLive(_15);                // scope 2 at $DIR/address-of.rs:13:9: 13:10
         _15 = &raw const (*_1);          // scope 2 at $DIR/address-of.rs:13:23: 13:24
-        FakeRead(ForLet, _15);           // scope 2 at $DIR/address-of.rs:13:9: 13:10
+        FakeRead(ForLet(None), _15);     // scope 2 at $DIR/address-of.rs:13:9: 13:10
         AscribeUserType(_15, o, UserTypeProjection { base: UserType(3), projs: [] }); // scope 2 at $DIR/address-of.rs:13:12: 13:20
         StorageLive(_16);                // scope 3 at $DIR/address-of.rs:14:9: 14:10
         _16 = &raw const (*_1);          // scope 3 at $DIR/address-of.rs:14:31: 14:32
-        FakeRead(ForLet, _16);           // scope 3 at $DIR/address-of.rs:14:9: 14:10
+        FakeRead(ForLet(None), _16);     // scope 3 at $DIR/address-of.rs:14:9: 14:10
         AscribeUserType(_16, o, UserTypeProjection { base: UserType(5), projs: [] }); // scope 3 at $DIR/address-of.rs:14:12: 14:28
         StorageLive(_17);                // scope 4 at $DIR/address-of.rs:15:9: 15:10
         StorageLive(_18);                // scope 4 at $DIR/address-of.rs:15:30: 15:31
         _18 = &raw const (*_1);          // scope 4 at $DIR/address-of.rs:15:30: 15:31
         _17 = move _18 as *const dyn std::marker::Send (Pointer(Unsize)); // scope 4 at $DIR/address-of.rs:15:30: 15:31
         StorageDead(_18);                // scope 4 at $DIR/address-of.rs:15:30: 15:31
-        FakeRead(ForLet, _17);           // scope 4 at $DIR/address-of.rs:15:9: 15:10
+        FakeRead(ForLet(None), _17);     // scope 4 at $DIR/address-of.rs:15:9: 15:10
         AscribeUserType(_17, o, UserTypeProjection { base: UserType(7), projs: [] }); // scope 4 at $DIR/address-of.rs:15:12: 15:27
         StorageLive(_19);                // scope 5 at $DIR/address-of.rs:16:9: 16:10
         StorageLive(_20);                // scope 5 at $DIR/address-of.rs:16:27: 16:28
         _20 = &raw const (*_1);          // scope 5 at $DIR/address-of.rs:16:27: 16:28
         _19 = move _20 as *const [i32] (Pointer(Unsize)); // scope 5 at $DIR/address-of.rs:16:27: 16:28
         StorageDead(_20);                // scope 5 at $DIR/address-of.rs:16:27: 16:28
-        FakeRead(ForLet, _19);           // scope 5 at $DIR/address-of.rs:16:9: 16:10
+        FakeRead(ForLet(None), _19);     // scope 5 at $DIR/address-of.rs:16:9: 16:10
         AscribeUserType(_19, o, UserTypeProjection { base: UserType(9), projs: [] }); // scope 5 at $DIR/address-of.rs:16:12: 16:24
         StorageLive(_21);                // scope 6 at $DIR/address-of.rs:18:5: 18:18
         StorageLive(_22);                // scope 6 at $DIR/address-of.rs:18:5: 18:18
@@ -218,25 +218,25 @@ fn address_of_reborrow() -> () {
         StorageDead(_27);                // scope 6 at $DIR/address-of.rs:21:22: 21:23
         StorageLive(_29);                // scope 6 at $DIR/address-of.rs:23:9: 23:10
         _29 = &raw const (*_3);          // scope 6 at $DIR/address-of.rs:23:23: 23:24
-        FakeRead(ForLet, _29);           // scope 6 at $DIR/address-of.rs:23:9: 23:10
+        FakeRead(ForLet(None), _29);     // scope 6 at $DIR/address-of.rs:23:9: 23:10
         AscribeUserType(_29, o, UserTypeProjection { base: UserType(13), projs: [] }); // scope 6 at $DIR/address-of.rs:23:12: 23:20
         StorageLive(_30);                // scope 7 at $DIR/address-of.rs:24:9: 24:10
         _30 = &raw const (*_3);          // scope 7 at $DIR/address-of.rs:24:31: 24:32
-        FakeRead(ForLet, _30);           // scope 7 at $DIR/address-of.rs:24:9: 24:10
+        FakeRead(ForLet(None), _30);     // scope 7 at $DIR/address-of.rs:24:9: 24:10
         AscribeUserType(_30, o, UserTypeProjection { base: UserType(15), projs: [] }); // scope 7 at $DIR/address-of.rs:24:12: 24:28
         StorageLive(_31);                // scope 8 at $DIR/address-of.rs:25:9: 25:10
         StorageLive(_32);                // scope 8 at $DIR/address-of.rs:25:30: 25:31
         _32 = &raw const (*_3);          // scope 8 at $DIR/address-of.rs:25:30: 25:31
         _31 = move _32 as *const dyn std::marker::Send (Pointer(Unsize)); // scope 8 at $DIR/address-of.rs:25:30: 25:31
         StorageDead(_32);                // scope 8 at $DIR/address-of.rs:25:30: 25:31
-        FakeRead(ForLet, _31);           // scope 8 at $DIR/address-of.rs:25:9: 25:10
+        FakeRead(ForLet(None), _31);     // scope 8 at $DIR/address-of.rs:25:9: 25:10
         AscribeUserType(_31, o, UserTypeProjection { base: UserType(17), projs: [] }); // scope 8 at $DIR/address-of.rs:25:12: 25:27
         StorageLive(_33);                // scope 9 at $DIR/address-of.rs:26:9: 26:10
         StorageLive(_34);                // scope 9 at $DIR/address-of.rs:26:27: 26:28
         _34 = &raw const (*_3);          // scope 9 at $DIR/address-of.rs:26:27: 26:28
         _33 = move _34 as *const [i32] (Pointer(Unsize)); // scope 9 at $DIR/address-of.rs:26:27: 26:28
         StorageDead(_34);                // scope 9 at $DIR/address-of.rs:26:27: 26:28
-        FakeRead(ForLet, _33);           // scope 9 at $DIR/address-of.rs:26:9: 26:10
+        FakeRead(ForLet(None), _33);     // scope 9 at $DIR/address-of.rs:26:9: 26:10
         AscribeUserType(_33, o, UserTypeProjection { base: UserType(19), projs: [] }); // scope 9 at $DIR/address-of.rs:26:12: 26:24
         StorageLive(_35);                // scope 10 at $DIR/address-of.rs:28:5: 28:16
         StorageLive(_36);                // scope 10 at $DIR/address-of.rs:28:5: 28:16
@@ -266,25 +266,25 @@ fn address_of_reborrow() -> () {
         StorageDead(_41);                // scope 10 at $DIR/address-of.rs:31:20: 31:21
         StorageLive(_43);                // scope 10 at $DIR/address-of.rs:33:9: 33:10
         _43 = &raw mut (*_3);            // scope 10 at $DIR/address-of.rs:33:21: 33:22
-        FakeRead(ForLet, _43);           // scope 10 at $DIR/address-of.rs:33:9: 33:10
+        FakeRead(ForLet(None), _43);     // scope 10 at $DIR/address-of.rs:33:9: 33:10
         AscribeUserType(_43, o, UserTypeProjection { base: UserType(23), projs: [] }); // scope 10 at $DIR/address-of.rs:33:12: 33:18
         StorageLive(_44);                // scope 11 at $DIR/address-of.rs:34:9: 34:10
         _44 = &raw mut (*_3);            // scope 11 at $DIR/address-of.rs:34:29: 34:30
-        FakeRead(ForLet, _44);           // scope 11 at $DIR/address-of.rs:34:9: 34:10
+        FakeRead(ForLet(None), _44);     // scope 11 at $DIR/address-of.rs:34:9: 34:10
         AscribeUserType(_44, o, UserTypeProjection { base: UserType(25), projs: [] }); // scope 11 at $DIR/address-of.rs:34:12: 34:26
         StorageLive(_45);                // scope 12 at $DIR/address-of.rs:35:9: 35:10
         StorageLive(_46);                // scope 12 at $DIR/address-of.rs:35:28: 35:29
         _46 = &raw mut (*_3);            // scope 12 at $DIR/address-of.rs:35:28: 35:29
         _45 = move _46 as *mut dyn std::marker::Send (Pointer(Unsize)); // scope 12 at $DIR/address-of.rs:35:28: 35:29
         StorageDead(_46);                // scope 12 at $DIR/address-of.rs:35:28: 35:29
-        FakeRead(ForLet, _45);           // scope 12 at $DIR/address-of.rs:35:9: 35:10
+        FakeRead(ForLet(None), _45);     // scope 12 at $DIR/address-of.rs:35:9: 35:10
         AscribeUserType(_45, o, UserTypeProjection { base: UserType(27), projs: [] }); // scope 12 at $DIR/address-of.rs:35:12: 35:25
         StorageLive(_47);                // scope 13 at $DIR/address-of.rs:36:9: 36:10
         StorageLive(_48);                // scope 13 at $DIR/address-of.rs:36:25: 36:26
         _48 = &raw mut (*_3);            // scope 13 at $DIR/address-of.rs:36:25: 36:26
         _47 = move _48 as *mut [i32] (Pointer(Unsize)); // scope 13 at $DIR/address-of.rs:36:25: 36:26
         StorageDead(_48);                // scope 13 at $DIR/address-of.rs:36:25: 36:26
-        FakeRead(ForLet, _47);           // scope 13 at $DIR/address-of.rs:36:9: 36:10
+        FakeRead(ForLet(None), _47);     // scope 13 at $DIR/address-of.rs:36:9: 36:10
         AscribeUserType(_47, o, UserTypeProjection { base: UserType(29), projs: [] }); // scope 13 at $DIR/address-of.rs:36:12: 36:22
         _0 = const ();                   // scope 0 at $DIR/address-of.rs:3:26: 37:2
         StorageDead(_47);                // scope 13 at $DIR/address-of.rs:37:1: 37:2
diff --git a/src/test/mir-opt/address_of.borrow_and_cast.SimplifyCfg-initial.after.mir b/src/test/mir-opt/address_of.borrow_and_cast.SimplifyCfg-initial.after.mir
index e058b0aaa8f..195f3e2e65c 100644
--- a/src/test/mir-opt/address_of.borrow_and_cast.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/address_of.borrow_and_cast.SimplifyCfg-initial.after.mir
@@ -24,19 +24,19 @@ fn borrow_and_cast(_1: i32) -> () {
         StorageLive(_3);                 // scope 0 at $DIR/address-of.rs:42:13: 42:15
         _3 = &_1;                        // scope 0 at $DIR/address-of.rs:42:13: 42:15
         _2 = &raw const (*_3);           // scope 0 at $DIR/address-of.rs:42:13: 42:15
-        FakeRead(ForLet, _2);            // scope 0 at $DIR/address-of.rs:42:9: 42:10
+        FakeRead(ForLet(None), _2);      // scope 0 at $DIR/address-of.rs:42:9: 42:10
         StorageDead(_3);                 // scope 0 at $DIR/address-of.rs:42:29: 42:30
         StorageLive(_4);                 // scope 1 at $DIR/address-of.rs:43:9: 43:10
         StorageLive(_5);                 // scope 1 at $DIR/address-of.rs:43:13: 43:19
         _5 = &mut _1;                    // scope 1 at $DIR/address-of.rs:43:13: 43:19
         _4 = &raw const (*_5);           // scope 1 at $DIR/address-of.rs:43:13: 43:19
-        FakeRead(ForLet, _4);            // scope 1 at $DIR/address-of.rs:43:9: 43:10
+        FakeRead(ForLet(None), _4);      // scope 1 at $DIR/address-of.rs:43:9: 43:10
         StorageDead(_5);                 // scope 1 at $DIR/address-of.rs:43:33: 43:34
         StorageLive(_6);                 // scope 2 at $DIR/address-of.rs:44:9: 44:10
         StorageLive(_7);                 // scope 2 at $DIR/address-of.rs:44:13: 44:19
         _7 = &mut _1;                    // scope 2 at $DIR/address-of.rs:44:13: 44:19
         _6 = &raw mut (*_7);             // scope 2 at $DIR/address-of.rs:44:13: 44:19
-        FakeRead(ForLet, _6);            // scope 2 at $DIR/address-of.rs:44:9: 44:10
+        FakeRead(ForLet(None), _6);      // scope 2 at $DIR/address-of.rs:44:9: 44:10
         StorageDead(_7);                 // scope 2 at $DIR/address-of.rs:44:31: 44:32
         _0 = const ();                   // scope 0 at $DIR/address-of.rs:41:32: 45:2
         StorageDead(_6);                 // scope 2 at $DIR/address-of.rs:45:1: 45:2
diff --git a/src/test/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
index 7e0ca3dea4b..e751b825c05 100644
--- a/src/test/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
@@ -28,7 +28,7 @@ fn main() -> () {
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/basic_assignment.rs:11:9: 11:17
         _1 = const false;                // scope 0 at $DIR/basic_assignment.rs:11:20: 11:25
-        FakeRead(ForLet, _1);            // scope 0 at $DIR/basic_assignment.rs:11:9: 11:17
+        FakeRead(ForLet(None), _1);      // scope 0 at $DIR/basic_assignment.rs:11:9: 11:17
         StorageLive(_2);                 // scope 1 at $DIR/basic_assignment.rs:12:9: 12:17
         StorageLive(_3);                 // scope 2 at $DIR/basic_assignment.rs:16:16: 16:24
         _3 = _1;                         // scope 2 at $DIR/basic_assignment.rs:16:16: 16:24
@@ -36,7 +36,7 @@ fn main() -> () {
         StorageDead(_3);                 // scope 2 at $DIR/basic_assignment.rs:16:23: 16:24
         StorageLive(_4);                 // scope 2 at $DIR/basic_assignment.rs:18:9: 18:15
         _4 = Option::<Box<u32>>::None;   // scope 2 at $DIR/basic_assignment.rs:18:36: 18:40
-        FakeRead(ForLet, _4);            // scope 2 at $DIR/basic_assignment.rs:18:9: 18:15
+        FakeRead(ForLet(None), _4);      // scope 2 at $DIR/basic_assignment.rs:18:9: 18:15
         AscribeUserType(_4, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 2 at $DIR/basic_assignment.rs:18:17: 18:33
         StorageLive(_5);                 // scope 3 at $DIR/basic_assignment.rs:19:9: 19:15
         StorageLive(_6);                 // scope 4 at $DIR/basic_assignment.rs:23:14: 23:20
diff --git a/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir b/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir
index aa4f996c4b4..93507879a6f 100644
--- a/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir
@@ -18,7 +18,7 @@ fn match_tuple(_1: (u32, bool, Option<i32>, u32)) -> u32 {
     }
 
     bb0: {
-        FakeRead(ForMatchedPlace, _1);   // scope 0 at $DIR/exponential-or.rs:5:11: 5:12
+        FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/exponential-or.rs:5:11: 5:12
         switchInt((_1.0: u32)) -> [1_u32: bb2, 4_u32: bb2, otherwise: bb1]; // scope 0 at $DIR/exponential-or.rs:6:15: 6:16
     }
 
diff --git a/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
index e9e5a101a64..8355b2d195e 100644
--- a/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
@@ -14,7 +14,7 @@ fn main() -> () {
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/issue-38669.rs:5:9: 5:25
         _1 = const false;                // scope 0 at $DIR/issue-38669.rs:5:28: 5:33
-        FakeRead(ForLet, _1);            // scope 0 at $DIR/issue-38669.rs:5:9: 5:25
+        FakeRead(ForLet(None), _1);      // scope 0 at $DIR/issue-38669.rs:5:9: 5:25
         goto -> bb1;                     // scope 1 at $DIR/issue-38669.rs:6:5: 11:6
     }
 
diff --git a/src/test/mir-opt/issue_49232.main.mir_map.0.mir b/src/test/mir-opt/issue_49232.main.mir_map.0.mir
index 79f5495c788..06fbbda3d9e 100644
--- a/src/test/mir-opt/issue_49232.main.mir_map.0.mir
+++ b/src/test/mir-opt/issue_49232.main.mir_map.0.mir
@@ -24,7 +24,7 @@ fn main() -> () {
         StorageLive(_2);                 // scope 0 at $DIR/issue-49232.rs:7:13: 7:19
         StorageLive(_3);                 // scope 0 at $DIR/issue-49232.rs:8:19: 8:23
         _3 = const true;                 // scope 0 at $DIR/issue-49232.rs:8:19: 8:23
-        FakeRead(ForMatchedPlace, _3);   // scope 0 at $DIR/issue-49232.rs:8:19: 8:23
+        FakeRead(ForMatchedPlace(None), _3); // scope 0 at $DIR/issue-49232.rs:8:19: 8:23
         switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/issue-49232.rs:9:17: 9:22
     }
 
@@ -51,7 +51,7 @@ fn main() -> () {
     }
 
     bb8: {
-        FakeRead(ForLet, _2);            // scope 0 at $DIR/issue-49232.rs:7:13: 7:19
+        FakeRead(ForLet(None), _2);      // scope 0 at $DIR/issue-49232.rs:7:13: 7:19
         StorageDead(_3);                 // scope 0 at $DIR/issue-49232.rs:12:10: 12:11
         StorageLive(_5);                 // scope 1 at $DIR/issue-49232.rs:13:9: 13:22
         StorageLive(_6);                 // scope 1 at $DIR/issue-49232.rs:13:14: 13:21
diff --git a/src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir b/src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir
index cf66a501e35..2e6783b7f3c 100644
--- a/src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir
+++ b/src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir
@@ -38,7 +38,7 @@ fn main() -> () {
         _2 = [move _3, move _4];         // scope 1 at $DIR/issue-72181.rs:26:13: 26:43
         StorageDead(_4);                 // scope 1 at $DIR/issue-72181.rs:26:42: 26:43
         StorageDead(_3);                 // scope 1 at $DIR/issue-72181.rs:26:42: 26:43
-        FakeRead(ForLet, _2);            // scope 1 at $DIR/issue-72181.rs:26:9: 26:10
+        FakeRead(ForLet(None), _2);      // scope 1 at $DIR/issue-72181.rs:26:9: 26:10
         StorageLive(_5);                 // scope 2 at $DIR/issue-72181.rs:27:13: 27:30
         StorageLive(_6);                 // scope 4 at $DIR/issue-72181.rs:27:24: 27:25
         _6 = const 0_usize;              // scope 4 at $DIR/issue-72181.rs:27:24: 27:25
diff --git a/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir b/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir
index cf66a501e35..2e6783b7f3c 100644
--- a/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir
+++ b/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir
@@ -38,7 +38,7 @@ fn main() -> () {
         _2 = [move _3, move _4];         // scope 1 at $DIR/issue-72181.rs:26:13: 26:43
         StorageDead(_4);                 // scope 1 at $DIR/issue-72181.rs:26:42: 26:43
         StorageDead(_3);                 // scope 1 at $DIR/issue-72181.rs:26:42: 26:43
-        FakeRead(ForLet, _2);            // scope 1 at $DIR/issue-72181.rs:26:9: 26:10
+        FakeRead(ForLet(None), _2);      // scope 1 at $DIR/issue-72181.rs:26:9: 26:10
         StorageLive(_5);                 // scope 2 at $DIR/issue-72181.rs:27:13: 27:30
         StorageLive(_6);                 // scope 4 at $DIR/issue-72181.rs:27:24: 27:25
         _6 = const 0_usize;              // scope 4 at $DIR/issue-72181.rs:27:24: 27:25
diff --git a/src/test/mir-opt/issue_72181_1.f.mir_map.0.mir b/src/test/mir-opt/issue_72181_1.f.mir_map.0.mir
index 7571d7bb94f..7def08ece22 100644
--- a/src/test/mir-opt/issue_72181_1.f.mir_map.0.mir
+++ b/src/test/mir-opt/issue_72181_1.f.mir_map.0.mir
@@ -9,7 +9,7 @@ fn f(_1: Void) -> ! {
     bb0: {
         StorageLive(_2);                 // scope 0 at $DIR/issue-72181-1.rs:10:20: 12:2
         StorageLive(_3);                 // scope 0 at $DIR/issue-72181-1.rs:11:5: 11:15
-        FakeRead(ForMatchedPlace, _1);   // scope 0 at $DIR/issue-72181-1.rs:11:11: 11:12
+        FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/issue-72181-1.rs:11:11: 11:12
         unreachable;                     // scope 0 at $DIR/issue-72181-1.rs:11:11: 11:12
     }
 
diff --git a/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir b/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir
index 1fd91c2056b..3c26b20c35e 100644
--- a/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir
+++ b/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir
@@ -29,7 +29,7 @@ fn main() -> () {
 
     bb1: {
         StorageDead(_3);                 // scope 2 at $DIR/issue-72181-1.rs:17:43: 17:44
-        FakeRead(ForLet, _2);            // scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10
+        FakeRead(ForLet(None), _2);      // scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10
         AscribeUserType(_2, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at $DIR/issue-72181-1.rs:16:12: 16:16
         StorageLive(_4);                 // scope 1 at $DIR/issue-72181-1.rs:20:5: 20:9
         StorageLive(_5);                 // scope 1 at $DIR/issue-72181-1.rs:20:7: 20:8
diff --git a/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir b/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
index f109937dbf9..99c7ac8d5b7 100644
--- a/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
+++ b/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
@@ -41,7 +41,7 @@ fn main() -> () {
     bb4: {
         StorageLive(_6);                 // scope 0 at $DIR/loop_test.rs:14:13: 14:14
         _6 = const 1_i32;                // scope 0 at $DIR/loop_test.rs:14:17: 14:18
-        FakeRead(ForLet, _6);            // scope 0 at $DIR/loop_test.rs:14:13: 14:14
+        FakeRead(ForLet(None), _6);      // scope 0 at $DIR/loop_test.rs:14:13: 14:14
         StorageDead(_6);                 // scope 0 at $DIR/loop_test.rs:16:5: 16:6
         goto -> bb3;                     // scope 0 at $DIR/loop_test.rs:1:1: 1:1
     }
diff --git a/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
index 95beab2ec9a..3395cbfbdfb 100644
--- a/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
+++ b/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
@@ -31,7 +31,7 @@
       }
   
       bb0: {
--         FakeRead(ForMatchedPlace, _2);   // scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16
+-         FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16
 -         switchInt((_2.0: bool)) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/match-arm-scopes.rs:15:10: 15:15
 +         switchInt((_2.0: bool)) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:15:10: 15:15
       }
diff --git a/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir b/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir
index 1921b935941..5af242376c9 100644
--- a/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir
+++ b/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir
@@ -27,7 +27,7 @@ fn full_tested_match() -> () {
         StorageLive(_1);                 // scope 0 at $DIR/match_false_edges.rs:15:13: 19:6
         StorageLive(_2);                 // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27
         _2 = Option::<i32>::Some(const 42_i32); // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27
-        FakeRead(ForMatchedPlace, _2);   // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27
+        FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27
         _3 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:16:9: 16:16
         switchInt(move _3) -> [0_isize: bb1, 1_isize: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:16:9: 16:16
     }
diff --git a/src/test/mir-opt/match_false_edges.full_tested_match2.PromoteTemps.before.mir b/src/test/mir-opt/match_false_edges.full_tested_match2.PromoteTemps.before.mir
index c7b1cce061b..a4ebf8a0246 100644
--- a/src/test/mir-opt/match_false_edges.full_tested_match2.PromoteTemps.before.mir
+++ b/src/test/mir-opt/match_false_edges.full_tested_match2.PromoteTemps.before.mir
@@ -26,7 +26,7 @@ fn full_tested_match2() -> () {
         StorageLive(_1);                 // scope 0 at $DIR/match_false_edges.rs:26:13: 30:6
         StorageLive(_2);                 // scope 0 at $DIR/match_false_edges.rs:26:19: 26:27
         _2 = Option::<i32>::Some(const 42_i32); // scope 0 at $DIR/match_false_edges.rs:26:19: 26:27
-        FakeRead(ForMatchedPlace, _2);   // scope 0 at $DIR/match_false_edges.rs:26:19: 26:27
+        FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:26:19: 26:27
         _3 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:27:9: 27:16
         switchInt(move _3) -> [0_isize: bb1, 1_isize: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:27:9: 27:16
     }
diff --git a/src/test/mir-opt/match_false_edges.main.PromoteTemps.before.mir b/src/test/mir-opt/match_false_edges.main.PromoteTemps.before.mir
index 9b8ce2c1ed0..5de52b324f4 100644
--- a/src/test/mir-opt/match_false_edges.main.PromoteTemps.before.mir
+++ b/src/test/mir-opt/match_false_edges.main.PromoteTemps.before.mir
@@ -37,7 +37,7 @@ fn main() -> () {
         StorageLive(_1);                 // scope 0 at $DIR/match_false_edges.rs:35:13: 40:6
         StorageLive(_2);                 // scope 0 at $DIR/match_false_edges.rs:35:19: 35:26
         _2 = Option::<i32>::Some(const 1_i32); // scope 0 at $DIR/match_false_edges.rs:35:19: 35:26
-        FakeRead(ForMatchedPlace, _2);   // scope 0 at $DIR/match_false_edges.rs:35:19: 35:26
+        FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:35:19: 35:26
         _4 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:36:9: 36:17
         switchInt(move _4) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/match_false_edges.rs:36:9: 36:17
     }
diff --git a/src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir
index e3bc4f80f27..5bb910947ca 100644
--- a/src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir
@@ -21,12 +21,12 @@ fn main() -> () {
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/match_test.rs:7:9: 7:10
         _1 = const 3_i32;                // scope 0 at $DIR/match_test.rs:7:13: 7:14
-        FakeRead(ForLet, _1);            // scope 0 at $DIR/match_test.rs:7:9: 7:10
+        FakeRead(ForLet(None), _1);      // scope 0 at $DIR/match_test.rs:7:9: 7:10
         StorageLive(_2);                 // scope 1 at $DIR/match_test.rs:8:9: 8:10
         _2 = const true;                 // scope 1 at $DIR/match_test.rs:8:13: 8:17
-        FakeRead(ForLet, _2);            // scope 1 at $DIR/match_test.rs:8:9: 8:10
+        FakeRead(ForLet(None), _2);      // scope 1 at $DIR/match_test.rs:8:9: 8:10
         StorageLive(_3);                 // scope 2 at $DIR/match_test.rs:12:5: 17:6
-        FakeRead(ForMatchedPlace, _1);   // scope 2 at $DIR/match_test.rs:12:11: 12:12
+        FakeRead(ForMatchedPlace(None), _1); // scope 2 at $DIR/match_test.rs:12:11: 12:12
         _6 = Le(const 0_i32, _1);        // scope 2 at $DIR/match_test.rs:13:9: 13:14
         switchInt(move _6) -> [false: bb4, otherwise: bb1]; // scope 2 at $DIR/match_test.rs:13:9: 13:14
     }
diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
index 8c939d5fc3d..39e6cee11b4 100644
--- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
+++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
@@ -46,7 +46,7 @@ fn main() -> () {
     bb0: {
         StorageLive(_1);                 // bb0[0]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
         _1 = [const Const(Value(Scalar(0x00000001)): usize), const Const(Value(Scalar(0x00000002)): usize), const Const(Value(Scalar(0x00000003)): usize)]; // bb0[1]: scope 0 at $DIR/region-subtyping-basic.rs:17:17: 17:26
-        FakeRead(ForLet, _1);            // bb0[2]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
+        FakeRead(ForLet(None), _1);      // bb0[2]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
         StorageLive(_2);                 // bb0[3]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10
         StorageLive(_3);                 // bb0[4]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17
         _3 = const Const(Value(Scalar(0x00000000)): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17
@@ -57,10 +57,10 @@ fn main() -> () {
 
     bb1: {
         _2 = &'_#3r _1[_3];              // bb1[0]: scope 1 at $DIR/region-subtyping-basic.rs:18:13: 18:18
-        FakeRead(ForLet, _2);            // bb1[1]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10
+        FakeRead(ForLet(None), _2);      // bb1[1]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10
         StorageLive(_6);                 // bb1[2]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
         _6 = _2;                         // bb1[3]: scope 2 at $DIR/region-subtyping-basic.rs:19:13: 19:14
-        FakeRead(ForLet, _6);            // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
+        FakeRead(ForLet(None), _6);      // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
         StorageLive(_7);                 // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
         _7 = const Const(Value(Scalar(0x01)): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
         switchInt(move _7) -> [Const(Value(Scalar(0x00)): bool): bb3, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
index 00704baa6c1..6021b6529f9 100644
--- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
+++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
@@ -46,7 +46,7 @@ fn main() -> () {
     bb0: {
         StorageLive(_1);                 // bb0[0]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
         _1 = [const Const(Value(Scalar(0x0000000000000001)): usize), const Const(Value(Scalar(0x0000000000000002)): usize), const Const(Value(Scalar(0x0000000000000003)): usize)]; // bb0[1]: scope 0 at $DIR/region-subtyping-basic.rs:17:17: 17:26
-        FakeRead(ForLet, _1);            // bb0[2]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
+        FakeRead(ForLet(None), _1);      // bb0[2]: scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
         StorageLive(_2);                 // bb0[3]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10
         StorageLive(_3);                 // bb0[4]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17
         _3 = const Const(Value(Scalar(0x0000000000000000)): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17
@@ -57,10 +57,10 @@ fn main() -> () {
 
     bb1: {
         _2 = &'_#3r _1[_3];              // bb1[0]: scope 1 at $DIR/region-subtyping-basic.rs:18:13: 18:18
-        FakeRead(ForLet, _2);            // bb1[1]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10
+        FakeRead(ForLet(None), _2);      // bb1[1]: scope 1 at $DIR/region-subtyping-basic.rs:18:9: 18:10
         StorageLive(_6);                 // bb1[2]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
         _6 = _2;                         // bb1[3]: scope 2 at $DIR/region-subtyping-basic.rs:19:13: 19:14
-        FakeRead(ForLet, _6);            // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
+        FakeRead(ForLet(None), _6);      // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
         StorageLive(_7);                 // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
         _7 = const Const(Value(Scalar(0x01)): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
         switchInt(move _7) -> [Const(Value(Scalar(0x00)): bool): bb3, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
diff --git a/src/test/mir-opt/receiver_ptr_mutability.main.mir_map.0.mir b/src/test/mir-opt/receiver_ptr_mutability.main.mir_map.0.mir
index d2d96ff468d..f54c8f8ab4a 100644
--- a/src/test/mir-opt/receiver_ptr_mutability.main.mir_map.0.mir
+++ b/src/test/mir-opt/receiver_ptr_mutability.main.mir_map.0.mir
@@ -36,7 +36,7 @@ fn main() -> () {
     }
 
     bb1: {
-        FakeRead(ForLet, _1);            // scope 0 at $DIR/receiver-ptr-mutability.rs:14:9: 14:12
+        FakeRead(ForLet(None), _1);      // scope 0 at $DIR/receiver-ptr-mutability.rs:14:9: 14:12
         AscribeUserType(_1, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at $DIR/receiver-ptr-mutability.rs:14:14: 14:23
         StorageLive(_2);                 // scope 1 at $DIR/receiver-ptr-mutability.rs:15:5: 15:12
         StorageLive(_3);                 // scope 1 at $DIR/receiver-ptr-mutability.rs:15:5: 15:8
@@ -63,7 +63,7 @@ fn main() -> () {
         _7 = &_8;                        // scope 1 at $DIR/receiver-ptr-mutability.rs:18:35: 18:41
         _6 = &_7;                        // scope 1 at $DIR/receiver-ptr-mutability.rs:18:34: 18:41
         _5 = &(*_6);                     // scope 1 at $DIR/receiver-ptr-mutability.rs:18:34: 18:41
-        FakeRead(ForLet, _5);            // scope 1 at $DIR/receiver-ptr-mutability.rs:18:9: 18:16
+        FakeRead(ForLet(None), _5);      // scope 1 at $DIR/receiver-ptr-mutability.rs:18:9: 18:16
         AscribeUserType(_5, o, UserTypeProjection { base: UserType(3), projs: [] }); // scope 1 at $DIR/receiver-ptr-mutability.rs:18:18: 18:31
         StorageDead(_6);                 // scope 1 at $DIR/receiver-ptr-mutability.rs:18:41: 18:42
         StorageLive(_10);                // scope 2 at $DIR/receiver-ptr-mutability.rs:19:5: 19:16
diff --git a/src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff b/src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff
index 47027311b47..4aa388fc67b 100644
--- a/src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff
+++ b/src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff
@@ -13,7 +13,7 @@
       let mut _8: bool;                    // in scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
   
       bb0: {
--         FakeRead(ForMatchedPlace, _1);   // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12
+-         FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12
 +         nop;                             // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12
           _3 = discriminant(_1);           // scope 0 at $DIR/remove_fake_borrows.rs:8:9: 8:16
           switchInt(move _3) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:8:9: 8:16
diff --git a/src/test/mir-opt/simple_match.match_bool.mir_map.0.32bit.mir b/src/test/mir-opt/simple_match.match_bool.mir_map.0.32bit.mir
index 5bcb20ca72a..841cca7c381 100644
--- a/src/test/mir-opt/simple_match.match_bool.mir_map.0.32bit.mir
+++ b/src/test/mir-opt/simple_match.match_bool.mir_map.0.32bit.mir
@@ -5,7 +5,7 @@ fn match_bool(_1: bool) -> usize {
     let mut _0: usize;                   // return place in scope 0 at $DIR/simple-match.rs:5:27: 5:32
 
     bb0: {
-        FakeRead(ForMatchedPlace, _1);   // scope 0 at $DIR/simple-match.rs:6:11: 6:12
+        FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/simple-match.rs:6:11: 6:12
         switchInt(_1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simple-match.rs:7:9: 7:13
     }
 
diff --git a/src/test/mir-opt/simple_match.match_bool.mir_map.0.64bit.mir b/src/test/mir-opt/simple_match.match_bool.mir_map.0.64bit.mir
index 5bcb20ca72a..841cca7c381 100644
--- a/src/test/mir-opt/simple_match.match_bool.mir_map.0.64bit.mir
+++ b/src/test/mir-opt/simple_match.match_bool.mir_map.0.64bit.mir
@@ -5,7 +5,7 @@ fn match_bool(_1: bool) -> usize {
     let mut _0: usize;                   // return place in scope 0 at $DIR/simple-match.rs:5:27: 5:32
 
     bb0: {
-        FakeRead(ForMatchedPlace, _1);   // scope 0 at $DIR/simple-match.rs:6:11: 6:12
+        FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/simple-match.rs:6:11: 6:12
         switchInt(_1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simple-match.rs:7:9: 7:13
     }
 
diff --git a/src/test/mir-opt/storage_ranges.main.nll.0.mir b/src/test/mir-opt/storage_ranges.main.nll.0.mir
index 6fa83d3de62..e02580135af 100644
--- a/src/test/mir-opt/storage_ranges.main.nll.0.mir
+++ b/src/test/mir-opt/storage_ranges.main.nll.0.mir
@@ -39,7 +39,7 @@ fn main() -> () {
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/storage_ranges.rs:4:9: 4:10
         _1 = const 0_i32;                // scope 0 at $DIR/storage_ranges.rs:4:13: 4:14
-        FakeRead(ForLet, _1);            // scope 0 at $DIR/storage_ranges.rs:4:9: 4:10
+        FakeRead(ForLet(None), _1);      // scope 0 at $DIR/storage_ranges.rs:4:9: 4:10
         StorageLive(_2);                 // scope 1 at $DIR/storage_ranges.rs:5:5: 7:6
         StorageLive(_3);                 // scope 1 at $DIR/storage_ranges.rs:6:13: 6:14
         StorageLive(_4);                 // scope 1 at $DIR/storage_ranges.rs:6:18: 6:25
@@ -48,14 +48,14 @@ fn main() -> () {
         _4 = Option::<i32>::Some(move _5); // scope 1 at $DIR/storage_ranges.rs:6:18: 6:25
         StorageDead(_5);                 // scope 1 at $DIR/storage_ranges.rs:6:24: 6:25
         _3 = &_4;                        // scope 1 at $DIR/storage_ranges.rs:6:17: 6:25
-        FakeRead(ForLet, _3);            // scope 1 at $DIR/storage_ranges.rs:6:13: 6:14
+        FakeRead(ForLet(None), _3);      // scope 1 at $DIR/storage_ranges.rs:6:13: 6:14
         _2 = const ();                   // scope 1 at $DIR/storage_ranges.rs:5:5: 7:6
         StorageDead(_4);                 // scope 1 at $DIR/storage_ranges.rs:7:5: 7:6
         StorageDead(_3);                 // scope 1 at $DIR/storage_ranges.rs:7:5: 7:6
         StorageDead(_2);                 // scope 1 at $DIR/storage_ranges.rs:7:5: 7:6
         StorageLive(_6);                 // scope 1 at $DIR/storage_ranges.rs:8:9: 8:10
         _6 = const 1_i32;                // scope 1 at $DIR/storage_ranges.rs:8:13: 8:14
-        FakeRead(ForLet, _6);            // scope 1 at $DIR/storage_ranges.rs:8:9: 8:10
+        FakeRead(ForLet(None), _6);      // scope 1 at $DIR/storage_ranges.rs:8:9: 8:10
         _0 = const ();                   // scope 0 at $DIR/storage_ranges.rs:3:11: 9:2
         StorageDead(_6);                 // scope 1 at $DIR/storage_ranges.rs:9:1: 9:2
         StorageDead(_1);                 // scope 0 at $DIR/storage_ranges.rs:9:1: 9:2
diff --git a/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir b/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir
index d18f6308ded..7f81d9fc482 100644
--- a/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir
+++ b/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir
@@ -48,7 +48,7 @@ fn move_out_by_subslice() -> () {
 
     bb4: {
         StorageDead(_2);                 // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27
-        FakeRead(ForLet, _1);            // scope 0 at $DIR/uniform_array_move_out.rs:11:9: 11:10
+        FakeRead(ForLet(None), _1);      // scope 0 at $DIR/uniform_array_move_out.rs:11:9: 11:10
         StorageLive(_6);                 // scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17
         _6 = move _1[0..2];              // scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17
         _0 = const ();                   // scope 0 at $DIR/uniform_array_move_out.rs:10:27: 13:2
diff --git a/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir b/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir
index eda8e5fd3af..62ab494c066 100644
--- a/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir
+++ b/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir
@@ -48,7 +48,7 @@ fn move_out_from_end() -> () {
 
     bb4: {
         StorageDead(_2);                 // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27
-        FakeRead(ForLet, _1);            // scope 0 at $DIR/uniform_array_move_out.rs:5:9: 5:10
+        FakeRead(ForLet(None), _1);      // scope 0 at $DIR/uniform_array_move_out.rs:5:9: 5:10
         StorageLive(_6);                 // scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16
         _6 = move _1[1 of 2];            // scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16
         _0 = const ();                   // scope 0 at $DIR/uniform_array_move_out.rs:4:24: 7:2