diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index d88f165b9e538..c4e44a6a4e388 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -3566,6 +3566,15 @@ impl<'hir> OwnerNode<'hir> {
         }
     }
 
+    pub fn fn_sig(self) -> Option<&'hir FnSig<'hir>> {
+        match self {
+            OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
+            | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
+            | OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig),
+            _ => None,
+        }
+    }
+
     pub fn fn_decl(self) -> Option<&'hir FnDecl<'hir>> {
         match self {
             OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index d03d92c3a4b83..8feefb4c03ccc 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -66,8 +66,9 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
         Use { source } => visitor.visit_expr(&visitor.thir()[source]),
         NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]),
         PointerCoercion { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]),
-        Let { expr, .. } => {
+        Let { expr, ref pat } => {
             visitor.visit_expr(&visitor.thir()[expr]);
+            visitor.visit_pat(pat);
         }
         Loop { body } => visitor.visit_expr(&visitor.thir()[body]),
         Match { scrutinee, ref arms, .. } => {
diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl
index 563851f712c66..54fc8f77f9367 100644
--- a/compiler/rustc_mir_build/messages.ftl
+++ b/compiler/rustc_mir_build/messages.ftl
@@ -320,6 +320,7 @@ mir_build_unreachable_pattern = unreachable pattern
     .label = unreachable pattern
     .catchall_label = matches any value
 
+mir_build_unsafe_fn_safe_body = an unsafe function restricts its caller, but its body is safe by default
 mir_build_unsafe_not_inherited = items do not inherit unsafety from separate enclosing items
 
 mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe =
@@ -386,3 +387,5 @@ mir_build_unused_unsafe = unnecessary `unsafe` block
 mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block
 
 mir_build_variant_defined_here = not covered
+
+mir_build_wrap_suggestion = consider wrapping the function body in an unsafe block
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 45be501537130..3d895c131a85c 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -35,6 +35,10 @@ struct UnsafetyVisitor<'a, 'tcx> {
     param_env: ParamEnv<'tcx>,
     inside_adt: bool,
     warnings: &'a mut Vec<UnusedUnsafeWarning>,
+
+    /// Flag to ensure that we only suggest wrapping the entire function body in
+    /// an unsafe block once.
+    suggest_unsafe_block: bool,
 }
 
 impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
@@ -95,7 +99,13 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
             SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {}
             SafetyContext::UnsafeFn => {
                 // unsafe_op_in_unsafe_fn is disallowed
-                kind.emit_unsafe_op_in_unsafe_fn_lint(self.tcx, self.hir_context, span);
+                kind.emit_unsafe_op_in_unsafe_fn_lint(
+                    self.tcx,
+                    self.hir_context,
+                    span,
+                    self.suggest_unsafe_block,
+                );
+                self.suggest_unsafe_block = false;
             }
             SafetyContext::Safe => {
                 kind.emit_requires_unsafe_err(
@@ -297,6 +307,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
             }
             PatKind::InlineConstant { def, .. } => {
                 self.visit_inner_body(*def);
+                visit::walk_pat(self, pat);
             }
             _ => {
                 visit::walk_pat(self, pat);
@@ -394,7 +405,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                 }
             }
             ExprKind::Deref { arg } => {
-                if let ExprKind::StaticRef { def_id, .. } = self.thir[arg].kind {
+                if let ExprKind::StaticRef { def_id, .. } | ExprKind::ThreadLocalRef(def_id) =
+                    self.thir[arg].kind
+                {
                     if self.tcx.is_mutable_static(def_id) {
                         self.requires_unsafe(expr.span, UseOfMutableStatic);
                     } else if self.tcx.is_foreign_item(def_id) {
@@ -482,14 +495,6 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                     }
                 }
             }
-            ExprKind::Let { expr: expr_id, .. } => {
-                let let_expr = &self.thir[expr_id];
-                if let ty::Adt(adt_def, _) = let_expr.ty.kind()
-                    && adt_def.is_union()
-                {
-                    self.requires_unsafe(expr.span, AccessToUnionField);
-                }
-            }
             _ => {}
         }
         visit::walk_expr(self, expr);
@@ -543,7 +548,22 @@ impl UnsafeOpKind {
         tcx: TyCtxt<'_>,
         hir_id: hir::HirId,
         span: Span,
+        suggest_unsafe_block: bool,
     ) {
+        let parent_id = tcx.hir().get_parent_item(hir_id);
+        let parent_owner = tcx.hir().owner(parent_id);
+        let should_suggest = parent_owner.fn_sig().map_or(false, |sig| sig.header.is_unsafe());
+        let unsafe_not_inherited_note = if should_suggest {
+            suggest_unsafe_block.then(|| {
+                let body_span = tcx.hir().body(parent_owner.body_id().unwrap()).value.span;
+                UnsafeNotInheritedLintNote {
+                    signature_span: tcx.def_span(parent_id.def_id),
+                    body_span,
+                }
+            })
+        } else {
+            None
+        };
         // FIXME: ideally we would want to trim the def paths, but this is not
         // feasible with the current lint emission API (see issue #106126).
         match self {
@@ -554,61 +574,89 @@ impl UnsafeOpKind {
                 UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
                     span,
                     function: &with_no_trimmed_paths!(tcx.def_path_str(*did)),
+                    unsafe_not_inherited_note,
                 },
             ),
             CallToUnsafeFunction(None) => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { span },
+                UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             UseOfInlineAssembly => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { span },
+                UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             InitializingTypeWith => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { span },
+                UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             UseOfMutableStatic => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { span },
+                UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             UseOfExternStatic => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { span },
+                UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             DerefOfRawPointer => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { span },
+                UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             AccessToUnionField => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { span },
+                UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             MutationOfLayoutConstrainedField => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { span },
+                UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             BorrowOfLayoutConstrainedField => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
                 hir_id,
                 span,
-                UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { span },
+                UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe {
+                    span,
+                    unsafe_not_inherited_note,
+                },
             ),
             CallToFunctionWith(did) => tcx.emit_spanned_lint(
                 UNSAFE_OP_IN_UNSAFE_FN,
@@ -617,6 +665,7 @@ impl UnsafeOpKind {
                 UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
                     span,
                     function: &with_no_trimmed_paths!(tcx.def_path_str(*did)),
+                    unsafe_not_inherited_note,
                 },
             ),
         }
@@ -831,6 +880,7 @@ pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
         param_env: tcx.param_env(def),
         inside_adt: false,
         warnings: &mut warnings,
+        suggest_unsafe_block: true,
     };
     visitor.visit_expr(&thir[expr]);
 
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index c4eed5532ee63..418f9bb9de94d 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -29,6 +29,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> {
     #[label]
     pub span: Span,
     pub function: &'a str,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -37,6 +39,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> {
 pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -45,6 +49,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
 pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -53,6 +59,8 @@ pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
 pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -61,6 +69,8 @@ pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
 pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -69,6 +79,8 @@ pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
 pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -77,6 +89,8 @@ pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
 pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -85,6 +99,8 @@ pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
 pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -93,6 +109,8 @@ pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
 pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -100,6 +118,8 @@ pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
 pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe {
     #[label]
     pub span: Span,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(LintDiagnostic)]
@@ -109,6 +129,8 @@ pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> {
     #[label]
     pub span: Span,
     pub function: &'a str,
+    #[subdiagnostic]
+    pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
 }
 
 #[derive(Diagnostic)]
@@ -376,6 +398,27 @@ pub struct UnsafeNotInheritedNote {
     pub span: Span,
 }
 
+pub struct UnsafeNotInheritedLintNote {
+    pub signature_span: Span,
+    pub body_span: Span,
+}
+
+impl AddToDiagnostic for UnsafeNotInheritedLintNote {
+    fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
+    where
+        F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+    {
+        diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body);
+        let body_start = self.body_span.shrink_to_lo();
+        let body_end = self.body_span.shrink_to_hi();
+        diag.tool_only_multipart_suggestion(
+            fluent::mir_build_wrap_suggestion,
+            vec![(body_start, "{ unsafe ".into()), (body_end, "}".into())],
+            Applicability::MaybeIncorrect,
+        );
+    }
+}
+
 #[derive(LintDiagnostic)]
 #[diag(mir_build_unused_unsafe)]
 pub struct UnusedUnsafe {
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index e74d66a859926..620844f6f097c 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -3962,7 +3962,7 @@ impl<'test> TestCx<'test> {
             // And finally, compile the fixed code and make sure it both
             // succeeds and has no diagnostics.
             let rustc = self.make_compile_args(
-                &self.testpaths.file.with_extension(UI_FIXED),
+                &self.expected_output_path(UI_FIXED),
                 TargetLocation::ThisFile(self.make_exe_name()),
                 emit_metadata,
                 AllowUnused::No,
diff --git a/tests/ui/thread-local/thread-local-static.stderr b/tests/ui/thread-local/thread-local-static.mir.stderr
similarity index 88%
rename from tests/ui/thread-local/thread-local-static.stderr
rename to tests/ui/thread-local/thread-local-static.mir.stderr
index 712050a25fcfe..607d7ee902cb6 100644
--- a/tests/ui/thread-local/thread-local-static.stderr
+++ b/tests/ui/thread-local/thread-local-static.mir.stderr
@@ -1,5 +1,5 @@
 error[E0658]: mutable references are not allowed in constant functions
-  --> $DIR/thread-local-static.rs:7:12
+  --> $DIR/thread-local-static.rs:10:12
    |
 LL | const fn g(x: &mut [u32; 8]) {
    |            ^
@@ -8,13 +8,13 @@ LL | const fn g(x: &mut [u32; 8]) {
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error[E0625]: thread-local statics cannot be accessed at compile-time
-  --> $DIR/thread-local-static.rs:9:28
+  --> $DIR/thread-local-static.rs:12:28
    |
 LL |     std::mem::swap(x, &mut STATIC_VAR_2)
    |                            ^^^^^^^^^^^^
 
 error[E0013]: constant functions cannot refer to statics
-  --> $DIR/thread-local-static.rs:9:28
+  --> $DIR/thread-local-static.rs:12:28
    |
 LL |     std::mem::swap(x, &mut STATIC_VAR_2)
    |                            ^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL |     std::mem::swap(x, &mut STATIC_VAR_2)
    = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error[E0658]: mutable references are not allowed in constant functions
-  --> $DIR/thread-local-static.rs:9:23
+  --> $DIR/thread-local-static.rs:12:23
    |
 LL |     std::mem::swap(x, &mut STATIC_VAR_2)
    |                       ^^^^^^^^^^^^^^^^^
@@ -31,7 +31,7 @@ LL |     std::mem::swap(x, &mut STATIC_VAR_2)
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error[E0133]: use of mutable static is unsafe and requires unsafe function or block
-  --> $DIR/thread-local-static.rs:9:23
+  --> $DIR/thread-local-static.rs:12:23
    |
 LL |     std::mem::swap(x, &mut STATIC_VAR_2)
    |                       ^^^^^^^^^^^^^^^^^ use of mutable static
diff --git a/tests/ui/thread-local/thread-local-static.rs b/tests/ui/thread-local/thread-local-static.rs
index c7fee9e6b4c5a..afaffbb7e9bbf 100644
--- a/tests/ui/thread-local/thread-local-static.rs
+++ b/tests/ui/thread-local/thread-local-static.rs
@@ -1,7 +1,10 @@
 // edition:2018
+// revisions: mir thir
+//thir: -Zthir-unsafeck
 
 #![feature(thread_local)]
 #![feature(const_swap)]
+
 #[thread_local]
 static mut STATIC_VAR_2: [u32; 8] = [4; 8];
 const fn g(x: &mut [u32; 8]) {
diff --git a/tests/ui/thread-local/thread-local-static.thir.stderr b/tests/ui/thread-local/thread-local-static.thir.stderr
new file mode 100644
index 0000000000000..607d7ee902cb6
--- /dev/null
+++ b/tests/ui/thread-local/thread-local-static.thir.stderr
@@ -0,0 +1,44 @@
+error[E0658]: mutable references are not allowed in constant functions
+  --> $DIR/thread-local-static.rs:10:12
+   |
+LL | const fn g(x: &mut [u32; 8]) {
+   |            ^
+   |
+   = 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[E0625]: thread-local statics cannot be accessed at compile-time
+  --> $DIR/thread-local-static.rs:12:28
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                            ^^^^^^^^^^^^
+
+error[E0013]: constant functions cannot refer to statics
+  --> $DIR/thread-local-static.rs:12:28
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                            ^^^^^^^^^^^^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0658]: mutable references are not allowed in constant functions
+  --> $DIR/thread-local-static.rs:12:23
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                       ^^^^^^^^^^^^^^^^^
+   |
+   = 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[E0133]: use of mutable static is unsafe and requires unsafe function or block
+  --> $DIR/thread-local-static.rs:12:23
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                       ^^^^^^^^^^^^^^^^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0013, E0133, E0625, E0658.
+For more information about an error, try `rustc --explain E0013`.
diff --git a/tests/ui/union/union-unsafe.mir.stderr b/tests/ui/union/union-unsafe.mir.stderr
index 544213dbc5543..15f059ffa4875 100644
--- a/tests/ui/union/union-unsafe.mir.stderr
+++ b/tests/ui/union/union-unsafe.mir.stderr
@@ -1,5 +1,5 @@
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:33:5
+  --> $DIR/union-unsafe.rs:34:5
    |
 LL |     *(u.p) = 13;
    |     ^^^^^^^^^^^ access to union field
@@ -7,7 +7,7 @@ LL |     *(u.p) = 13;
    = 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/union-unsafe.rs:46:6
+  --> $DIR/union-unsafe.rs:47:6
    |
 LL |     *u3.a = T::default();
    |      ^^^^ access to union field
@@ -15,7 +15,7 @@ LL |     *u3.a = T::default();
    = 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/union-unsafe.rs:52:6
+  --> $DIR/union-unsafe.rs:53:6
    |
 LL |     *u3.a = T::default();
    |      ^^^^ access to union field
@@ -23,7 +23,7 @@ LL |     *u3.a = T::default();
    = 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/union-unsafe.rs:60:13
+  --> $DIR/union-unsafe.rs:61:13
    |
 LL |     let a = u1.a;
    |             ^^^^ access to union field
@@ -31,7 +31,7 @@ LL |     let a = 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/union-unsafe.rs:63:14
+  --> $DIR/union-unsafe.rs:64:14
    |
 LL |     let U1 { a } = u1;
    |              ^ access to union field
@@ -39,7 +39,7 @@ LL |     let U1 { a } = u1;
    = 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/union-unsafe.rs:64:12
+  --> $DIR/union-unsafe.rs:65:12
    |
 LL |     if let U1 { a: 12 } = u1 {}
    |            ^^^^^^^^^^^^ access to union field
@@ -47,7 +47,15 @@ LL |     if let U1 { a: 12 } = u1 {}
    = 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/union-unsafe.rs:69:6
+  --> $DIR/union-unsafe.rs:66:12
+   |
+LL |     if let Some(U1 { a: 13 }) = Some(u1) {}
+   |            ^^^^^^^^^^^^^^^^^^ 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/union-unsafe.rs:71:6
    |
 LL |     *u2.a = String::from("new");
    |      ^^^^ access to union field
@@ -55,7 +63,7 @@ LL |     *u2.a = String::from("new");
    = 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/union-unsafe.rs:73:6
+  --> $DIR/union-unsafe.rs:75:6
    |
 LL |     *u3.a = 1;
    |      ^^^^ access to union field
@@ -63,13 +71,13 @@ LL |     *u3.a = 1;
    = 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/union-unsafe.rs:77:6
+  --> $DIR/union-unsafe.rs:79:6
    |
 LL |     *u3.a = String::from("new");
    |      ^^^^ access to union field
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/union/union-unsafe.rs b/tests/ui/union/union-unsafe.rs
index 5e1837a901d46..d1465486f7784 100644
--- a/tests/ui/union/union-unsafe.rs
+++ b/tests/ui/union/union-unsafe.rs
@@ -1,30 +1,31 @@
 // revisions: mir thir
 // [thir]compile-flags: -Z thir-unsafeck
 
-use std::mem::ManuallyDrop;
 use std::cell::RefCell;
+use std::mem::ManuallyDrop;
 
 union U1 {
-    a: u8
+    a: u8,
 }
 
 union U2 {
-    a: ManuallyDrop<String>
+    a: ManuallyDrop<String>,
 }
 
 union U3<T> {
-    a: ManuallyDrop<T>
+    a: ManuallyDrop<T>,
 }
 
 union U4<T: Copy> {
-    a: T
+    a: T,
 }
 
 union URef {
     p: &'static mut i32,
 }
 
-union URefCell { // field that does not drop but is not `Copy`, either
+union URefCell {
+    // field that does not drop but is not `Copy`, either
     a: (ManuallyDrop<RefCell<i32>>, i32),
 }
 
@@ -62,6 +63,7 @@ fn main() {
 
     let U1 { a } = u1; //~ ERROR access to union field is unsafe
     if let U1 { a: 12 } = u1 {} //~ ERROR access to union field is unsafe
+    if let Some(U1 { a: 13 }) = Some(u1) {} //~ ERROR access to union field is unsafe
     // let U1 { .. } = u1; // OK
 
     let mut u2 = U2 { a: ManuallyDrop::new(String::from("old")) }; // OK
diff --git a/tests/ui/union/union-unsafe.thir.stderr b/tests/ui/union/union-unsafe.thir.stderr
index f959fe5bdb5c5..9ce835497c519 100644
--- a/tests/ui/union/union-unsafe.thir.stderr
+++ b/tests/ui/union/union-unsafe.thir.stderr
@@ -1,5 +1,5 @@
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:33:6
+  --> $DIR/union-unsafe.rs:34:6
    |
 LL |     *(u.p) = 13;
    |      ^^^^^ access to union field
@@ -7,7 +7,7 @@ LL |     *(u.p) = 13;
    = 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/union-unsafe.rs:46:6
+  --> $DIR/union-unsafe.rs:47:6
    |
 LL |     *u3.a = T::default();
    |      ^^^^ access to union field
@@ -15,7 +15,7 @@ LL |     *u3.a = T::default();
    = 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/union-unsafe.rs:52:6
+  --> $DIR/union-unsafe.rs:53:6
    |
 LL |     *u3.a = T::default();
    |      ^^^^ access to union field
@@ -23,7 +23,7 @@ LL |     *u3.a = T::default();
    = 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/union-unsafe.rs:60:13
+  --> $DIR/union-unsafe.rs:61:13
    |
 LL |     let a = u1.a;
    |             ^^^^ access to union field
@@ -31,7 +31,7 @@ LL |     let a = 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/union-unsafe.rs:63:14
+  --> $DIR/union-unsafe.rs:64:14
    |
 LL |     let U1 { a } = u1;
    |              ^ access to union field
@@ -39,15 +39,23 @@ LL |     let U1 { a } = u1;
    = 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/union-unsafe.rs:64:8
+  --> $DIR/union-unsafe.rs:65:20
    |
 LL |     if let U1 { a: 12 } = u1 {}
-   |        ^^^^^^^^^^^^^^^^^^^^^ access to union field
+   |                    ^^ 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/union-unsafe.rs:69:6
+  --> $DIR/union-unsafe.rs:66:25
+   |
+LL |     if let Some(U1 { a: 13 }) = Some(u1) {}
+   |                         ^^ 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/union-unsafe.rs:71:6
    |
 LL |     *u2.a = String::from("new");
    |      ^^^^ access to union field
@@ -55,7 +63,7 @@ LL |     *u2.a = String::from("new");
    = 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/union-unsafe.rs:73:6
+  --> $DIR/union-unsafe.rs:75:6
    |
 LL |     *u3.a = 1;
    |      ^^^^ access to union field
@@ -63,13 +71,13 @@ LL |     *u3.a = 1;
    = 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/union-unsafe.rs:77:6
+  --> $DIR/union-unsafe.rs:79:6
    |
 LL |     *u3.a = String::from("new");
    |      ^^^^ access to union field
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr
similarity index 80%
rename from tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr
rename to tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr
index fbc621f4d0e37..ea53bf59d3101 100644
--- a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr
+++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr
@@ -1,12 +1,12 @@
 warning: call to unsafe function is unsafe and requires unsafe block (error E0133)
-  --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:12:5
+  --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:13:5
    |
 LL |     unsf();
    |     ^^^^^^ call to unsafe function
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
 note: an unsafe function restricts its caller, but its body is safe by default
-  --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:11:1
+  --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:12:1
    |
 LL | unsafe fn foo() {
    | ^^^^^^^^^^^^^^^
diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs
index a192f3445f73e..1b429955cb035 100644
--- a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs
+++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs
@@ -1,17 +1,21 @@
 // edition: 2024
 // compile-flags: -Zunstable-options
 // check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Zthir-unsafeck
 
 #![crate_type = "lib"]
-
 #![deny(unused_unsafe)]
 
 unsafe fn unsf() {}
 
 unsafe fn foo() {
     unsf();
-    //~^ WARN call to unsafe function is unsafe and requires unsafe block
+    //[mir]~^ WARN call to unsafe function is unsafe and requires unsafe block
+    //[thir]~^^ WARN call to unsafe function `unsf` is unsafe and requires unsafe block
 
     // no unused_unsafe
-    unsafe { unsf(); }
+    unsafe {
+        unsf();
+    }
 }
diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr
new file mode 100644
index 0000000000000..d63843ed2b361
--- /dev/null
+++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr
@@ -0,0 +1,16 @@
+warning: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+  --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:13:5
+   |
+LL |     unsf();
+   |     ^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:12:1
+   |
+LL | unsafe fn foo() {
+   | ^^^^^^^^^^^^^^^
+   = note: `#[warn(unsafe_op_in_unsafe_fn)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr
index 427843f8d45ce..dc6bd72f56c57 100644
--- a/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr
+++ b/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr
@@ -6,6 +6,14 @@ LL |     let y = &mut x.0;
    |
    = note: mutating layout constrained fields cannot statically be checked for valid values
 
-error: aborting due to previous error
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints2.rs:12:25
+   |
+LL |     if let Some(NonZero(ref mut y)) = Some(x) {}
+   |                         ^^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/unsafe/ranged_ints2.rs b/tests/ui/unsafe/ranged_ints2.rs
index 9a6bb18f92664..ad9d598aba2a4 100644
--- a/tests/ui/unsafe/ranged_ints2.rs
+++ b/tests/ui/unsafe/ranged_ints2.rs
@@ -9,4 +9,5 @@ pub(crate) struct NonZero<T>(pub(crate) T);
 fn main() {
     let mut x = unsafe { NonZero(1) };
     let y = &mut x.0; //~ ERROR mutation of layout constrained field is unsafe
+    if let Some(NonZero(ref mut y)) = Some(x) {} //~ ERROR mutation of layout constrained field is unsafe
 }
diff --git a/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr
index 427843f8d45ce..dc6bd72f56c57 100644
--- a/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr
+++ b/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr
@@ -6,6 +6,14 @@ LL |     let y = &mut x.0;
    |
    = note: mutating layout constrained fields cannot statically be checked for valid values
 
-error: aborting due to previous error
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+  --> $DIR/ranged_ints2.rs:12:25
+   |
+LL |     if let Some(NonZero(ref mut y)) = Some(x) {}
+   |                         ^^^^^^^^^ mutation of layout constrained field
+   |
+   = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr
index 4cdd97e5e06aa..ad0621a1d0435 100644
--- a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr
+++ b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr
@@ -5,6 +5,11 @@ LL |     unsf();
    |     ^^^^^^ call to unsafe function
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:11:1
+   |
+LL | unsafe fn deny_level() {
+   | ^^^^^^^^^^^^^^^^^^^^^^
 note: the lint level is defined here
   --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:4:9
    |
@@ -46,6 +51,11 @@ LL |     unsf();
    |     ^^^^^^ call to unsafe function
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:27:1
+   |
+LL | unsafe fn warning_level() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: the lint level is defined here
   --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:8
    |
diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed
similarity index 73%
rename from tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed
rename to tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed
index db1c102210e3b..b59029df6429b 100644
--- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed
+++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed
@@ -1,7 +1,10 @@
 // run-rustfix
 // aux-build:external_unsafe_macro.rs
+// revisions: mir thir
+// [thir]compile-flags: -Zthir-unsafeck
 
 #![deny(unsafe_op_in_unsafe_fn)] //~ NOTE
+#![crate_name = "wrapping_unsafe_block_sugg"]
 
 extern crate external_unsafe_macro;
 
@@ -9,11 +12,13 @@ unsafe fn unsf() {}
 
 pub unsafe fn foo() { unsafe {
     //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
-    unsf(); //~ ERROR call to unsafe function is unsafe
-    //~^ NOTE
+    unsf(); //[mir]~ ERROR call to unsafe function is unsafe
+     //[thir]~^ ERROR call to unsafe function `unsf` is unsafe
+    //~^^ NOTE
     //~| NOTE
-    unsf(); //~ ERROR call to unsafe function is unsafe
-    //~^ NOTE
+    unsf(); //[mir]~ ERROR call to unsafe function is unsafe
+    //[thir]~^ ERROR call to unsafe function `unsf` is unsafe
+    //~^^ NOTE
     //~| NOTE
 }}
 
@@ -39,10 +44,12 @@ pub unsafe fn baz() -> i32 { unsafe {
 }}
 
 macro_rules! unsafe_macro { () => (unsf()) }
-//~^ ERROR call to unsafe function is unsafe
+//[mir]~^ ERROR call to unsafe function is unsafe
+//[thir]~^^ ERROR call to unsafe function `unsf` is unsafe
 //~| NOTE
 //~| NOTE
-//~| ERROR call to unsafe function is unsafe
+//[mir]~| ERROR call to unsafe function is unsafe
+//[thir]~| ERROR call to unsafe function `unsf` is unsafe
 //~| NOTE
 //~| NOTE
 
diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr
similarity index 86%
rename from tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr
rename to tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr
index 43f619c27d274..7a1b83c7367da 100644
--- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr
+++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr
@@ -1,23 +1,23 @@
 error: call to unsafe function is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:12:5
+  --> $DIR/wrapping-unsafe-block-sugg.rs:15:5
    |
 LL |     unsf();
    |     ^^^^^^ call to unsafe function
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
 note: an unsafe function restricts its caller, but its body is safe by default
-  --> $DIR/wrapping-unsafe-block-sugg.rs:10:1
+  --> $DIR/wrapping-unsafe-block-sugg.rs:13:1
    |
 LL | pub unsafe fn foo() {
    | ^^^^^^^^^^^^^^^^^^^
 note: the lint level is defined here
-  --> $DIR/wrapping-unsafe-block-sugg.rs:4:9
+  --> $DIR/wrapping-unsafe-block-sugg.rs:6:9
    |
 LL | #![deny(unsafe_op_in_unsafe_fn)]
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error: call to unsafe function is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:15:5
+  --> $DIR/wrapping-unsafe-block-sugg.rs:19:5
    |
 LL |     unsf();
    |     ^^^^^^ call to unsafe function
@@ -25,20 +25,20 @@ LL |     unsf();
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:22:13
+  --> $DIR/wrapping-unsafe-block-sugg.rs:27:13
    |
 LL |     let y = *x;
    |             ^^ 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
 note: an unsafe function restricts its caller, but its body is safe by default
-  --> $DIR/wrapping-unsafe-block-sugg.rs:20:1
+  --> $DIR/wrapping-unsafe-block-sugg.rs:25:1
    |
 LL | pub unsafe fn bar(x: *const i32) -> i32 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:25:9
+  --> $DIR/wrapping-unsafe-block-sugg.rs:30:9
    |
 LL |     y + *x
    |         ^^ dereference of raw pointer
@@ -46,20 +46,20 @@ LL |     y + *x
    = 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: use of mutable static is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:33:13
+  --> $DIR/wrapping-unsafe-block-sugg.rs:38:13
    |
 LL |     let y = BAZ;
    |             ^^^ use of mutable static
    |
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 note: an unsafe function restricts its caller, but its body is safe by default
-  --> $DIR/wrapping-unsafe-block-sugg.rs:31:1
+  --> $DIR/wrapping-unsafe-block-sugg.rs:36:1
    |
 LL | pub unsafe fn baz() -> i32 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of mutable static is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:36:9
+  --> $DIR/wrapping-unsafe-block-sugg.rs:41:9
    |
 LL |     y + BAZ
    |         ^^^ use of mutable static
@@ -67,7 +67,7 @@ LL |     y + BAZ
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 
 error: call to unsafe function is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:41:36
+  --> $DIR/wrapping-unsafe-block-sugg.rs:46:36
    |
 LL | macro_rules! unsafe_macro { () => (unsf()) }
    |                                    ^^^^^^ call to unsafe function
@@ -77,14 +77,14 @@ LL |     unsafe_macro!();
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
 note: an unsafe function restricts its caller, but its body is safe by default
-  --> $DIR/wrapping-unsafe-block-sugg.rs:49:1
+  --> $DIR/wrapping-unsafe-block-sugg.rs:56:1
    |
 LL | pub unsafe fn unsafe_in_macro() {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: call to unsafe function is unsafe and requires unsafe block (error E0133)
-  --> $DIR/wrapping-unsafe-block-sugg.rs:41:36
+  --> $DIR/wrapping-unsafe-block-sugg.rs:46:36
    |
 LL | macro_rules! unsafe_macro { () => (unsf()) }
    |                                    ^^^^^^ call to unsafe function
diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs
index 9c6be45896e25..3629b8a1beb5f 100644
--- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs
+++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs
@@ -1,7 +1,10 @@
 // run-rustfix
 // aux-build:external_unsafe_macro.rs
+// revisions: mir thir
+// [thir]compile-flags: -Zthir-unsafeck
 
 #![deny(unsafe_op_in_unsafe_fn)] //~ NOTE
+#![crate_name = "wrapping_unsafe_block_sugg"]
 
 extern crate external_unsafe_macro;
 
@@ -9,11 +12,13 @@ unsafe fn unsf() {}
 
 pub unsafe fn foo() {
     //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
-    unsf(); //~ ERROR call to unsafe function is unsafe
-    //~^ NOTE
+    unsf(); //[mir]~ ERROR call to unsafe function is unsafe
+     //[thir]~^ ERROR call to unsafe function `unsf` is unsafe
+    //~^^ NOTE
     //~| NOTE
-    unsf(); //~ ERROR call to unsafe function is unsafe
-    //~^ NOTE
+    unsf(); //[mir]~ ERROR call to unsafe function is unsafe
+    //[thir]~^ ERROR call to unsafe function `unsf` is unsafe
+    //~^^ NOTE
     //~| NOTE
 }
 
@@ -39,10 +44,12 @@ pub unsafe fn baz() -> i32 {
 }
 
 macro_rules! unsafe_macro { () => (unsf()) }
-//~^ ERROR call to unsafe function is unsafe
+//[mir]~^ ERROR call to unsafe function is unsafe
+//[thir]~^^ ERROR call to unsafe function `unsf` is unsafe
 //~| NOTE
 //~| NOTE
-//~| ERROR call to unsafe function is unsafe
+//[mir]~| ERROR call to unsafe function is unsafe
+//[thir]~| ERROR call to unsafe function `unsf` is unsafe
 //~| NOTE
 //~| NOTE
 
diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed
new file mode 100644
index 0000000000000..b59029df6429b
--- /dev/null
+++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed
@@ -0,0 +1,73 @@
+// run-rustfix
+// aux-build:external_unsafe_macro.rs
+// revisions: mir thir
+// [thir]compile-flags: -Zthir-unsafeck
+
+#![deny(unsafe_op_in_unsafe_fn)] //~ NOTE
+#![crate_name = "wrapping_unsafe_block_sugg"]
+
+extern crate external_unsafe_macro;
+
+unsafe fn unsf() {}
+
+pub unsafe fn foo() { unsafe {
+    //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
+    unsf(); //[mir]~ ERROR call to unsafe function is unsafe
+     //[thir]~^ ERROR call to unsafe function `unsf` is unsafe
+    //~^^ NOTE
+    //~| NOTE
+    unsf(); //[mir]~ ERROR call to unsafe function is unsafe
+    //[thir]~^ ERROR call to unsafe function `unsf` is unsafe
+    //~^^ NOTE
+    //~| NOTE
+}}
+
+pub unsafe fn bar(x: *const i32) -> i32 { unsafe {
+    //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
+    let y = *x; //~ ERROR dereference of raw pointer is unsafe and requires unsafe block
+    //~^ NOTE
+    //~| NOTE
+    y + *x //~ ERROR dereference of raw pointer is unsafe and requires unsafe block
+    //~^ NOTE
+    //~| NOTE
+}}
+
+static mut BAZ: i32 = 0;
+pub unsafe fn baz() -> i32 { unsafe {
+    //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
+    let y = BAZ; //~ ERROR use of mutable static is unsafe and requires unsafe block
+    //~^ NOTE
+    //~| NOTE
+    y + BAZ //~ ERROR use of mutable static is unsafe and requires unsafe block
+    //~^ NOTE
+    //~| NOTE
+}}
+
+macro_rules! unsafe_macro { () => (unsf()) }
+//[mir]~^ ERROR call to unsafe function is unsafe
+//[thir]~^^ ERROR call to unsafe function `unsf` is unsafe
+//~| NOTE
+//~| NOTE
+//[mir]~| ERROR call to unsafe function is unsafe
+//[thir]~| ERROR call to unsafe function `unsf` is unsafe
+//~| NOTE
+//~| NOTE
+
+pub unsafe fn unsafe_in_macro() { unsafe {
+    //~^ NOTE an unsafe function restricts its caller, but its body is safe by default
+    unsafe_macro!();
+    //~^ NOTE
+    //~| NOTE
+    unsafe_macro!();
+    //~^ NOTE
+    //~| NOTE
+}}
+
+pub unsafe fn unsafe_in_external_macro() {
+    // FIXME: https://github.com/rust-lang/rust/issues/112504
+    // FIXME: ~^ NOTE an unsafe function restricts its caller, but its body is safe by default
+    external_unsafe_macro::unsafe_macro!();
+    external_unsafe_macro::unsafe_macro!();
+}
+
+fn main() {}
diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.stderr b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.stderr
new file mode 100644
index 0000000000000..b1fb35f85a606
--- /dev/null
+++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.stderr
@@ -0,0 +1,99 @@
+error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+  --> $DIR/wrapping-unsafe-block-sugg.rs:15:5
+   |
+LL |     unsf();
+   |     ^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/wrapping-unsafe-block-sugg.rs:13:1
+   |
+LL | pub unsafe fn foo() {
+   | ^^^^^^^^^^^^^^^^^^^
+note: the lint level is defined here
+  --> $DIR/wrapping-unsafe-block-sugg.rs:6:9
+   |
+LL | #![deny(unsafe_op_in_unsafe_fn)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+  --> $DIR/wrapping-unsafe-block-sugg.rs:19:5
+   |
+LL |     unsf();
+   |     ^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+  --> $DIR/wrapping-unsafe-block-sugg.rs:27:13
+   |
+LL |     let y = *x;
+   |             ^^ 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
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/wrapping-unsafe-block-sugg.rs:25:1
+   |
+LL | pub unsafe fn bar(x: *const i32) -> i32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+  --> $DIR/wrapping-unsafe-block-sugg.rs:30:9
+   |
+LL |     y + *x
+   |         ^^ 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: use of mutable static is unsafe and requires unsafe block (error E0133)
+  --> $DIR/wrapping-unsafe-block-sugg.rs:38:13
+   |
+LL |     let y = BAZ;
+   |             ^^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/wrapping-unsafe-block-sugg.rs:36:1
+   |
+LL | pub unsafe fn baz() -> i32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: use of mutable static is unsafe and requires unsafe block (error E0133)
+  --> $DIR/wrapping-unsafe-block-sugg.rs:41:9
+   |
+LL |     y + BAZ
+   |         ^^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+  --> $DIR/wrapping-unsafe-block-sugg.rs:46:36
+   |
+LL | macro_rules! unsafe_macro { () => (unsf()) }
+   |                                    ^^^^^^ call to unsafe function
+...
+LL |     unsafe_macro!();
+   |     --------------- in this macro invocation
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+note: an unsafe function restricts its caller, but its body is safe by default
+  --> $DIR/wrapping-unsafe-block-sugg.rs:56:1
+   |
+LL | pub unsafe fn unsafe_in_macro() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+  --> $DIR/wrapping-unsafe-block-sugg.rs:46:36
+   |
+LL | macro_rules! unsafe_macro { () => (unsf()) }
+   |                                    ^^^^^^ call to unsafe function
+...
+LL |     unsafe_macro!();
+   |     --------------- in this macro invocation
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 8 previous errors
+