about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast/src/ast.rs8
-rw-r--r--compiler/rustc_ast_passes/messages.ftl2
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs29
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs3
-rw-r--r--tests/ui/extern/issue-95829.stderr9
-rw-r--r--tests/ui/parser/fn-header-semantic-fail.rs5
-rw-r--r--tests/ui/parser/fn-header-semantic-fail.stderr68
-rw-r--r--tests/ui/parser/no-const-fn-in-extern-block.rs1
-rw-r--r--tests/ui/parser/no-const-fn-in-extern-block.stderr27
-rw-r--r--tests/ui/parser/unsafe-foreign-mod-2.stderr9
10 files changed, 91 insertions, 70 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index c10a6258d39..e29ef591bcb 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2484,6 +2484,14 @@ pub enum CoroutineKind {
 }
 
 impl CoroutineKind {
+    pub fn span(self) -> Span {
+        match self {
+            CoroutineKind::Async { span, .. } => span,
+            CoroutineKind::Gen { span, .. } => span,
+            CoroutineKind::AsyncGen { span, .. } => span,
+        }
+    }
+
     pub fn is_async(self) -> bool {
         matches!(self, CoroutineKind::Async { .. })
     }
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 28a13d275a5..ac3799e7a05 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -68,7 +68,7 @@ ast_passes_extern_block_suggestion = if you meant to declare an externally defin
 
 ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have qualifiers
     .label = in this `extern` block
-    .suggestion = remove the qualifiers
+    .suggestion = remove this qualifier
 
 ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers
     .label = in this `extern` block
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 80c62d3fecf..093a985495c 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -514,13 +514,32 @@ impl<'a> AstValidator<'a> {
     }
 
     /// An `fn` in `extern { ... }` cannot have qualifiers, e.g. `async fn`.
-    fn check_foreign_fn_headerless(&self, ident: Ident, span: Span, header: FnHeader) {
-        if header.has_qualifiers() {
+    fn check_foreign_fn_headerless(
+        &self,
+        // Deconstruct to ensure exhaustiveness
+        FnHeader { unsafety, coroutine_kind, constness, ext }: FnHeader,
+    ) {
+        let report_err = |span| {
             self.dcx().emit_err(errors::FnQualifierInExtern {
-                span: ident.span,
+                span: span,
                 block: self.current_extern_span(),
-                sugg_span: span.until(ident.span.shrink_to_lo()),
             });
+        };
+        match unsafety {
+            Unsafe::Yes(span) => report_err(span),
+            Unsafe::No => (),
+        }
+        match coroutine_kind {
+            Some(knd) => report_err(knd.span()),
+            None => (),
+        }
+        match constness {
+            Const::Yes(span) => report_err(span),
+            Const::No => (),
+        }
+        match ext {
+            Extern::None => (),
+            Extern::Implicit(span) | Extern::Explicit(_, span) => report_err(span),
         }
     }
 
@@ -1145,7 +1164,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => {
                 self.check_defaultness(fi.span, *defaultness);
                 self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
-                self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
+                self.check_foreign_fn_headerless(sig.header);
                 self.check_foreign_item_ascii_only(fi.ident);
             }
             ForeignItemKind::TyAlias(box TyAlias {
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 9e8c1d7f5fd..8ae9f7d3966 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -270,11 +270,10 @@ pub struct FnBodyInExtern {
 #[diag(ast_passes_extern_fn_qualifiers)]
 pub struct FnQualifierInExtern {
     #[primary_span]
+    #[suggestion(code = "", applicability = "maybe-incorrect")]
     pub span: Span,
     #[label]
     pub block: Span,
-    #[suggestion(code = "fn ", applicability = "maybe-incorrect", style = "verbose")]
-    pub sugg_span: Span,
 }
 
 #[derive(Diagnostic)]
diff --git a/tests/ui/extern/issue-95829.stderr b/tests/ui/extern/issue-95829.stderr
index b902f0ef8f5..16504d1f0c9 100644
--- a/tests/ui/extern/issue-95829.stderr
+++ b/tests/ui/extern/issue-95829.stderr
@@ -16,17 +16,12 @@ LL | |     }
    = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/issue-95829.rs:4:14
+  --> $DIR/issue-95829.rs:4:5
    |
 LL | extern {
    | ------ in this `extern` block
 LL |     async fn L() {
-   |              ^
-   |
-help: remove the qualifiers
-   |
-LL |     fn L() {
-   |     ~~
+   |     ^^^^^ help: remove this qualifier
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/fn-header-semantic-fail.rs b/tests/ui/parser/fn-header-semantic-fail.rs
index 25d7c3f35fc..6ed173b6854 100644
--- a/tests/ui/parser/fn-header-semantic-fail.rs
+++ b/tests/ui/parser/fn-header-semantic-fail.rs
@@ -48,6 +48,9 @@ fn main() {
         const fn fe3(); //~ ERROR functions in `extern` blocks cannot have qualifiers
         extern "C" fn fe4(); //~ ERROR functions in `extern` blocks cannot have qualifiers
         const async unsafe extern "C" fn fe5(); //~ ERROR functions in `extern` blocks
-        //~^ ERROR functions cannot be both `const` and `async`
+        //~| ERROR functions in `extern` blocks
+        //~| ERROR functions in `extern` blocks
+        //~| ERROR functions in `extern` blocks
+        //~| ERROR functions cannot be both `const` and `async`
     }
 }
diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr
index 696d8e01b63..cfc54839eb7 100644
--- a/tests/ui/parser/fn-header-semantic-fail.stderr
+++ b/tests/ui/parser/fn-header-semantic-fail.stderr
@@ -71,73 +71,75 @@ LL |         const async unsafe extern "C" fn fi5() {}
    |         `const` because of this
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:46:18
+  --> $DIR/fn-header-semantic-fail.rs:46:9
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
 LL |         async fn fe1();
-   |                  ^^^
-   |
-help: remove the qualifiers
-   |
-LL |         fn fe1();
-   |         ~~
+   |         ^^^^^ help: remove this qualifier
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:47:19
+  --> $DIR/fn-header-semantic-fail.rs:47:9
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
 LL |         async fn fe1();
 LL |         unsafe fn fe2();
-   |                   ^^^
-   |
-help: remove the qualifiers
-   |
-LL |         fn fe2();
-   |         ~~
+   |         ^^^^^^ help: remove this qualifier
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:48:18
+  --> $DIR/fn-header-semantic-fail.rs:48:9
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
 ...
 LL |         const fn fe3();
-   |                  ^^^
-   |
-help: remove the qualifiers
-   |
-LL |         fn fe3();
-   |         ~~
+   |         ^^^^^ help: remove this qualifier
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:49:23
+  --> $DIR/fn-header-semantic-fail.rs:49:9
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
 ...
 LL |         extern "C" fn fe4();
-   |                       ^^^
-   |
-help: remove the qualifiers
+   |         ^^^^^^^^^^ help: remove this qualifier
+
+error: functions in `extern` blocks cannot have qualifiers
+  --> $DIR/fn-header-semantic-fail.rs:50:21
    |
-LL |         fn fe4();
-   |         ~~
+LL |     extern "C" {
+   |     ---------- in this `extern` block
+...
+LL |         const async unsafe extern "C" fn fe5();
+   |                     ^^^^^^ help: remove this qualifier
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/fn-header-semantic-fail.rs:50:42
+  --> $DIR/fn-header-semantic-fail.rs:50:15
    |
 LL |     extern "C" {
    |     ---------- in this `extern` block
 ...
 LL |         const async unsafe extern "C" fn fe5();
-   |                                          ^^^
+   |               ^^^^^ help: remove this qualifier
+
+error: functions in `extern` blocks cannot have qualifiers
+  --> $DIR/fn-header-semantic-fail.rs:50:9
    |
-help: remove the qualifiers
+LL |     extern "C" {
+   |     ---------- in this `extern` block
+...
+LL |         const async unsafe extern "C" fn fe5();
+   |         ^^^^^ help: remove this qualifier
+
+error: functions in `extern` blocks cannot have qualifiers
+  --> $DIR/fn-header-semantic-fail.rs:50:28
    |
-LL |         fn fe5();
-   |         ~~
+LL |     extern "C" {
+   |     ---------- in this `extern` block
+...
+LL |         const async unsafe extern "C" fn fe5();
+   |                            ^^^^^^^^^^ help: remove this qualifier
 
 error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:50:9
@@ -148,6 +150,6 @@ LL |         const async unsafe extern "C" fn fe5();
    |         |     `async` because of this
    |         `const` because of this
 
-error: aborting due to 14 previous errors
+error: aborting due to 17 previous errors
 
 For more information about this error, try `rustc --explain E0379`.
diff --git a/tests/ui/parser/no-const-fn-in-extern-block.rs b/tests/ui/parser/no-const-fn-in-extern-block.rs
index 1993124edc3..d6c578681cc 100644
--- a/tests/ui/parser/no-const-fn-in-extern-block.rs
+++ b/tests/ui/parser/no-const-fn-in-extern-block.rs
@@ -3,6 +3,7 @@ extern "C" {
     //~^ ERROR functions in `extern` blocks cannot have qualifiers
     const unsafe fn bar();
     //~^ ERROR functions in `extern` blocks cannot have qualifiers
+    //~| ERROR functions in `extern` blocks cannot have qualifiers
 }
 
 fn main() {}
diff --git a/tests/ui/parser/no-const-fn-in-extern-block.stderr b/tests/ui/parser/no-const-fn-in-extern-block.stderr
index 4ac0e265501..948ce669112 100644
--- a/tests/ui/parser/no-const-fn-in-extern-block.stderr
+++ b/tests/ui/parser/no-const-fn-in-extern-block.stderr
@@ -1,29 +1,28 @@
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/no-const-fn-in-extern-block.rs:2:14
+  --> $DIR/no-const-fn-in-extern-block.rs:2:5
    |
 LL | extern "C" {
    | ---------- in this `extern` block
 LL |     const fn foo();
-   |              ^^^
-   |
-help: remove the qualifiers
-   |
-LL |     fn foo();
-   |     ~~
+   |     ^^^^^ help: remove this qualifier
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/no-const-fn-in-extern-block.rs:4:21
+  --> $DIR/no-const-fn-in-extern-block.rs:4:11
    |
 LL | extern "C" {
    | ---------- in this `extern` block
 ...
 LL |     const unsafe fn bar();
-   |                     ^^^
-   |
-help: remove the qualifiers
+   |           ^^^^^^ help: remove this qualifier
+
+error: functions in `extern` blocks cannot have qualifiers
+  --> $DIR/no-const-fn-in-extern-block.rs:4:5
    |
-LL |     fn bar();
-   |     ~~
+LL | extern "C" {
+   | ---------- in this `extern` block
+...
+LL |     const unsafe fn bar();
+   |     ^^^^^ help: remove this qualifier
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/parser/unsafe-foreign-mod-2.stderr b/tests/ui/parser/unsafe-foreign-mod-2.stderr
index 7cc2de141ae..fc05184f018 100644
--- a/tests/ui/parser/unsafe-foreign-mod-2.stderr
+++ b/tests/ui/parser/unsafe-foreign-mod-2.stderr
@@ -11,18 +11,13 @@ LL | extern "C" unsafe {
    |            ^^^^^^
 
 error: functions in `extern` blocks cannot have qualifiers
-  --> $DIR/unsafe-foreign-mod-2.rs:4:15
+  --> $DIR/unsafe-foreign-mod-2.rs:4:5
    |
 LL | extern "C" unsafe {
    | ----------------- in this `extern` block
 ...
 LL |     unsafe fn foo();
-   |               ^^^
-   |
-help: remove the qualifiers
-   |
-LL |     fn foo();
-   |     ~~
+   |     ^^^^^^ help: remove this qualifier
 
 error: aborting due to 3 previous errors