about summary refs log tree commit diff
path: root/compiler/rustc_mir_transform/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_transform/src')
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs26
-rw-r--r--compiler/rustc_mir_transform/src/errors.rs19
2 files changed, 34 insertions, 11 deletions
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index 069514d8a3b..fd8e02ebeab 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -527,6 +527,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     }
 
     let UnsafetyCheckResult { violations, unused_unsafes, .. } = tcx.unsafety_check_result(def_id);
+    // Only suggest wrapping the entire function body in an unsafe block once
+    let mut suggest_unsafe_block = true;
 
     for &UnsafetyViolation { source_info, lint_root, kind, details } in violations.iter() {
         let details = errors::RequiresUnsafeDetail { violation: details, span: source_info.span };
@@ -561,12 +563,24 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
                     op_in_unsafe_fn_allowed,
                 });
             }
-            UnsafetyViolationKind::UnsafeFn => tcx.emit_spanned_lint(
-                UNSAFE_OP_IN_UNSAFE_FN,
-                lint_root,
-                source_info.span,
-                errors::UnsafeOpInUnsafeFn { details },
-            ),
+            UnsafetyViolationKind::UnsafeFn => {
+                tcx.emit_spanned_lint(
+                    UNSAFE_OP_IN_UNSAFE_FN,
+                    lint_root,
+                    source_info.span,
+                    errors::UnsafeOpInUnsafeFn {
+                        details,
+                        suggest_unsafe_block: suggest_unsafe_block.then(|| {
+                            let body = tcx.hir().body_owned_by(def_id);
+                            let body_span = tcx.hir().body(body).value.span;
+                            let start = tcx.sess.source_map().start_point(body_span).shrink_to_hi();
+                            let end = tcx.sess.source_map().end_point(body_span).shrink_to_lo();
+                            (start, end)
+                        }),
+                    },
+                );
+                suggest_unsafe_block = false;
+            }
         }
     }
 
diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs
index 602e40d5131..b546e34f037 100644
--- a/compiler/rustc_mir_transform/src/errors.rs
+++ b/compiler/rustc_mir_transform/src/errors.rs
@@ -1,5 +1,6 @@
 use rustc_errors::{
-    DecorateLint, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Handler, IntoDiagnostic,
+    Applicability, DecorateLint, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Handler,
+    IntoDiagnostic,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::mir::{AssertKind, UnsafetyViolationDetails};
@@ -130,6 +131,7 @@ impl RequiresUnsafeDetail {
 
 pub(crate) struct UnsafeOpInUnsafeFn {
     pub details: RequiresUnsafeDetail,
+    pub suggest_unsafe_block: Option<(Span, Span)>,
 }
 
 impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn {
@@ -138,13 +140,20 @@ impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn {
         self,
         diag: &'b mut DiagnosticBuilder<'a, ()>,
     ) -> &'b mut DiagnosticBuilder<'a, ()> {
-        let desc = diag
-            .handler()
-            .expect("lint should not yet be emitted")
-            .eagerly_translate_to_string(self.details.label(), [].into_iter());
+        let handler = diag.handler().expect("lint should not yet be emitted");
+        let desc = handler.eagerly_translate_to_string(self.details.label(), [].into_iter());
         diag.set_arg("details", desc);
         diag.span_label(self.details.span, self.details.label());
         diag.note(self.details.note());
+
+        if let Some((start, end)) = self.suggest_unsafe_block {
+            diag.multipart_suggestion_verbose(
+                crate::fluent_generated::mir_transform_suggestion,
+                vec![(start, " unsafe {".into()), (end, "}".into())],
+                Applicability::MaybeIncorrect,
+            );
+        }
+
         diag
     }