about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-09-22 20:38:19 +0000
committerbors <bors@rust-lang.org>2018-09-22 20:38:19 +0000
commit4591a245c7eec9f70d668982b1383cd2a6854af5 (patch)
tree182aea300e2792c6f042da22b652a972bf600563
parentaf50e3822c4ceda60445c4a2adbb3bfa480ebd39 (diff)
parent3bdba74ed3f8a859331ff658a6c0235855331095 (diff)
downloadrust-4591a245c7eec9f70d668982b1383cd2a6854af5.tar.gz
rust-4591a245c7eec9f70d668982b1383cd2a6854af5.zip
Auto merge of #54188 - lqd:fallout-53695, r=nikomatsakis
NLL: disallow creation of immediately unusable variables

Fix #53695

Original description follows

----

This WIP PR is for discussing the impact of fixing #53695 by injecting a fake read in let patterns.

(Travis will fail, at least the `mir-opt` suite is failing in its current state)
-rw-r--r--src/librustc/ich/impls_mir.rs5
-rw-r--r--src/librustc/mir/mod.rs36
-rw-r--r--src/librustc/mir/visit.rs2
-rw-r--r--src/librustc/session/config.rs2
-rw-r--r--src/librustc/ty/context.rs2
-rw-r--r--src/librustc_codegen_llvm/mir/statement.rs2
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs17
-rw-r--r--src/librustc_mir/borrow_check/mod.rs6
-rw-r--r--src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs10
-rw-r--r--src/librustc_mir/borrow_check/nll/invalidation.rs4
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs2
-rw-r--r--src/librustc_mir/build/matches/mod.rs34
-rw-r--r--src/librustc_mir/dataflow/impls/borrows.rs2
-rw-r--r--src/librustc_mir/dataflow/move_paths/builder.rs2
-rw-r--r--src/librustc_mir/interpret/step.rs4
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs2
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs2
-rw-r--r--src/librustc_mir/transform/qualify_min_const_fn.rs2
-rw-r--r--src/librustc_mir/transform/remove_noop_landing_pads.rs2
-rw-r--r--src/librustc_mir/transform/rustc_peek.rs2
-rw-r--r--src/librustc_passes/mir_stats.rs2
-rw-r--r--src/test/mir-opt/basic_assignment.rs2
-rw-r--r--src/test/mir-opt/box_expr.rs1
-rw-r--r--src/test/mir-opt/end_region_1.rs2
-rw-r--r--src/test/mir-opt/end_region_2.rs3
-rw-r--r--src/test/mir-opt/end_region_3.rs2
-rw-r--r--src/test/mir-opt/end_region_4.rs4
-rw-r--r--src/test/mir-opt/end_region_5.rs1
-rw-r--r--src/test/mir-opt/end_region_6.rs2
-rw-r--r--src/test/mir-opt/end_region_7.rs2
-rw-r--r--src/test/mir-opt/end_region_8.rs2
-rw-r--r--src/test/mir-opt/end_region_9.rs2
-rw-r--r--src/test/mir-opt/end_region_cyclic.rs1
-rw-r--r--src/test/mir-opt/inline-closure-borrows-arg.rs1
-rw-r--r--src/test/mir-opt/issue-38669.rs1
-rw-r--r--src/test/mir-opt/issue-49232.rs1
-rw-r--r--src/test/mir-opt/loop_test.rs1
-rw-r--r--src/test/mir-opt/match_false_edges.rs20
-rw-r--r--src/test/mir-opt/nll/region-subtyping-basic.rs6
-rw-r--r--src/test/mir-opt/storage_ranges.rs3
-rw-r--r--src/test/mir-opt/validate_1.rs1
-rw-r--r--src/test/mir-opt/validate_2.rs1
-rw-r--r--src/test/mir-opt/validate_3.rs2
-rw-r--r--src/test/ui/extern/extern-const.fixed25
-rw-r--r--src/test/ui/extern/extern-const.rs2
-rw-r--r--src/test/ui/generator/borrowing.nll.stderr5
-rw-r--r--src/test/ui/regions/regions-steal-closure.nll.stderr5
-rw-r--r--src/test/ui/span/range-2.nll.stderr12
-rw-r--r--src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr12
-rw-r--r--src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr12
-rw-r--r--src/test/ui/span/wf-method-late-bound-regions.nll.stderr6
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-region.nll.stderr5
52 files changed, 185 insertions, 102 deletions
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index 5f35c9fea0a..313ef054829 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -238,7 +238,8 @@ for mir::StatementKind<'gcx> {
                 place.hash_stable(hcx, hasher);
                 rvalue.hash_stable(hcx, hasher);
             }
-            mir::StatementKind::ReadForMatch(ref place) => {
+            mir::StatementKind::FakeRead(ref cause, ref place) => {
+                cause.hash_stable(hcx, hasher);
                 place.hash_stable(hcx, hasher);
             }
             mir::StatementKind::SetDiscriminant { ref place, variant_index } => {
@@ -271,6 +272,8 @@ for mir::StatementKind<'gcx> {
     }
 }
 
+impl_stable_hash_for!(enum mir::FakeReadCause { ForMatch, ForLet });
+
 impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>>
     for mir::ValidationOperand<'gcx, T>
     where T: HashStable<StableHashingContext<'a>>
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 3450eec8082..57aa2186927 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1613,8 +1613,10 @@ pub enum StatementKind<'tcx> {
     Assign(Place<'tcx>, Rvalue<'tcx>),
 
     /// This represents all the reading that a pattern match may do
-    /// (e.g. inspecting constants and discriminant values).
-    ReadForMatch(Place<'tcx>),
+    /// (e.g. inspecting constants and discriminant values), and the
+    /// kind of pattern it comes from. This is in order to adapt potential
+    /// error messages to these specific patterns.
+    FakeRead(FakeReadCause, Place<'tcx>),
 
     /// Write the discriminant for a variant to the enum Place.
     SetDiscriminant {
@@ -1662,6 +1664,31 @@ pub enum StatementKind<'tcx> {
     Nop,
 }
 
+/// The `FakeReadCause` describes the type of pattern why a `FakeRead` statement exists.
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
+pub enum FakeReadCause {
+    /// Inject a fake read of the borrowed input at the start of each arm's
+    /// pattern testing code.
+    ///
+    /// This should ensure that you cannot change the variant for an enum
+    /// while you are in the midst of matching on it.
+    ForMatch,
+
+    /// Officially, the semantics of
+    ///
+    /// `let pattern = <expr>;`
+    ///
+    /// is that `<expr>` is evaluated into a temporary and then this temporary is
+    /// into the pattern.
+    ///
+    /// However, if we see the simple pattern `let var = <expr>`, we optimize this to
+    /// evaluate `<expr>` directly into the variable `var`. This is mostly unobservable,
+    /// 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,
+}
+
 /// The `ValidationOp` describes what happens with each of the operands of a
 /// `Validate` statement.
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable, PartialEq, Eq)]
@@ -1718,7 +1745,7 @@ impl<'tcx> Debug for Statement<'tcx> {
         use self::StatementKind::*;
         match self.kind {
             Assign(ref place, ref rv) => write!(fmt, "{:?} = {:?}", place, rv),
-            ReadForMatch(ref place) => write!(fmt, "ReadForMatch({:?})", place),
+            FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place),
             // (reuse lifetime rendering policy from ppaux.)
             EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)),
             Validate(ref op, ref places) => write!(fmt, "Validate({:?}, {:?})", op, places),
@@ -2585,6 +2612,7 @@ CloneTypeFoldableAndLiftImpls! {
     Mutability,
     SourceInfo,
     UpvarDecl,
+    FakeReadCause,
     ValidationOp,
     SourceScope,
     SourceScopeData,
@@ -2651,7 +2679,7 @@ BraceStructTypeFoldableImpl! {
 EnumTypeFoldableImpl! {
     impl<'tcx> TypeFoldable<'tcx> for StatementKind<'tcx> {
         (StatementKind::Assign)(a, b),
-        (StatementKind::ReadForMatch)(place),
+        (StatementKind::FakeRead)(cause, place),
         (StatementKind::SetDiscriminant) { place, variant_index },
         (StatementKind::StorageLive)(a),
         (StatementKind::StorageDead)(a),
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 0beb5ac0a3c..91c83ecb2e2 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -354,7 +354,7 @@ macro_rules! make_mir_visitor {
                                           ref $($mutability)* rvalue) => {
                         self.visit_assign(block, place, rvalue, location);
                     }
-                    StatementKind::ReadForMatch(ref $($mutability)* place) => {
+                    StatementKind::FakeRead(_, ref $($mutability)* place) => {
                         self.visit_place(place,
                                          PlaceContext::Inspect,
                                          location);
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index e4d633c3f2c..1fdbf687be8 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1330,7 +1330,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
     disable_nll_user_type_assert: bool = (false, parse_bool, [UNTRACKED],
         "disable user provided type assertion in NLL"),
     nll_dont_emit_read_for_match: bool = (false, parse_bool, [UNTRACKED],
-        "in match codegen, do not include ReadForMatch statements (used by mir-borrowck)"),
+        "in match codegen, do not include FakeRead statements (used by mir-borrowck)"),
     dont_buffer_diagnostics: bool = (false, parse_bool, [UNTRACKED],
         "emit diagnostics rather than buffering (breaks NLL error downgrading, sorting)."),
     polonius: bool = (false, parse_bool, [UNTRACKED],
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index b7b0fdca2e6..37ef408c6bd 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -1505,7 +1505,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.emit_read_for_match()
     }
 
-    /// If true, make MIR codegen for `match` emit ReadForMatch
+    /// If true, make MIR codegen for `match` emit FakeRead
     /// statements (which simulate the maximal effect of executing the
     /// patterns in a match arm).
     pub fn emit_read_for_match(&self) -> bool {
diff --git a/src/librustc_codegen_llvm/mir/statement.rs b/src/librustc_codegen_llvm/mir/statement.rs
index 0cb8f99efc3..b4eb7615f98 100644
--- a/src/librustc_codegen_llvm/mir/statement.rs
+++ b/src/librustc_codegen_llvm/mir/statement.rs
@@ -89,7 +89,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
                 asm::codegen_inline_asm(&bx, asm, outputs, input_vals);
                 bx
             }
-            mir::StatementKind::ReadForMatch(_) |
+            mir::StatementKind::FakeRead(..) |
             mir::StatementKind::EndRegion(_) |
             mir::StatementKind::Validate(..) |
             mir::StatementKind::AscribeUserType(..) |
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 9187cb97e69..44bfc0cf06d 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -12,7 +12,7 @@ use borrow_check::WriteKind;
 use rustc::middle::region::ScopeTree;
 use rustc::mir::VarBindingForm;
 use rustc::mir::{BindingForm, BorrowKind, ClearCrossCrate, Field, Local};
-use rustc::mir::{LocalDecl, LocalKind, Location, Operand, Place};
+use rustc::mir::{FakeReadCause, LocalDecl, LocalKind, Location, Operand, Place};
 use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind};
 use rustc::ty;
 use rustc_data_structures::fx::FxHashSet;
@@ -1020,6 +1020,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             false
         }
     }
+
+    /// Returns the `FakeReadCause` at this location if it is a `FakeRead` statement.
+    pub(super) fn retrieve_fake_read_cause_for_location(
+        &self,
+        location: &Location,
+    ) -> Option<FakeReadCause> {
+        let stmt = self.mir.basic_blocks()[location.block]
+            .statements
+            .get(location.statement_index)?;
+        if let StatementKind::FakeRead(cause, _) = stmt.kind {
+            Some(cause)
+        } else {
+            None
+        }
+    }
 }
 
 // The span(s) associated to a use of a place.
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index c7e53714e3e..aea0bb748b2 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -501,9 +501,9 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
                     flow_state,
                 );
             }
-            StatementKind::ReadForMatch(ref place) => {
+            StatementKind::FakeRead(_, ref place) => {
                 self.access_place(
-                    ContextKind::ReadForMatch.new(location),
+                    ContextKind::FakeRead.new(location),
                     (place, span),
                     (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
                     LocalMutationIsAllowed::No,
@@ -2229,7 +2229,7 @@ enum ContextKind {
     CallDest,
     Assert,
     Yield,
-    ReadForMatch,
+    FakeRead,
     StorageDead,
 }
 
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
index 414cb1d6f05..c094350757e 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -11,7 +11,7 @@
 use borrow_check::borrow_set::BorrowData;
 use borrow_check::nll::region_infer::Cause;
 use borrow_check::{Context, MirBorrowckCtxt, WriteKind};
-use rustc::mir::{Local, Location, Place, TerminatorKind};
+use rustc::mir::{FakeReadCause, Local, Location, Place, TerminatorKind};
 use rustc_errors::DiagnosticBuilder;
 use rustc::ty::Region;
 
@@ -142,7 +142,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     if spans.for_closure() {
                         "borrow later captured here by closure"
                     } else {
-                        "borrow later used here"
+                        // Check if the location represents a `FakeRead`, and adapt the error
+                        // message to the `FakeReadCause` it is from: in particular,
+                        // the ones inserted in optimized `let var = <expr>` patterns.
+                        match self.retrieve_fake_read_cause_for_location(&location) {
+                            Some(FakeReadCause::ForLet) => "borrow later stored here",
+                            _ => "borrow later used here"
+                        }
                     }
                 };
                 err.span_label(spans.var_or_use(), message);
diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs
index 71345f22e44..0b7fededa97 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/nll/invalidation.rs
@@ -93,9 +93,9 @@ impl<'cg, 'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cg, 'cx, 'tc
                     JustWrite
                 );
             }
-            StatementKind::ReadForMatch(ref place) => {
+            StatementKind::FakeRead(_, ref place) => {
                 self.access_place(
-                    ContextKind::ReadForMatch.new(location),
+                    ContextKind::FakeRead.new(location),
                     place,
                     (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
                     LocalMutationIsAllowed::No,
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index de96539ec30..1f12e9c747f 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -995,7 +995,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     );
                 }
             }
-            StatementKind::ReadForMatch(_)
+            StatementKind::FakeRead(..)
             | StatementKind::StorageLive(_)
             | StatementKind::StorageDead(_)
             | StatementKind::InlineAsm { .. }
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 49c4ed874bb..c30dcdafdb4 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -145,19 +145,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     if let (true, Some(borrow_temp)) =
                         (tcx.emit_read_for_match(), borrowed_input_temp.clone())
                     {
-                        // inject a fake read of the borrowed input at
-                        // the start of each arm's pattern testing
-                        // code.
-                        //
-                        // This should ensure that you cannot change
-                        // the variant for an enum while you are in
-                        // the midst of matching on it.
+                        // Inject a fake read, see comments on `FakeReadCause::ForMatch`.
                         let pattern_source_info = self.source_info(pattern.span);
                         self.cfg.push(
                             *pre_binding_block,
                             Statement {
                                 source_info: pattern_source_info,
-                                kind: StatementKind::ReadForMatch(borrow_temp.clone()),
+                                kind: StatementKind::FakeRead(
+                                    FakeReadCause::ForMatch,
+                                    borrow_temp.clone(),
+                                ),
                             },
                         );
                     }
@@ -264,6 +261,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 let place =
                     self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard);
                 unpack!(block = self.into(&place, block, initializer));
+
+
+                // Inject a fake read, see comments on `FakeReadCause::ForLet`.
+                let source_info = self.source_info(irrefutable_pat.span);
+                self.cfg.push(
+                    block,
+                    Statement {
+                        source_info,
+                        kind: StatementKind::FakeRead(FakeReadCause::ForLet, place.clone()),
+                    },
+                );
+
                 self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard);
                 block.unit()
             }
@@ -305,6 +314,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     },
                 );
 
+                // Inject a fake read, see comments on `FakeReadCause::ForLet`.
+                self.cfg.push(
+                    block,
+                    Statement {
+                        source_info,
+                        kind: StatementKind::FakeRead(FakeReadCause::ForLet, place.clone()),
+                    },
+                );
+
                 self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard);
                 block.unit()
             }
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index 010ffafc4bd..ed2f780baf1 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -336,7 +336,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
                 }
             }
 
-            mir::StatementKind::ReadForMatch(..) |
+            mir::StatementKind::FakeRead(..) |
             mir::StatementKind::SetDiscriminant { .. } |
             mir::StatementKind::StorageLive(..) |
             mir::StatementKind::Validate(..) |
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 5451d27082d..63adcb5132a 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -281,7 +281,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
                 }
                 self.gather_rvalue(rval);
             }
-            StatementKind::ReadForMatch(ref place) => {
+            StatementKind::FakeRead(_, ref place) => {
                 self.create_move_path(place);
             }
             StatementKind::InlineAsm { ref outputs, ref inputs, ref asm } => {
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index 5bdaf6ba729..5db7e0b5eb5 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -150,9 +150,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
                 self.deallocate_local(old_val)?;
             }
 
-            // No dynamic semantics attached to `ReadForMatch`; MIR
+            // No dynamic semantics attached to `FakeRead`; MIR
             // interpreter is solely intended for borrowck'ed code.
-            ReadForMatch(..) => {}
+            FakeRead(..) => {}
 
             // Validity checks.
             Validate(op, ref places) => {
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 6fbc2f85c08..286de52bec5 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -108,7 +108,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
         self.source_info = statement.source_info;
         match statement.kind {
             StatementKind::Assign(..) |
-            StatementKind::ReadForMatch(..) |
+            StatementKind::FakeRead(..) |
             StatementKind::SetDiscriminant { .. } |
             StatementKind::StorageLive(..) |
             StatementKind::StorageDead(..) |
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index bc9cc7274d5..a997bd37c50 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -1090,7 +1090,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                 StatementKind::Assign(ref place, ref rvalue) => {
                     this.visit_assign(bb, place, rvalue, location);
                 }
-                StatementKind::ReadForMatch(..) |
+                StatementKind::FakeRead(..) |
                 StatementKind::SetDiscriminant { .. } |
                 StatementKind::StorageLive(_) |
                 StatementKind::StorageDead(_) |
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index f7e44dde186..541b3c0607d 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -216,7 +216,7 @@ fn check_statement(
             check_rvalue(tcx, mir, rval, span)
         }
 
-        StatementKind::ReadForMatch(_) => Err((span, "match in const fn is unstable".into())),
+        StatementKind::FakeRead(..) => Err((span, "match in const fn is unstable".into())),
 
         // just an assignment
         StatementKind::SetDiscriminant { .. } => Ok(()),
diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs
index 9cdd94a7be7..298e38228d3 100644
--- a/src/librustc_mir/transform/remove_noop_landing_pads.rs
+++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs
@@ -49,7 +49,7 @@ impl RemoveNoopLandingPads {
     ) -> bool {
         for stmt in &mir[bb].statements {
             match stmt.kind {
-                StatementKind::ReadForMatch(_) |
+                StatementKind::FakeRead(..) |
                 StatementKind::StorageLive(_) |
                 StatementKind::StorageDead(_) |
                 StatementKind::EndRegion(_) |
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 3c898eedebc..487a18f6620 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -157,7 +157,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             mir::StatementKind::Assign(ref place, ref rvalue) => {
                 (place, rvalue)
             }
-            mir::StatementKind::ReadForMatch(_) |
+            mir::StatementKind::FakeRead(..) |
             mir::StatementKind::StorageLive(_) |
             mir::StatementKind::StorageDead(_) |
             mir::StatementKind::InlineAsm { .. } |
diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs
index 0120b5bc532..0b9b20d3c45 100644
--- a/src/librustc_passes/mir_stats.rs
+++ b/src/librustc_passes/mir_stats.rs
@@ -82,7 +82,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
         self.record("Statement", statement);
         self.record(match statement.kind {
             StatementKind::Assign(..) => "StatementKind::Assign",
-            StatementKind::ReadForMatch(..) => "StatementKind::ReadForMatch",
+            StatementKind::FakeRead(..) => "StatementKind::FakeRead",
             StatementKind::EndRegion(..) => "StatementKind::EndRegion",
             StatementKind::Validate(..) => "StatementKind::Validate",
             StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant",
diff --git a/src/test/mir-opt/basic_assignment.rs b/src/test/mir-opt/basic_assignment.rs
index f04d4328929..b474e1a0d6c 100644
--- a/src/test/mir-opt/basic_assignment.rs
+++ b/src/test/mir-opt/basic_assignment.rs
@@ -47,6 +47,7 @@ fn main() {
 //    bb0: {
 //        StorageLive(_1);
 //        _1 = const false;
+//        FakeRead(ForLet, _1);
 //        StorageLive(_2);
 //        StorageLive(_3);
 //        _3 = _1;
@@ -55,6 +56,7 @@ fn main() {
 //        StorageLive(_4);
 //        _4 = std::option::Option<std::boxed::Box<u32>>::None;
 //        AscribeUserType(_4, o, Canonical { variables: [], value: std::option::Option<std::boxed::Box<u32>> });
+//        FakeRead(ForLet, _4);
 //        StorageLive(_5);
 //        StorageLive(_6);
 //        _6 = move _4;
diff --git a/src/test/mir-opt/box_expr.rs b/src/test/mir-opt/box_expr.rs
index 8390a0d19ae..f6877d979e0 100644
--- a/src/test/mir-opt/box_expr.rs
+++ b/src/test/mir-opt/box_expr.rs
@@ -63,6 +63,7 @@ impl Drop for S {
 //
 //     bb4: {
 //         StorageDead(_2);
+//         FakeRead(ForLet, _1);
 //         StorageLive(_4);
 //         _4 = move _1;
 //         _3 = const std::mem::drop(move _4) -> [return: bb5, unwind: bb7];
diff --git a/src/test/mir-opt/end_region_1.rs b/src/test/mir-opt/end_region_1.rs
index 184459aa90e..23c00c3bce1 100644
--- a/src/test/mir-opt/end_region_1.rs
+++ b/src/test/mir-opt/end_region_1.rs
@@ -29,8 +29,10 @@ fn main() {
 //     bb0: {
 //         StorageLive(_1);
 //         _1 = const 3i32;
+//         FakeRead(ForLet, _1);
 //         StorageLive(_2);
 //         _2 = &'10_1rs _1;
+//         FakeRead(ForLet, _2);
 //         _0 = ();
 //         EndRegion('10_1rs);
 //         StorageDead(_2);
diff --git a/src/test/mir-opt/end_region_2.rs b/src/test/mir-opt/end_region_2.rs
index c40ab5253a0..08de5320a2b 100644
--- a/src/test/mir-opt/end_region_2.rs
+++ b/src/test/mir-opt/end_region_2.rs
@@ -45,8 +45,10 @@ fn main() {
 //     bb2: {
 //         StorageLive(_2);
 //         _2 = const true;
+//         FakeRead(ForLet, _2);
 //         StorageLive(_3);
 //         _3 = &'23_1rs _2;
+//         FakeRead(ForLet, _3);
 //         StorageLive(_5);
 //         _5 = _2;
 //         switchInt(move _5) -> [false: bb5, otherwise: bb4];
@@ -67,6 +69,7 @@ fn main() {
 //         StorageDead(_5);
 //         StorageLive(_7);
 //         _7 = &'23_3rs _2;
+//         FakeRead(ForLet, _7);
 //         _1 = ();
 //         EndRegion('23_3rs);
 //         StorageDead(_7);
diff --git a/src/test/mir-opt/end_region_3.rs b/src/test/mir-opt/end_region_3.rs
index 086d80d15ea..189154332b8 100644
--- a/src/test/mir-opt/end_region_3.rs
+++ b/src/test/mir-opt/end_region_3.rs
@@ -49,6 +49,7 @@ fn main() {
 //         _1 = const true;
 //         StorageLive(_3);
 //         _3 = &'26_1rs _1;
+//         FakeRead(ForLet, _3);
 //         StorageLive(_5);
 //         _5 = _1;
 //         switchInt(move _5) -> [false: bb5, otherwise: bb4];
@@ -69,6 +70,7 @@ fn main() {
 //         StorageDead(_5);
 //         StorageLive(_7);
 //         _7 = &'26_3rs _1;
+//         FakeRead(ForLet, _7);
 //         _2 = ();
 //         EndRegion('26_3rs);
 //         StorageDead(_7);
diff --git a/src/test/mir-opt/end_region_4.rs b/src/test/mir-opt/end_region_4.rs
index fc58e0824e8..d5701669d2b 100644
--- a/src/test/mir-opt/end_region_4.rs
+++ b/src/test/mir-opt/end_region_4.rs
@@ -45,10 +45,13 @@ fn foo(i: i32) {
 //     bb0: {
 //         StorageLive(_1);
 //         _1 = D::{{constructor}}(const 0i32,);
+//         FakeRead(ForLet, _1);
 //         StorageLive(_2);
 //         _2 = const 0i32;
+//         FakeRead(ForLet, _2);
 //         StorageLive(_3);
 //         _3 = &'26_2rs _2;
+//         FakeRead(ForLet, _3);
 //         StorageLive(_5);
 //         _5 = (*_3);
 //         _4 = const foo(move _5) -> [return: bb2, unwind: bb3];
@@ -60,6 +63,7 @@ fn foo(i: i32) {
 //         StorageDead(_5);
 //         StorageLive(_6);
 //         _6 = &'26_4rs _2;
+//         FakeRead(ForLet, _6);
 //         _0 = ();
 //         EndRegion('26_4rs);
 //         StorageDead(_6);
diff --git a/src/test/mir-opt/end_region_5.rs b/src/test/mir-opt/end_region_5.rs
index 9496fd9e6c1..7a5d71ee21b 100644
--- a/src/test/mir-opt/end_region_5.rs
+++ b/src/test/mir-opt/end_region_5.rs
@@ -38,6 +38,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //     bb0: {
 //         StorageLive(_1);
 //         _1 = D::{{constructor}}(const 0i32,);
+//         FakeRead(ForLet, _1);
 //         StorageLive(_3);
 //         StorageLive(_4);
 //         _4 = &'14s _1;
diff --git a/src/test/mir-opt/end_region_6.rs b/src/test/mir-opt/end_region_6.rs
index 910362f65c8..b9162f85fa7 100644
--- a/src/test/mir-opt/end_region_6.rs
+++ b/src/test/mir-opt/end_region_6.rs
@@ -38,6 +38,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //     bb0: {
 //         StorageLive(_1);
 //         _1 = D::{{constructor}}(const 0i32,);
+//         FakeRead(ForLet, _1);
 //         StorageLive(_3);
 //         StorageLive(_4);
 //         _4 = &'19s _1;
@@ -73,6 +74,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //     bb0: {
 //         StorageLive(_2);
 //         _2 = &'16_0rs (*(_1.0: &'19s D));
+//         FakeRead(ForLet, _2);
 //         _0 = ((*_2).0: i32);
 //         EndRegion('16_0rs);
 //         StorageDead(_2);
diff --git a/src/test/mir-opt/end_region_7.rs b/src/test/mir-opt/end_region_7.rs
index 59261ec9687..4deea75e56b 100644
--- a/src/test/mir-opt/end_region_7.rs
+++ b/src/test/mir-opt/end_region_7.rs
@@ -37,6 +37,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //     bb0: {
 //         StorageLive(_1);
 //         _1 = D::{{constructor}}(const 0i32,);
+//         FakeRead(ForLet, _1);
 //         StorageLive(_3);
 //         _3 = [closure@NodeId(22)] { d: move _1 };
 //         _2 = const foo(move _3) -> [return: bb2, unwind: bb4];
@@ -74,6 +75,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //     bb0: {
 //         StorageLive(_2);
 //         _2 = &'16_0rs (_1.0: D);
+//         FakeRead(ForLet, _2);
 //         _0 = ((*_2).0: i32);
 //         EndRegion('16_0rs);
 //         StorageDead(_2);
diff --git a/src/test/mir-opt/end_region_8.rs b/src/test/mir-opt/end_region_8.rs
index a49913a62d9..6f899a0db15 100644
--- a/src/test/mir-opt/end_region_8.rs
+++ b/src/test/mir-opt/end_region_8.rs
@@ -40,8 +40,10 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //    bb0: {
 //        StorageLive(_1);
 //        _1 = D::{{constructor}}(const 0i32,);
+//        FakeRead(ForLet, _1);
 //        StorageLive(_2);
 //        _2 = &'21_1rs _1;
+//        FakeRead(ForLet, _2);
 //        StorageLive(_4);
 //        _4 = [closure@NodeId(22)] { r: _2 };
 //        _3 = const foo(move _4) -> [return: bb2, unwind: bb3];
diff --git a/src/test/mir-opt/end_region_9.rs b/src/test/mir-opt/end_region_9.rs
index 15c31e17875..b43f25e6f54 100644
--- a/src/test/mir-opt/end_region_9.rs
+++ b/src/test/mir-opt/end_region_9.rs
@@ -55,8 +55,10 @@ fn main() {
 //     bb0: {
 //        StorageLive(_1);
 //        _1 = const false;
+//        FakeRead(ForLet, _1);
 //        StorageLive(_2);
 //        _2 = const 3i32;
+//        FakeRead(ForLet, _2);
 //        falseUnwind -> [real: bb2, cleanup: bb1];
 //    }
 //    bb1: {
diff --git a/src/test/mir-opt/end_region_cyclic.rs b/src/test/mir-opt/end_region_cyclic.rs
index 2d6962c5a5c..75cfb5c2f62 100644
--- a/src/test/mir-opt/end_region_cyclic.rs
+++ b/src/test/mir-opt/end_region_cyclic.rs
@@ -83,6 +83,7 @@ fn query() -> bool { true }
 //         StorageDead(_4);
 //         _2 = S<'36_0rs> { r: move _3 };
 //         StorageDead(_3);
+//         FakeRead(ForLet, _2);
 //         StorageLive(_6);
 //         _6 = &'17s (_2.0: std::cell::Cell<std::option::Option<&'36_0rs S<'36_0rs>>>);
 //         StorageLive(_7);
diff --git a/src/test/mir-opt/inline-closure-borrows-arg.rs b/src/test/mir-opt/inline-closure-borrows-arg.rs
index 6ce51be3ec5..aab432ddc87 100644
--- a/src/test/mir-opt/inline-closure-borrows-arg.rs
+++ b/src/test/mir-opt/inline-closure-borrows-arg.rs
@@ -40,6 +40,7 @@ fn foo<T: Copy>(_t: T, q: &i32) -> i32 {
 //     _5 = (move _6, move _7);
 //     _8 = move (_5.0: &i32);
 //     _9 = move (_5.1: &i32);
+//     ...
 //     _0 = (*_8);
 //     ...
 //     return;
diff --git a/src/test/mir-opt/issue-38669.rs b/src/test/mir-opt/issue-38669.rs
index a9eea26f466..78820d7a6f5 100644
--- a/src/test/mir-opt/issue-38669.rs
+++ b/src/test/mir-opt/issue-38669.rs
@@ -25,6 +25,7 @@ fn main() {
 //     bb0: {
 //         StorageLive(_1);
 //         _1 = const false;
+//         FakeRead(ForLet, _1);
 //         goto -> bb2;
 //     }
 //     bb1: {
diff --git a/src/test/mir-opt/issue-49232.rs b/src/test/mir-opt/issue-49232.rs
index 8e5a94abeed..3bc735bc6c5 100644
--- a/src/test/mir-opt/issue-49232.rs
+++ b/src/test/mir-opt/issue-49232.rs
@@ -87,6 +87,7 @@ fn main() {
 //         goto -> bb6;
 //     }
 //     bb14: {
+//         FakeRead(ForLet, _2);
 //         StorageDead(_3);
 //         StorageLive(_7);
 //         _7 = &_2;
diff --git a/src/test/mir-opt/loop_test.rs b/src/test/mir-opt/loop_test.rs
index d36d8908094..2e526a221cc 100644
--- a/src/test/mir-opt/loop_test.rs
+++ b/src/test/mir-opt/loop_test.rs
@@ -42,6 +42,7 @@ fn main() {
 //    bb5: { // The loop body (body_block)
 //        StorageLive(_5);
 //        _5 = const 1i32;
+//        FakeRead(ForLet, _5);
 //        StorageDead(_5);
 //        goto -> bb4;
 //    }
diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs
index 43e711ca902..b9f4c239127 100644
--- a/src/test/mir-opt/match_false_edges.rs
+++ b/src/test/mir-opt/match_false_edges.rs
@@ -66,15 +66,15 @@ fn main() {
 //      goto -> bb13;
 //  }
 //  bb3: { // binding3(empty) and arm3
-//      ReadForMatch(_4);
+//      FakeRead(ForMatch, _4);
 //      falseEdges -> [real: bb8, imaginary: bb4]; //pre_binding1
 //  }
 //  bb4: {
-//      ReadForMatch(_4);
+//      FakeRead(ForMatch, _4);
 //      falseEdges -> [real: bb12, imaginary: bb5]; //pre_binding2
 //  }
 //  bb5: {
-//      ReadForMatch(_4);
+//      FakeRead(ForMatch, _4);
 //      falseEdges -> [real: bb2, imaginary: bb6]; //pre_binding3
 //  }
 //  bb6: {
@@ -136,15 +136,15 @@ fn main() {
 //      goto -> bb13;
 //  }
 //  bb3: {
-//      ReadForMatch(_4);
+//      FakeRead(ForMatch, _4);
 //      falseEdges -> [real: bb8, imaginary: bb4]; //pre_binding1
 //  }
 //  bb4: {
-//      ReadForMatch(_4);
+//      FakeRead(ForMatch, _4);
 //      falseEdges -> [real: bb2, imaginary: bb5]; //pre_binding2
 //  }
 //  bb5: {
-//      ReadForMatch(_4);
+//      FakeRead(ForMatch, _4);
 //      falseEdges -> [real: bb12, imaginary: bb6]; //pre_binding3
 //  }
 //  bb6: {
@@ -202,19 +202,19 @@ fn main() {
 //     resume;
 // }
 // bb2: {
-//     ReadForMatch(_4);
+//     FakeRead(ForMatch, _4);
 //     falseEdges -> [real: bb7, imaginary: bb3]; //pre_binding1
 // }
 // bb3: {
-//     ReadForMatch(_4);
+//     FakeRead(ForMatch, _4);
 //     falseEdges -> [real: bb11, imaginary: bb4]; //pre_binding2
 // }
 // bb4: {
-//     ReadForMatch(_4);
+//     FakeRead(ForMatch, _4);
 //     falseEdges -> [real: bb12, imaginary: bb5]; //pre_binding3
 // }
 // bb5: {
-//     ReadForMatch(_4);
+//     FakeRead(ForMatch, _4);
 //     falseEdges -> [real: bb16, imaginary: bb6]; //pre_binding4
 // }
 // bb6: {
diff --git a/src/test/mir-opt/nll/region-subtyping-basic.rs b/src/test/mir-opt/nll/region-subtyping-basic.rs
index e554024efef..2b926422b00 100644
--- a/src/test/mir-opt/nll/region-subtyping-basic.rs
+++ b/src/test/mir-opt/nll/region-subtyping-basic.rs
@@ -32,9 +32,9 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#2r    | U0 | {bb2[0..=3], bb3[0..=1]}
-// | '_#3r    | U0 | {bb2[1..=3], bb3[0..=1]}
-// | '_#4r    | U0 | {bb2[3], bb3[0..=1]}
+// | '_#2r    | U0 | {bb2[0..=5], bb3[0..=1]}
+// | '_#3r    | U0 | {bb2[1..=5], bb3[0..=1]}
+// | '_#4r    | U0 | {bb2[4..=5], bb3[0..=1]}
 // END rustc.main.nll.0.mir
 // START rustc.main.nll.0.mir
 // let _6: &'_#4r usize;
diff --git a/src/test/mir-opt/storage_ranges.rs b/src/test/mir-opt/storage_ranges.rs
index 16e30f84d17..203814ce949 100644
--- a/src/test/mir-opt/storage_ranges.rs
+++ b/src/test/mir-opt/storage_ranges.rs
@@ -23,6 +23,7 @@ fn main() {
 //     bb0: {
 //         StorageLive(_1);
 //         _1 = const 0i32;
+//         FakeRead(ForLet, _1);
 //         StorageLive(_3);
 //         StorageLive(_4);
 //         StorageLive(_5);
@@ -30,11 +31,13 @@ fn main() {
 //         _4 = std::option::Option<i32>::Some(move _5,);
 //         StorageDead(_5);
 //         _3 = &_4;
+//         FakeRead(ForLet, _3);
 //         _2 = ();
 //         StorageDead(_4);
 //         StorageDead(_3);
 //         StorageLive(_6);
 //         _6 = const 1i32;
+//         FakeRead(ForLet, _6);
 //         _0 = ();
 //         StorageDead(_6);
 //         StorageDead(_1);
diff --git a/src/test/mir-opt/validate_1.rs b/src/test/mir-opt/validate_1.rs
index 882579c5710..3ea8e99e953 100644
--- a/src/test/mir-opt/validate_1.rs
+++ b/src/test/mir-opt/validate_1.rs
@@ -67,6 +67,7 @@ fn main() {
 //         Validate(Suspend(ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 })), [(*_2): i32]);
 //         _3 = &ReErased (*_2);
 //         Validate(Acquire, [(*_3): i32/ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 }) (imm)]);
+//         FakeRead(ForLet, _3);
 //         _0 = (*_3);
 //         EndRegion(ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 }));
 //         StorageDead(_3);
diff --git a/src/test/mir-opt/validate_2.rs b/src/test/mir-opt/validate_2.rs
index 3776a11b3ab..0cb0b7debfa 100644
--- a/src/test/mir-opt/validate_2.rs
+++ b/src/test/mir-opt/validate_2.rs
@@ -28,6 +28,7 @@ fn main() {
 //         Validate(Acquire, [_1: std::boxed::Box<[i32]>]);
 //         StorageDead(_2);
 //         StorageDead(_3);
+//         FakeRead(ForLet, _1);
 //         _0 = ();
 //         Validate(Release, [_1: std::boxed::Box<[i32]>]);
 //         drop(_1) -> [return: bb2, unwind: bb3];
diff --git a/src/test/mir-opt/validate_3.rs b/src/test/mir-opt/validate_3.rs
index 07f5b2aa84b..89b67bd34c8 100644
--- a/src/test/mir-opt/validate_3.rs
+++ b/src/test/mir-opt/validate_3.rs
@@ -47,10 +47,12 @@ fn main() {
 //     bb0: {
 //         StorageLive(_1);
 //         _1 = Test { x: const 0i32 };
+//         FakeRead(ForLet, _1);
 //         StorageLive(_2);
 //         Validate(Suspend(ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 })), [_1: Test]);
 //         _2 = &ReErased _1;
 //         Validate(Acquire, [(*_2): Test/ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 }) (imm)]);
+//         FakeRead(ForLet, _2);
 //         StorageLive(_4);
 //         StorageLive(_5);
 //         Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [((*_2).0: i32): i32/ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 }) (imm)]);
diff --git a/src/test/ui/extern/extern-const.fixed b/src/test/ui/extern/extern-const.fixed
deleted file mode 100644
index 6e131ca41aa..00000000000
--- a/src/test/ui/extern/extern-const.fixed
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// run-rustfix
-// compile-flags: -Z continue-parse-after-error
-
-extern "C" {
-    static C: u8; //~ ERROR extern items cannot be `const`
-}
-
-fn main() {
-    // We suggest turning the (illegal) extern `const` into an extern `static`,
-    // but this also requires `unsafe` (a deny-by-default lint at comment time,
-    // future error; Issue #36247)
-    unsafe {
-        let _x = C;
-    }
-}
diff --git a/src/test/ui/extern/extern-const.rs b/src/test/ui/extern/extern-const.rs
index 4a766b9724d..d8a167311d5 100644
--- a/src/test/ui/extern/extern-const.rs
+++ b/src/test/ui/extern/extern-const.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// run-rustfix
+// FIXME(#54388): re-enable rustfix later, when this test has consistent output across targets
 // compile-flags: -Z continue-parse-after-error
 
 extern "C" {
diff --git a/src/test/ui/generator/borrowing.nll.stderr b/src/test/ui/generator/borrowing.nll.stderr
index e03d72a02f0..2488df7772b 100644
--- a/src/test/ui/generator/borrowing.nll.stderr
+++ b/src/test/ui/generator/borrowing.nll.stderr
@@ -10,6 +10,9 @@ LL |     };
 error[E0597]: `a` does not live long enough
   --> $DIR/borrowing.rs:24:9
    |
+LL |       let _b = {
+   |           -- borrow later stored here
+LL |           let a = 3;
 LL | /         || {
 LL | |             yield &a
 LL | |             //~^ ERROR: `a` does not live long enough
@@ -17,8 +20,6 @@ LL | |         }
    | |_________^ borrowed value does not live long enough
 LL |       };
    |       - `a` dropped here while still borrowed
-LL |   }
-   |   - borrow later used here, when `_b` is dropped
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/regions/regions-steal-closure.nll.stderr b/src/test/ui/regions/regions-steal-closure.nll.stderr
index ed70e38362d..538903c5918 100644
--- a/src/test/ui/regions/regions-steal-closure.nll.stderr
+++ b/src/test/ui/regions/regions-steal-closure.nll.stderr
@@ -1,14 +1,15 @@
 error[E0597]: `i` does not live long enough
   --> $DIR/regions-steal-closure.rs:24:28
    |
+LL |     let mut cl_box = {
+   |         ---------- borrow later stored here
+LL |         let mut i = 3;
 LL |         box_it(Box::new(|| i += 1)) //~ ERROR `i` does not live long enough
    |                         -- ^ borrowed value does not live long enough
    |                         |
    |                         value captured here
 LL |     };
    |     - `i` dropped here while still borrowed
-LL |     cl_box.cl.call_mut(());
-   |     --------- borrow later used here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/range-2.nll.stderr b/src/test/ui/span/range-2.nll.stderr
index 2a82e1b8ada..fe2fa2887ed 100644
--- a/src/test/ui/span/range-2.nll.stderr
+++ b/src/test/ui/span/range-2.nll.stderr
@@ -1,24 +1,24 @@
 error[E0597]: `a` does not live long enough
   --> $DIR/range-2.rs:17:9
    |
+LL |     let r = {
+   |         - borrow later stored here
+...
 LL |         &a..&b
    |         ^^ borrowed value does not live long enough
 LL |     };
    |     - `a` dropped here while still borrowed
-...
-LL |     r.use_ref();
-   |     - borrow later used here
 
 error[E0597]: `b` does not live long enough
   --> $DIR/range-2.rs:17:13
    |
+LL |     let r = {
+   |         - borrow later stored here
+...
 LL |         &a..&b
    |             ^^ borrowed value does not live long enough
 LL |     };
    |     - `b` dropped here while still borrowed
-...
-LL |     r.use_ref();
-   |     - borrow later used here
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr b/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr
index c14cb709893..80e2266896f 100644
--- a/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr
+++ b/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr
@@ -1,18 +1,21 @@
 error[E0597]: `x` does not live long enough
   --> $DIR/send-is-not-static-ensures-scoping.rs:26:17
    |
+LL |     let bad = {
+   |         --- borrow later stored here
+LL |         let x = 1;
 LL |         let y = &x;
    |                 ^^ borrowed value does not live long enough
 ...
 LL |     };
    |     - `x` dropped here while still borrowed
-LL | 
-LL |     bad.join();
-   |     --- borrow later used here
 
 error[E0597]: `y` does not live long enough
   --> $DIR/send-is-not-static-ensures-scoping.rs:30:22
    |
+LL |     let bad = {
+   |         --- borrow later stored here
+...
 LL |         scoped(|| {
    |                -- value captured here
 LL |             let _z = y;
@@ -20,9 +23,6 @@ LL |             let _z = y;
 ...
 LL |     };
    |     - `y` dropped here while still borrowed
-LL | 
-LL |     bad.join();
-   |     --- borrow later used here
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr b/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr
index 58dad753ac4..5b79b71dda0 100644
--- a/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr
+++ b/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr
@@ -1,24 +1,24 @@
 error[E0597]: `x` does not live long enough
   --> $DIR/send-is-not-static-std-sync-2.rs:21:20
    |
+LL |     let lock = {
+   |         ---- borrow later stored here
+LL |         let x = 1;
 LL |         Mutex::new(&x)
    |                    ^^ borrowed value does not live long enough
 LL |     };
    |     - `x` dropped here while still borrowed
-...
-LL |     let _dangling = *lock.lock().unwrap();
-   |                      ---- borrow later used here
 
 error[E0597]: `x` does not live long enough
   --> $DIR/send-is-not-static-std-sync-2.rs:31:21
    |
+LL |     let lock = {
+   |         ---- borrow later stored here
+LL |         let x = 1;
 LL |         RwLock::new(&x)
    |                     ^^ borrowed value does not live long enough
 LL |     };
    |     - `x` dropped here while still borrowed
-LL |     //~^^ ERROR `x` does not live long enough
-LL |     let _dangling = *lock.read().unwrap();
-   |                      ---- borrow later used here
 
 error[E0597]: `x` does not live long enough
   --> $DIR/send-is-not-static-std-sync-2.rs:41:25
diff --git a/src/test/ui/span/wf-method-late-bound-regions.nll.stderr b/src/test/ui/span/wf-method-late-bound-regions.nll.stderr
index cc32eaaa979..85eb348257b 100644
--- a/src/test/ui/span/wf-method-late-bound-regions.nll.stderr
+++ b/src/test/ui/span/wf-method-late-bound-regions.nll.stderr
@@ -1,13 +1,13 @@
 error[E0597]: `pointer` does not live long enough
   --> $DIR/wf-method-late-bound-regions.rs:30:18
    |
+LL |     let dangling = {
+   |         -------- borrow later stored here
+LL |         let pointer = Box::new(42);
 LL |         f2.xmute(&pointer)
    |                  ^^^^^^^^ borrowed value does not live long enough
 LL |     };
    |     - `pointer` dropped here while still borrowed
-LL |     //~^^ ERROR `pointer` does not live long enough
-LL |     println!("{}", dangling);
-   |                    -------- borrow later used here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-region.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closure-region.nll.stderr
index 6ad57a15465..7ba06b6ffb2 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-region.nll.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-region.nll.stderr
@@ -1,14 +1,15 @@
 error[E0597]: `x` does not live long enough
   --> $DIR/unboxed-closure-region.rs:18:12
    |
+LL |     let _f = {
+   |         -- borrow later stored here
+LL |         let x = 0;
 LL |         || x //~ ERROR `x` does not live long enough
    |         -- ^ borrowed value does not live long enough
    |         |
    |         value captured here
 LL |     };
    |     - `x` dropped here while still borrowed
-LL |     _f;
-   |     -- borrow later used here
 
 error: aborting due to previous error