about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_passes/messages.ftl2
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs19
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs7
-rw-r--r--compiler/rustc_lint/messages.ftl1
-rw-r--r--compiler/rustc_lint/src/context/diagnostics.rs4
-rw-r--r--compiler/rustc_lint/src/lints.rs5
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs8
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs4
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr4
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs2
10 files changed, 40 insertions, 16 deletions
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index b90b502c22b..9a8689e27c0 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -177,6 +177,8 @@ ast_passes_match_arm_with_no_body =
     `match` arm with no body
     .suggestion = add a body after the pattern
 
+ast_passes_missing_unsafe_on_extern = extern blocks must be unsafe
+
 ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
     .help = consider using the `#[path]` attribute to specify filesystem path
 
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index dc554ba04df..0fbb288cc96 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1044,12 +1044,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
 
                     if this.features.unsafe_extern_blocks {
                         if &Safety::Default == safety {
-                            this.lint_buffer.buffer_lint(
-                                MISSING_UNSAFE_ON_EXTERN,
-                                item.id,
-                                item.span,
-                                BuiltinLintDiag::MissingUnsafeOnExtern,
-                            );
+                            if item.span.at_least_rust_2024() {
+                                this.dcx()
+                                    .emit_err(errors::MissingUnsafeOnExtern { span: item.span });
+                            } else {
+                                this.lint_buffer.buffer_lint(
+                                    MISSING_UNSAFE_ON_EXTERN,
+                                    item.id,
+                                    item.span,
+                                    BuiltinLintDiag::MissingUnsafeOnExtern {
+                                        suggestion: item.span.shrink_to_lo(),
+                                    },
+                                );
+                            }
                         }
                     } else if let &Safety::Unsafe(span) = safety {
                         this.dcx().emit_err(errors::UnsafeItem { span, kind: "extern block" });
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 05e99a3d636..260c182bd9e 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -495,6 +495,13 @@ pub struct UnsafeItem {
 }
 
 #[derive(Diagnostic)]
+#[diag(ast_passes_missing_unsafe_on_extern)]
+pub struct MissingUnsafeOnExtern {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(ast_passes_fieldless_union)]
 pub struct FieldlessUnion {
     #[primary_span]
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index bb6ad7c945b..522f2f84cca 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -463,6 +463,7 @@ lint_metavariable_wrong_operator = meta-variable repeats with different Kleene o
 lint_missing_fragment_specifier = missing fragment specifier
 
 lint_missing_unsafe_on_extern = extern blocks should be unsafe
+    .suggestion = needs `unsafe` before the extern keyword
 
 lint_mixed_script_confusables =
     the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index f824e02dcf9..c38804e7714 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -205,8 +205,8 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
             };
             lints::DeprecatedWhereClauseLocation { suggestion }.decorate_lint(diag);
         }
-        BuiltinLintDiag::MissingUnsafeOnExtern => {
-            lints::MissingUnsafeOnExtern.decorate_lint(diag);
+        BuiltinLintDiag::MissingUnsafeOnExtern { suggestion } => {
+            lints::MissingUnsafeOnExtern { suggestion }.decorate_lint(diag);
         }
         BuiltinLintDiag::SingleUseLifetime {
             param_span,
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 01b455c588b..985b66a54e1 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -2740,7 +2740,10 @@ pub enum DeprecatedWhereClauseLocationSugg {
 
 #[derive(LintDiagnostic)]
 #[diag(lint_missing_unsafe_on_extern)]
-pub struct MissingUnsafeOnExtern;
+pub struct MissingUnsafeOnExtern {
+    #[suggestion(code = "unsafe ", applicability = "machine-applicable")]
+    pub suggestion: Span,
+}
 
 #[derive(LintDiagnostic)]
 #[diag(lint_single_use_lifetime)]
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index ec124c3224c..7082a068c48 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -4858,8 +4858,9 @@ declare_lint! {
     ///
     /// ### Example
     ///
-    /// ```rust,edition2024,ignore
+    /// ```rust
     /// #![feature(unsafe_extern_blocks)]
+    /// #![warn(missing_unsafe_on_extern)]
     /// #![allow(dead_code)]
     ///
     /// extern "C" {
@@ -4883,5 +4884,8 @@ declare_lint! {
     pub MISSING_UNSAFE_ON_EXTERN,
     Allow,
     "detects missing unsafe keyword on extern declarations",
-    @edition Edition2024 => Deny;
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
+        reference: "issue #123743 <https://github.com/rust-lang/rust/issues/123743>",
+    };
 }
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 0f13046923e..67e1bfee620 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -630,7 +630,9 @@ pub enum BuiltinLintDiag {
     UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
     UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
     DeprecatedWhereclauseLocation(Span, Option<(Span, String)>),
-    MissingUnsafeOnExtern,
+    MissingUnsafeOnExtern {
+        suggestion: Span,
+    },
     SingleUseLifetime {
         /// Span of the parameter which declares this lifetime.
         param_span: Span,
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr
index 8e1ec814635..d456cfc6829 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr
@@ -1,4 +1,4 @@
-error: extern blocks should be unsafe
+error: extern blocks must be unsafe
   --> $DIR/extern-items.rs:9:1
    |
 LL | / extern "C" {
@@ -7,8 +7,6 @@ LL | |     static TEST1: i32;
 LL | |     fn test1(i: i32);
 LL | | }
    | |_^
-   |
-   = note: `#[deny(missing_unsafe_on_extern)]` on by default
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs
index 905d1434155..16fa1bbb8a4 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs
@@ -7,7 +7,7 @@
 #![feature(unsafe_extern_blocks)]
 
 extern "C" {
-    //[edition2024]~^ ERROR extern blocks should be unsafe
+    //[edition2024]~^ ERROR extern blocks must be unsafe
     static TEST1: i32;
     fn test1(i: i32);
 }