Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix diagnostic for qualifier in extern block #123397

Merged
merged 1 commit into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2483,6 +2483,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 { .. })
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
29 changes: 24 additions & 5 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
}

Expand Down Expand Up @@ -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 {
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_ast_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
9 changes: 2 additions & 7 deletions tests/ui/extern/issue-95829.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

5 changes: 4 additions & 1 deletion tests/ui/parser/fn-header-semantic-fail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`
}
}
68 changes: 35 additions & 33 deletions tests/ui/parser/fn-header-semantic-fail.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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`.
1 change: 1 addition & 0 deletions tests/ui/parser/no-const-fn-in-extern-block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
27 changes: 13 additions & 14 deletions tests/ui/parser/no-const-fn-in-extern-block.stderr
Original file line number Diff line number Diff line change
@@ -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

9 changes: 2 additions & 7 deletions tests/ui/parser/unsafe-foreign-mod-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Loading