about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs1
-rw-r--r--compiler/rustc_borrowck/src/def_use.rs2
-rw-r--r--compiler/rustc_borrowck/src/invalidation.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs5
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/statement.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs1
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs8
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs3
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs1
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs9
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs9
-rw-r--r--compiler/rustc_mir_build/src/build/cfg.rs11
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs7
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/liveness.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs1
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs5
-rw-r--r--compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs1
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs1
-rw-r--r--compiler/rustc_mir_transform/src/dead_store_elimination.rs4
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs4
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs1
-rw-r--r--compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs1
-rw-r--r--compiler/rustc_mir_transform/src/separate_const_switch.rs2
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs1
-rw-r--r--tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir1
-rw-r--r--tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir1
-rw-r--r--tests/mir-opt/building/match_false_edges.main.built.after.mir1
-rw-r--r--tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir1
-rw-r--r--tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir1
-rw-r--r--tests/mir-opt/issue_72181.main.built.after.mir2
-rw-r--r--tests/mir-opt/issue_91633.bar.built.after.mir1
-rw-r--r--tests/mir-opt/issue_91633.hey.built.after.mir1
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.continue.txt2
-rw-r--r--tests/ui/binding/issue-53114-safety-checks.rs16
-rw-r--r--tests/ui/binding/issue-53114-safety-checks.stderr72
-rw-r--r--tests/ui/borrowck/let_underscore_temporary.rs27
-rw-r--r--tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs3
-rw-r--r--tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr11
-rw-r--r--tests/ui/unsafe/unsafe-fn-deref-ptr.mir.stderr28
-rw-r--r--tests/ui/unsafe/unsafe-fn-deref-ptr.rs3
-rw-r--r--tests/ui/unsafe/unsafe-fn-deref-ptr.thir.stderr28
48 files changed, 271 insertions, 19 deletions
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index d2574aa58c2..0762987e229 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -390,6 +390,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
             | mir::StatementKind::Deinit(..)
             | mir::StatementKind::StorageLive(..)
             | mir::StatementKind::Retag { .. }
+            | mir::StatementKind::PlaceMention(..)
             | mir::StatementKind::AscribeUserType(..)
             | mir::StatementKind::Coverage(..)
             | mir::StatementKind::Intrinsic(..)
diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs
index 8e62a0198be..9e9f0b4b4ad 100644
--- a/compiler/rustc_borrowck/src/def_use.rs
+++ b/compiler/rustc_borrowck/src/def_use.rs
@@ -72,6 +72,8 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
         PlaceContext::MutatingUse(MutatingUseContext::Drop) =>
             Some(DefUse::Drop),
 
+        // This statement exists to help unsafeck. It does not require the place to be live.
+        PlaceContext::NonUse(NonUseContext::PlaceMention) => None,
         // Debug info is neither def nor use.
         PlaceContext::NonUse(NonUseContext::VarDebugInfo) => None,
 
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index 1006a047cce..a71c4163286 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -79,6 +79,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
             }
             // Only relevant for mir typeck
             StatementKind::AscribeUserType(..)
+            // Only relevant for unsafeck
+            | StatementKind::PlaceMention(..)
             // Doesn't have any language semantics
             | StatementKind::Coverage(..)
             // Does not actually affect borrowck
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 92acd755509..f84a4691d32 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -690,6 +690,8 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
             }
             // Only relevant for mir typeck
             StatementKind::AscribeUserType(..)
+            // Only relevant for unsafeck
+            | StatementKind::PlaceMention(..)
             // Doesn't have any language semantics
             | StatementKind::Coverage(..)
             // These do not actually affect borrowck
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index d85e058bb20..3919c4793a0 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -772,7 +772,9 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
 
         match context {
             PlaceContext::MutatingUse(_) => ty::Invariant,
-            PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant,
+            PlaceContext::NonUse(StorageDead | StorageLive | PlaceMention | VarDebugInfo) => {
+                ty::Invariant
+            }
             PlaceContext::NonMutatingUse(
                 Inspect | Copy | Move | SharedBorrow | ShallowBorrow | UniqueBorrow | AddressOf
                 | Projection,
@@ -1282,6 +1284,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             | StatementKind::Retag { .. }
             | StatementKind::Coverage(..)
             | StatementKind::ConstEvalCounter
+            | StatementKind::PlaceMention(..)
             | StatementKind::Nop => {}
             StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => {
                 bug!("Statement not allowed in this MIR phase")
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index cb0e272ceda..230256ba5aa 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -819,6 +819,7 @@ fn codegen_stmt<'tcx>(
         | StatementKind::Nop
         | StatementKind::FakeRead(..)
         | StatementKind::Retag { .. }
+        | StatementKind::PlaceMention(..)
         | StatementKind::AscribeUserType(..) => {}
 
         StatementKind::Coverage { .. } => fx.tcx.sess.fatal("-Zcoverage is unimplemented"),
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index 1930db72ead..efdf9f6d5bc 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -529,6 +529,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
                         | StatementKind::StorageDead(_)
                         | StatementKind::Retag(_, _)
                         | StatementKind::AscribeUserType(_, _)
+                        | StatementKind::PlaceMention(..)
                         | StatementKind::Coverage(_)
                         | StatementKind::ConstEvalCounter
                         | StatementKind::Nop => {}
diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs
index 60fbceb344d..41f585f7fcc 100644
--- a/compiler/rustc_codegen_ssa/src/mir/statement.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs
@@ -92,6 +92,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             | mir::StatementKind::Retag { .. }
             | mir::StatementKind::AscribeUserType(..)
             | mir::StatementKind::ConstEvalCounter
+            | mir::StatementKind::PlaceMention(..)
             | mir::StatementKind::Nop => {}
         }
     }
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 6863435e508..9a366364e76 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -114,7 +114,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             Intrinsic(box intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?,
 
             // Statements we do not track.
-            AscribeUserType(..) => {}
+            PlaceMention(..) | AscribeUserType(..) => {}
 
             // Currently, Miri discards Coverage statements. Coverage statements are only injected
             // via an optional compile time MIR pass and have no side effects. Since Coverage
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 656baa784d7..081d9dc8700 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -690,6 +690,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
             | StatementKind::StorageLive(_)
             | StatementKind::StorageDead(_)
             | StatementKind::Retag { .. }
+            | StatementKind::PlaceMention(..)
             | StatementKind::AscribeUserType(..)
             | StatementKind::Coverage(..)
             | StatementKind::Intrinsic(..)
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 8ecd8f639dd..49b1e6d967c 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -679,6 +679,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     }
                 }
             }
+            StatementKind::PlaceMention(..) => {
+                if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
+                    self.fail(
+                        location,
+                        "`PlaceMention` should have been removed after drop lowering phase",
+                    );
+                }
+            }
             StatementKind::AscribeUserType(..) => {
                 if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 6e6bb8ce95e..5215e3db798 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1453,6 +1453,9 @@ impl Debug for Statement<'_> {
                 write!(fmt, "discriminant({:?}) = {:?}", place, variant_index)
             }
             Deinit(ref place) => write!(fmt, "Deinit({:?})", place),
+            PlaceMention(ref place) => {
+                write!(fmt, "PlaceMention({:?})", place)
+            }
             AscribeUserType(box (ref place, ref c_ty), ref variance) => {
                 write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty)
             }
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index e52610faf5a..1a23f9dadd4 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -247,6 +247,7 @@ pub fn statement_kind_name(statement: &Statement<'_>) -> &'static str {
         StorageLive(..) => "StorageLive",
         StorageDead(..) => "StorageDead",
         Retag(..) => "Retag",
+        PlaceMention(..) => "PlaceMention",
         AscribeUserType(..) => "AscribeUserType",
         Coverage(..) => "Coverage",
         Intrinsic(..) => "Intrinsic",
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 58c060db660..9312e27df37 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -325,6 +325,15 @@ pub enum StatementKind<'tcx> {
     /// Only `RetagKind::Default` and `RetagKind::FnEntry` are permitted.
     Retag(RetagKind, Box<Place<'tcx>>),
 
+    /// This statement exists to preserve a trace of a scrutinee matched against a wildcard binding.
+    /// This is especially useful for `let _ = PLACE;` bindings that desugar to a single
+    /// `PlaceMention(PLACE)`.
+    ///
+    /// When executed at runtime this is a nop.
+    ///
+    /// Disallowed after drop elaboration.
+    PlaceMention(Box<Place<'tcx>>),
+
     /// Encodes a user's type ascription. These need to be preserved
     /// intact so that NLL can respect them. For example:
     /// ```ignore (illustrative)
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 14b18618aa8..cbeacf21c19 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -405,6 +405,13 @@ macro_rules! make_mir_visitor {
                     StatementKind::Retag(kind, place) => {
                         self.visit_retag($(& $mutability)? *kind, place, location);
                     }
+                    StatementKind::PlaceMention(place) => {
+                        self.visit_place(
+                            place,
+                            PlaceContext::NonUse(NonUseContext::PlaceMention),
+                            location
+                        );
+                    }
                     StatementKind::AscribeUserType(
                         box (place, user_ty),
                         variance
@@ -1288,6 +1295,8 @@ pub enum NonUseContext {
     AscribeUserTy,
     /// The data of a user variable, for debug info.
     VarDebugInfo,
+    /// PlaceMention statement.
+    PlaceMention,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
diff --git a/compiler/rustc_mir_build/src/build/cfg.rs b/compiler/rustc_mir_build/src/build/cfg.rs
index d7b4b1f731a..4f1623b4c6a 100644
--- a/compiler/rustc_mir_build/src/build/cfg.rs
+++ b/compiler/rustc_mir_build/src/build/cfg.rs
@@ -90,6 +90,17 @@ impl<'tcx> CFG<'tcx> {
         self.push(block, stmt);
     }
 
+    pub(crate) fn push_place_mention(
+        &mut self,
+        block: BasicBlock,
+        source_info: SourceInfo,
+        place: Place<'tcx>,
+    ) {
+        let kind = StatementKind::PlaceMention(Box::new(place));
+        let stmt = Statement { source_info, kind };
+        self.push(block, stmt);
+    }
+
     pub(crate) fn terminate(
         &mut self,
         block: BasicBlock,
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index de2851a1af9..32892e0ae11 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -556,6 +556,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             _ => {
                 let place_builder = unpack!(block = self.as_place_builder(block, initializer));
+
+                if let Some(place) = place_builder.try_to_place(self) {
+                    let source_info = self.source_info(initializer.span);
+                    self.cfg.push_place_mention(block, source_info, place);
+                }
+
                 self.place_into_pattern(block, &irrefutable_pat, place_builder, true)
             }
         }
@@ -576,6 +582,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             false,
             &mut [&mut candidate],
         );
+
         // For matches and function arguments, the place that is being matched
         // can be set when creating the variables. But the place for
         // let PATTERN = ... might not even exist until we do the assignment.
diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
index 633a5674f1f..bc67aa476f1 100644
--- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
@@ -263,6 +263,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
             | StatementKind::StorageDead(_)
             | StatementKind::Retag(..)
             | StatementKind::AscribeUserType(..)
+            | StatementKind::PlaceMention(..)
             | StatementKind::Coverage(..)
             | StatementKind::Intrinsic(..)
             | StatementKind::ConstEvalCounter
diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
index 60fd5169054..99988b29e8a 100644
--- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
@@ -139,6 +139,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc
             // Nothing to do for these. Match exhaustively so this fails to compile when new
             // variants are added.
             StatementKind::AscribeUserType(..)
+            | StatementKind::PlaceMention(..)
             | StatementKind::Coverage(..)
             | StatementKind::FakeRead(..)
             | StatementKind::ConstEvalCounter
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index fa62960eee0..d9ceac1154f 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -329,6 +329,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             }
             StatementKind::Retag { .. }
             | StatementKind::AscribeUserType(..)
+            | StatementKind::PlaceMention(..)
             | StatementKind::Coverage(..)
             | StatementKind::Intrinsic(..)
             | StatementKind::ConstEvalCounter
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index b1474a770c5..7f560d61194 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -86,6 +86,7 @@ pub trait ValueAnalysis<'tcx> {
             StatementKind::ConstEvalCounter
             | StatementKind::Nop
             | StatementKind::FakeRead(..)
+            | StatementKind::PlaceMention(..)
             | StatementKind::Coverage(..)
             | StatementKind::AscribeUserType(..) => (),
         }
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index c61947c566d..a8ec568eb0d 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -100,13 +100,16 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
             | StatementKind::StorageLive(..)
             | StatementKind::StorageDead(..)
             | StatementKind::Retag { .. }
-            | StatementKind::AscribeUserType(..)
+            | StatementKind::PlaceMention(..)
             | StatementKind::Coverage(..)
             | StatementKind::Intrinsic(..)
             | StatementKind::ConstEvalCounter
             | StatementKind::Nop => {
                 // safe (at least as emitted during MIR construction)
             }
+            // `AscribeUserType` just exists to help MIR borrowck.
+            // It has no semantics, and everything is already reported by `PlaceMention`.
+            StatementKind::AscribeUserType(..) => return,
         }
         self.super_statement(statement, location);
     }
diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
index d435d3ee69b..0923824db48 100644
--- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
+++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
@@ -24,6 +24,7 @@ impl<'tcx> MirPass<'tcx> for CleanupPostBorrowck {
             for statement in basic_block.statements.iter_mut() {
                 match statement.kind {
                     StatementKind::AscribeUserType(..)
+                    | StatementKind::PlaceMention(..)
                     | StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Shallow, _)))
                     | StatementKind::FakeRead(..) => statement.make_nop(),
                     _ => (),
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index d9f68f5d93a..2f120258659 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -832,6 +832,7 @@ pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span>
         | StatementKind::SetDiscriminant { .. }
         | StatementKind::Deinit(..)
         | StatementKind::Retag(_, _)
+        | StatementKind::PlaceMention(..)
         | StatementKind::AscribeUserType(_, _) => {
             Some(statement.source_info.span)
         }
diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
index 9dbfb089dc6..18c407b42d3 100644
--- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs
+++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
@@ -56,7 +56,9 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
                 | StatementKind::ConstEvalCounter
                 | StatementKind::Nop => (),
 
-                StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => {
+                StatementKind::FakeRead(_)
+                | StatementKind::PlaceMention(_)
+                | StatementKind::AscribeUserType(_, _) => {
                     bug!("{:?} not found in this MIR phase!", &statement.kind)
                 }
             }
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 3823b6201c3..7344ec793ea 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -583,7 +583,9 @@ impl WriteInfo {
             | StatementKind::Coverage(_)
             | StatementKind::StorageLive(_)
             | StatementKind::StorageDead(_) => (),
-            StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => {
+            StatementKind::FakeRead(_)
+            | StatementKind::AscribeUserType(_, _)
+            | StatementKind::PlaceMention(_) => {
                 bug!("{:?} not found in this MIR phase", statement)
             }
         }
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 129f366bcd0..b7f1cdfc7f2 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1647,6 +1647,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
             | StatementKind::StorageDead(_)
             | StatementKind::Retag(..)
             | StatementKind::AscribeUserType(..)
+            | StatementKind::PlaceMention(..)
             | StatementKind::Coverage(..)
             | StatementKind::Intrinsic(..)
             | StatementKind::ConstEvalCounter
diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
index 6c067f45299..e962819b691 100644
--- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -33,6 +33,7 @@ impl RemoveNoopLandingPads {
                 StatementKind::FakeRead(..)
                 | StatementKind::StorageLive(_)
                 | StatementKind::StorageDead(_)
+                | StatementKind::PlaceMention(..)
                 | StatementKind::AscribeUserType(..)
                 | StatementKind::Coverage(..)
                 | StatementKind::ConstEvalCounter
diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs
index c3f5b881ab8..d76ab95faba 100644
--- a/compiler/rustc_mir_transform/src/separate_const_switch.rs
+++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs
@@ -245,6 +245,7 @@ fn is_likely_const<'tcx>(mut tracked_place: Place<'tcx>, block: &BasicBlockData<
             | StatementKind::StorageLive(_)
             | StatementKind::Retag(_, _)
             | StatementKind::AscribeUserType(_, _)
+            | StatementKind::PlaceMention(..)
             | StatementKind::Coverage(_)
             | StatementKind::StorageDead(_)
             | StatementKind::Intrinsic(_)
@@ -315,6 +316,7 @@ fn find_determining_place<'tcx>(
             | StatementKind::StorageDead(_)
             | StatementKind::Retag(_, _)
             | StatementKind::AscribeUserType(_, _)
+            | StatementKind::PlaceMention(..)
             | StatementKind::Coverage(_)
             | StatementKind::Intrinsic(_)
             | StatementKind::ConstEvalCounter
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 9ef55c558c6..929d229dcdf 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -525,6 +525,7 @@ impl<'tcx> Visitor<'tcx> for UsedLocals {
             | StatementKind::Retag(..)
             | StatementKind::Coverage(..)
             | StatementKind::FakeRead(..)
+            | StatementKind::PlaceMention(..)
             | StatementKind::AscribeUserType(..) => {
                 self.super_statement(statement, location);
             }
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index c00800291db..24403e8b6f3 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -241,6 +241,7 @@ fn check_statement<'tcx>(
         | StatementKind::StorageDead(_)
         | StatementKind::Retag { .. }
         | StatementKind::AscribeUserType(..)
+        | StatementKind::PlaceMention(..)
         | StatementKind::Coverage(..)
         | StatementKind::ConstEvalCounter
         | StatementKind::Nop => Ok(()),
diff --git a/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir b/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir
index cb36bc64da6..0e6de839df3 100644
--- a/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir
+++ b/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir
@@ -100,6 +100,7 @@ fn full_tested_match() -> () {
     }
 
     bb11: {
+        PlaceMention(_1);                // scope 0 at $DIR/match_false_edges.rs:+1:13: +5:6
         StorageDead(_2);                 // scope 0 at $DIR/match_false_edges.rs:+5:6: +5:7
         StorageDead(_1);                 // scope 0 at $DIR/match_false_edges.rs:+5:6: +5:7
         _0 = const ();                   // scope 0 at $DIR/match_false_edges.rs:+0:28: +6:2
diff --git a/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir b/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir
index 7f8755faac6..37e6b1cd4b4 100644
--- a/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir
+++ b/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir
@@ -100,6 +100,7 @@ fn full_tested_match2() -> () {
     }
 
     bb11: {
+        PlaceMention(_1);                // scope 0 at $DIR/match_false_edges.rs:+1:13: +5:6
         StorageDead(_2);                 // scope 0 at $DIR/match_false_edges.rs:+5:6: +5:7
         StorageDead(_1);                 // scope 0 at $DIR/match_false_edges.rs:+5:6: +5:7
         _0 = const ();                   // scope 0 at $DIR/match_false_edges.rs:+0:29: +6:2
diff --git a/tests/mir-opt/building/match_false_edges.main.built.after.mir b/tests/mir-opt/building/match_false_edges.main.built.after.mir
index e8b93f4371e..7b8983138d2 100644
--- a/tests/mir-opt/building/match_false_edges.main.built.after.mir
+++ b/tests/mir-opt/building/match_false_edges.main.built.after.mir
@@ -162,6 +162,7 @@ fn main() -> () {
     }
 
     bb19: {
+        PlaceMention(_1);                // scope 0 at $DIR/match_false_edges.rs:+1:13: +6:6
         StorageDead(_2);                 // scope 0 at $DIR/match_false_edges.rs:+6:6: +6:7
         StorageDead(_1);                 // scope 0 at $DIR/match_false_edges.rs:+6:6: +6:7
         _0 = const ();                   // scope 0 at $DIR/match_false_edges.rs:+0:11: +7:2
diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir
index 234cd083977..d80a77fefe5 100644
--- a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir
+++ b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir
@@ -77,6 +77,7 @@ fn move_out_by_subslice() -> () {
     bb6: {
         StorageDead(_2);                 // scope 0 at $DIR/uniform_array_move_out.rs:+1:26: +1:27
         FakeRead(ForLet(None), _1);      // scope 0 at $DIR/uniform_array_move_out.rs:+1:9: +1:10
+        PlaceMention(_1);                // scope 1 at $DIR/uniform_array_move_out.rs:+2:21: +2:22
         StorageLive(_12);                // scope 1 at $DIR/uniform_array_move_out.rs:+2:10: +2:12
         _12 = move _1[0..2];             // scope 1 at $DIR/uniform_array_move_out.rs:+2:10: +2:12
         _0 = const ();                   // scope 0 at $DIR/uniform_array_move_out.rs:+0:27: +3:2
diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir
index 24a189498d3..5f5c18c9f0c 100644
--- a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir
+++ b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir
@@ -77,6 +77,7 @@ fn move_out_from_end() -> () {
     bb6: {
         StorageDead(_2);                 // scope 0 at $DIR/uniform_array_move_out.rs:+1:26: +1:27
         FakeRead(ForLet(None), _1);      // scope 0 at $DIR/uniform_array_move_out.rs:+1:9: +1:10
+        PlaceMention(_1);                // scope 1 at $DIR/uniform_array_move_out.rs:+2:20: +2:21
         StorageLive(_12);                // scope 1 at $DIR/uniform_array_move_out.rs:+2:14: +2:16
         _12 = move _1[1 of 2];           // scope 1 at $DIR/uniform_array_move_out.rs:+2:14: +2:16
         _0 = const ();                   // scope 0 at $DIR/uniform_array_move_out.rs:+0:24: +3:2
diff --git a/tests/mir-opt/issue_72181.main.built.after.mir b/tests/mir-opt/issue_72181.main.built.after.mir
index e8683692770..724e55e17fb 100644
--- a/tests/mir-opt/issue_72181.main.built.after.mir
+++ b/tests/mir-opt/issue_72181.main.built.after.mir
@@ -29,6 +29,7 @@ fn main() -> () {
     }
 
     bb1: {
+        PlaceMention(_1);                // scope 0 at $DIR/issue_72181.rs:+1:13: +1:34
         StorageDead(_1);                 // scope 0 at $DIR/issue_72181.rs:+1:34: +1:35
         StorageLive(_2);                 // scope 1 at $DIR/issue_72181.rs:+3:9: +3:10
         StorageLive(_3);                 // scope 1 at $DIR/issue_72181.rs:+3:14: +3:27
@@ -49,6 +50,7 @@ fn main() -> () {
 
     bb2: {
         _5 = (_2[_6].0: u64);            // scope 4 at $DIR/issue_72181.rs:+4:22: +4:28
+        PlaceMention(_5);                // scope 2 at $DIR/issue_72181.rs:+4:13: +4:30
         StorageDead(_6);                 // scope 2 at $DIR/issue_72181.rs:+4:30: +4:31
         StorageDead(_5);                 // scope 2 at $DIR/issue_72181.rs:+4:30: +4:31
         _0 = const ();                   // scope 0 at $DIR/issue_72181.rs:+0:11: +5:2
diff --git a/tests/mir-opt/issue_91633.bar.built.after.mir b/tests/mir-opt/issue_91633.bar.built.after.mir
index c3fb90e8402..760e5a8f90a 100644
--- a/tests/mir-opt/issue_91633.bar.built.after.mir
+++ b/tests/mir-opt/issue_91633.bar.built.after.mir
@@ -20,6 +20,7 @@ fn bar(_1: Box<[T]>) -> () {
 
     bb1: {
         StorageDead(_3);                 // scope 0 at $DIR/issue_91633.rs:+4:18: +4:19
+        PlaceMention((*_2));             // scope 0 at $DIR/issue_91633.rs:+4:14: +4:19
         StorageDead(_2);                 // scope 0 at $DIR/issue_91633.rs:+4:19: +4:20
         _0 = const ();                   // scope 0 at $DIR/issue_91633.rs:+3:2: +5:3
         drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_91633.rs:+5:2: +5:3
diff --git a/tests/mir-opt/issue_91633.hey.built.after.mir b/tests/mir-opt/issue_91633.hey.built.after.mir
index ccb06dd5983..19f0c133e2e 100644
--- a/tests/mir-opt/issue_91633.hey.built.after.mir
+++ b/tests/mir-opt/issue_91633.hey.built.after.mir
@@ -23,6 +23,7 @@ fn hey(_1: &[T]) -> () {
     bb1: {
         StorageDead(_4);                 // scope 0 at $DIR/issue_91633.rs:+4:19: +4:20
         _2 = &(*_3);                     // scope 0 at $DIR/issue_91633.rs:+4:14: +4:20
+        PlaceMention(_2);                // scope 0 at $DIR/issue_91633.rs:+4:14: +4:20
         StorageDead(_2);                 // scope 0 at $DIR/issue_91633.rs:+4:20: +4:21
         _0 = const ();                   // scope 0 at $DIR/issue_91633.rs:+3:2: +5:3
         StorageDead(_3);                 // scope 0 at $DIR/issue_91633.rs:+5:2: +5:3
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.continue.txt b/tests/run-make/coverage-reports/expected_show_coverage.continue.txt
index 1c64ead9f26..bf42924b191 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.continue.txt
+++ b/tests/run-make/coverage-reports/expected_show_coverage.continue.txt
@@ -65,6 +65,6 @@
    65|       |        }
    66|      0|        x = 3;
    67|       |    }
-   68|       |    let _ = x;
+   68|      1|    let _ = x;
    69|      1|}
 
diff --git a/tests/ui/binding/issue-53114-safety-checks.rs b/tests/ui/binding/issue-53114-safety-checks.rs
index e234db516c7..f4be2b482a7 100644
--- a/tests/ui/binding/issue-53114-safety-checks.rs
+++ b/tests/ui/binding/issue-53114-safety-checks.rs
@@ -21,7 +21,7 @@ fn let_wild_gets_unsafe_field() {
     let u2 = U { a: I(1) };
     let p = P { a: &2, b: &3 };
     let _ = &p.b;  //~ ERROR    reference to packed field
-    let _ = u1.a;  // #53114: should eventually signal error as well
+    let _ = u1.a;  //~ ERROR  [E0133]
     let _ = &u2.a; //~ ERROR  [E0133]
 
     // variation on above with `_` in substructure
@@ -30,6 +30,20 @@ fn let_wild_gets_unsafe_field() {
     let (_,) = (&u2.a,); //~ ERROR   [E0133]
 }
 
+fn let_ascribe_gets_unsafe_field() {
+    let u1 = U { a: I(0) };
+    let u2 = U { a: I(1) };
+    let p = P { a: &2, b: &3 };
+    let _: _ = &p.b;  //~ ERROR    reference to packed field
+    let _: _ = u1.a;  //~ ERROR  [E0133]
+    let _: _ = &u2.a; //~ ERROR  [E0133]
+
+    // variation on above with `_` in substructure
+    let (_,): _ = (&p.b,);  //~ ERROR     reference to packed field
+    let (_,): _ = (u1.a,);  //~ ERROR   [E0133]
+    let (_,): _ = (&u2.a,); //~ ERROR   [E0133]
+}
+
 fn match_unsafe_field_to_wild() {
     let u1 = U { a: I(0) };
     let u2 = U { a: I(1) };
diff --git a/tests/ui/binding/issue-53114-safety-checks.stderr b/tests/ui/binding/issue-53114-safety-checks.stderr
index 5c9d7877247..41318d0a38a 100644
--- a/tests/ui/binding/issue-53114-safety-checks.stderr
+++ b/tests/ui/binding/issue-53114-safety-checks.stderr
@@ -17,7 +17,25 @@ LL |     let (_,) = (&p.b,);
    = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
 
 error[E0793]: reference to packed field is unaligned
-  --> $DIR/issue-53114-safety-checks.rs:37:11
+  --> $DIR/issue-53114-safety-checks.rs:37:16
+   |
+LL |     let _: _ = &p.b;
+   |                ^^^^
+   |
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+error[E0793]: reference to packed field is unaligned
+  --> $DIR/issue-53114-safety-checks.rs:42:20
+   |
+LL |     let (_,): _ = (&p.b,);
+   |                    ^^^^
+   |
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+error[E0793]: reference to packed field is unaligned
+  --> $DIR/issue-53114-safety-checks.rs:51:11
    |
 LL |     match &p.b  { _ => { } }
    |           ^^^^
@@ -26,7 +44,7 @@ LL |     match &p.b  { _ => { } }
    = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
 
 error[E0793]: reference to packed field is unaligned
-  --> $DIR/issue-53114-safety-checks.rs:42:12
+  --> $DIR/issue-53114-safety-checks.rs:56:12
    |
 LL |     match (&p.b,)  { (_,) => { } }
    |            ^^^^
@@ -35,6 +53,14 @@ LL |     match (&p.b,)  { (_,) => { } }
    = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/issue-53114-safety-checks.rs:24:13
+   |
+LL |     let _ = u1.a;
+   |             ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
   --> $DIR/issue-53114-safety-checks.rs:25:13
    |
 LL |     let _ = &u2.a;
@@ -59,7 +85,39 @@ LL |     let (_,) = (&u2.a,);
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/issue-53114-safety-checks.rs:38:11
+  --> $DIR/issue-53114-safety-checks.rs:38:16
+   |
+LL |     let _: _ = u1.a;
+   |                ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/issue-53114-safety-checks.rs:39:16
+   |
+LL |     let _: _ = &u2.a;
+   |                ^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/issue-53114-safety-checks.rs:43:20
+   |
+LL |     let (_,): _ = (u1.a,);
+   |                    ^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/issue-53114-safety-checks.rs:44:20
+   |
+LL |     let (_,): _ = (&u2.a,);
+   |                    ^^^^^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/issue-53114-safety-checks.rs:52:11
    |
 LL |     match u1.a  { _ => { } }
    |           ^^^^ access to union field
@@ -67,7 +125,7 @@ LL |     match u1.a  { _ => { } }
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/issue-53114-safety-checks.rs:39:11
+  --> $DIR/issue-53114-safety-checks.rs:53:11
    |
 LL |     match &u2.a { _ => { } }
    |           ^^^^^ access to union field
@@ -75,7 +133,7 @@ LL |     match &u2.a { _ => { } }
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/issue-53114-safety-checks.rs:43:12
+  --> $DIR/issue-53114-safety-checks.rs:57:12
    |
 LL |     match (u1.a,)  { (_,) => { } }
    |            ^^^^ access to union field
@@ -83,14 +141,14 @@ LL |     match (u1.a,)  { (_,) => { } }
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/issue-53114-safety-checks.rs:44:12
+  --> $DIR/issue-53114-safety-checks.rs:58:12
    |
 LL |     match (&u2.a,) { (_,) => { } }
    |            ^^^^^ access to union field
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
-error: aborting due to 11 previous errors
+error: aborting due to 18 previous errors
 
 Some errors have detailed explanations: E0133, E0793.
 For more information about an error, try `rustc --explain E0133`.
diff --git a/tests/ui/borrowck/let_underscore_temporary.rs b/tests/ui/borrowck/let_underscore_temporary.rs
new file mode 100644
index 00000000000..37b5c5d9d7a
--- /dev/null
+++ b/tests/ui/borrowck/let_underscore_temporary.rs
@@ -0,0 +1,27 @@
+// check-pass
+
+fn let_underscore(string: &Option<&str>, mut num: Option<i32>) {
+    let _ = if let Some(s) = *string { s.len() } else { 0 };
+    let _ = if let Some(s) = &num { s } else { &0 };
+    let _ = if let Some(s) = &mut num {
+        *s += 1;
+        s
+    } else {
+        &mut 0
+    };
+    let _ = if let Some(ref s) = num { s } else { &0 };
+    let _ = if let Some(mut s) = num {
+        s += 1;
+        s
+    } else {
+        0
+    };
+    let _ = if let Some(ref mut s) = num {
+        *s += 1;
+        s
+    } else {
+        &mut 0
+    };
+}
+
+fn main() {}
diff --git a/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs b/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs
index a6e1788bb7f..df20ff446cd 100644
--- a/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs
+++ b/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs
@@ -7,4 +7,7 @@ const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x }
 const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x }
 //~^ dereferencing raw mutable pointers in constant functions
 
+const unsafe fn bad_const_unsafe_deref_raw_underscore(x: *mut usize) { let _ = *x; }
+//~^ dereferencing raw mutable pointers in constant functions
+
 fn main() {}
diff --git a/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr b/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr
index 820b6433f36..e68376e7b87 100644
--- a/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr
+++ b/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr
@@ -25,6 +25,15 @@ LL | const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static u
    = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error: aborting due to 3 previous errors
+error[E0658]: dereferencing raw mutable pointers in constant functions is unstable
+  --> $DIR/min_const_fn_unsafe_bad.rs:10:80
+   |
+LL | const unsafe fn bad_const_unsafe_deref_raw_underscore(x: *mut usize) { let _ = *x; }
+   |                                                                                ^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/unsafe/unsafe-fn-deref-ptr.mir.stderr b/tests/ui/unsafe/unsafe-fn-deref-ptr.mir.stderr
index a2614992445..7f1e7c8902f 100644
--- a/tests/ui/unsafe/unsafe-fn-deref-ptr.mir.stderr
+++ b/tests/ui/unsafe/unsafe-fn-deref-ptr.mir.stderr
@@ -1,11 +1,35 @@
 error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/unsafe-fn-deref-ptr.rs:5:12
+  --> $DIR/unsafe-fn-deref-ptr.rs:5:13
+   |
+LL |     let _ = *p;
+   |             ^^ dereference of raw pointer
+   |
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-fn-deref-ptr.rs:6:17
+   |
+LL |     let _: u8 = *p;
+   |                 ^^ dereference of raw pointer
+   |
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-fn-deref-ptr.rs:7:9
+   |
+LL |     _ = *p;
+   |         ^^ dereference of raw pointer
+   |
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-fn-deref-ptr.rs:8:12
    |
 LL |     return *p;
    |            ^^ dereference of raw pointer
    |
    = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
-error: aborting due to previous error
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/unsafe/unsafe-fn-deref-ptr.rs b/tests/ui/unsafe/unsafe-fn-deref-ptr.rs
index dc989535bd6..4b7c6bf6985 100644
--- a/tests/ui/unsafe/unsafe-fn-deref-ptr.rs
+++ b/tests/ui/unsafe/unsafe-fn-deref-ptr.rs
@@ -2,6 +2,9 @@
 // [thir]compile-flags: -Z thir-unsafeck
 
 fn f(p: *const u8) -> u8 {
+    let _ = *p; //~ ERROR dereference of raw pointer is unsafe
+    let _: u8 = *p; //~ ERROR dereference of raw pointer is unsafe
+    _ = *p; //~ ERROR dereference of raw pointer is unsafe
     return *p; //~ ERROR dereference of raw pointer is unsafe
 }
 
diff --git a/tests/ui/unsafe/unsafe-fn-deref-ptr.thir.stderr b/tests/ui/unsafe/unsafe-fn-deref-ptr.thir.stderr
index a2614992445..7f1e7c8902f 100644
--- a/tests/ui/unsafe/unsafe-fn-deref-ptr.thir.stderr
+++ b/tests/ui/unsafe/unsafe-fn-deref-ptr.thir.stderr
@@ -1,11 +1,35 @@
 error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/unsafe-fn-deref-ptr.rs:5:12
+  --> $DIR/unsafe-fn-deref-ptr.rs:5:13
+   |
+LL |     let _ = *p;
+   |             ^^ dereference of raw pointer
+   |
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-fn-deref-ptr.rs:6:17
+   |
+LL |     let _: u8 = *p;
+   |                 ^^ dereference of raw pointer
+   |
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-fn-deref-ptr.rs:7:9
+   |
+LL |     _ = *p;
+   |         ^^ dereference of raw pointer
+   |
+   = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/unsafe-fn-deref-ptr.rs:8:12
    |
 LL |     return *p;
    |            ^^ dereference of raw pointer
    |
    = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
-error: aborting due to previous error
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0133`.