Skip to content

Commit 9835a35

Browse files
committed
Fix diagnostic for qualifier in extern block
Closes: rust-lang#123306
1 parent 45796d1 commit 9835a35

File tree

8 files changed

+136
-33
lines changed

8 files changed

+136
-33
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2483,6 +2483,14 @@ pub enum CoroutineKind {
24832483
}
24842484

24852485
impl CoroutineKind {
2486+
pub fn span(self) -> Span {
2487+
match self {
2488+
CoroutineKind::Async { span, .. } => span,
2489+
CoroutineKind::Gen { span, .. } => span,
2490+
CoroutineKind::AsyncGen { span, .. } => span,
2491+
}
2492+
}
2493+
24862494
pub fn is_async(self) -> bool {
24872495
matches!(self, CoroutineKind::Async { .. })
24882496
}

compiler/rustc_ast_passes/messages.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ ast_passes_extern_block_suggestion = if you meant to declare an externally defin
6868
6969
ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have qualifiers
7070
.label = in this `extern` block
71-
.suggestion = remove the qualifiers
71+
.suggestion = remove this qualifier
7272
7373
ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers
7474
.label = in this `extern` block

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -514,13 +514,49 @@ impl<'a> AstValidator<'a> {
514514
}
515515

516516
/// An `fn` in `extern { ... }` cannot have qualifiers, e.g. `async fn`.
517-
fn check_foreign_fn_headerless(&self, ident: Ident, span: Span, header: FnHeader) {
518-
if header.has_qualifiers() {
519-
self.dcx().emit_err(errors::FnQualifierInExtern {
520-
span: ident.span,
521-
block: self.current_extern_span(),
522-
sugg_span: span.until(ident.span.shrink_to_lo()),
523-
});
517+
fn check_foreign_fn_headerless(&self, header: FnHeader) {
518+
let FnHeader { unsafety, coroutine_kind, constness, ext } = header;
519+
match unsafety {
520+
Unsafe::Yes(span) => {
521+
self.dcx().emit_err(errors::FnQualifierInExtern {
522+
span: span,
523+
block: self.current_extern_span(),
524+
});
525+
}
526+
Unsafe::No => (),
527+
}
528+
match coroutine_kind {
529+
Some(knd) => {
530+
self.dcx().emit_err(errors::FnQualifierInExtern {
531+
span: knd.span(),
532+
block: self.current_extern_span(),
533+
});
534+
}
535+
None => (),
536+
}
537+
match constness {
538+
Const::Yes(span) => {
539+
self.dcx().emit_err(errors::FnQualifierInExtern {
540+
span,
541+
block: self.current_extern_span(),
542+
});
543+
}
544+
Const::No => (),
545+
}
546+
match ext {
547+
Extern::None => (),
548+
Extern::Implicit(span) => {
549+
self.dcx().emit_err(errors::FnQualifierInExtern {
550+
span,
551+
block: self.current_extern_span(),
552+
});
553+
}
554+
Extern::Explicit(_, span) => {
555+
self.dcx().emit_err(errors::FnQualifierInExtern {
556+
span,
557+
block: self.current_extern_span(),
558+
});
559+
}
524560
}
525561
}
526562

@@ -1145,7 +1181,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11451181
ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => {
11461182
self.check_defaultness(fi.span, *defaultness);
11471183
self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
1148-
self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
1184+
self.check_foreign_fn_headerless(sig.header);
11491185
self.check_foreign_item_ascii_only(fi.ident);
11501186
}
11511187
ForeignItemKind::TyAlias(box TyAlias {

compiler/rustc_ast_passes/src/errors.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,15 +266,14 @@ pub struct FnBodyInExtern {
266266
pub block: Span,
267267
}
268268

269-
#[derive(Diagnostic)]
269+
#[derive(Diagnostic, Debug)]
270270
#[diag(ast_passes_extern_fn_qualifiers)]
271271
pub struct FnQualifierInExtern {
272272
#[primary_span]
273+
#[suggestion(code = "", applicability = "maybe-incorrect")]
273274
pub span: Span,
274275
#[label]
275276
pub block: Span,
276-
#[suggestion(code = "fn ", applicability = "maybe-incorrect", style = "verbose")]
277-
pub sugg_span: Span,
278277
}
279278

280279
#[derive(Diagnostic)]

tests/ui/extern/extern-headerless.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//@ edition:2018
2+
3+
extern "C" {
4+
const fn a();
5+
//~^ ERROR functions in `extern` blocks cannot have qualifiers
6+
7+
unsafe fn b();
8+
//~^ ERROR functions in `extern` blocks cannot have qualifiers
9+
10+
async fn c();
11+
//~^ ERROR functions in `extern` blocks cannot have qualifiers
12+
13+
extern fn d();
14+
//~^ ERROR functions in `extern` blocks cannot have qualifiers
15+
16+
extern "C" fn e();
17+
//~^ ERROR functions in `extern` blocks cannot have qualifiers
18+
}
19+
20+
pub fn main() {}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
error: functions in `extern` blocks cannot have qualifiers
2+
--> $DIR/extern-headerless.rs:4:5
3+
|
4+
LL | extern "C" {
5+
| ---------- in this `extern` block
6+
LL | const fn a();
7+
| ^^^^^ help: remove this qualifier
8+
9+
error: functions in `extern` blocks cannot have qualifiers
10+
--> $DIR/extern-headerless.rs:7:5
11+
|
12+
LL | extern "C" {
13+
| ---------- in this `extern` block
14+
...
15+
LL | unsafe fn b();
16+
| ^^^^^^ help: remove this qualifier
17+
18+
error: functions in `extern` blocks cannot have qualifiers
19+
--> $DIR/extern-headerless.rs:10:5
20+
|
21+
LL | extern "C" {
22+
| ---------- in this `extern` block
23+
...
24+
LL | async fn c();
25+
| ^^^^^ help: remove this qualifier
26+
27+
error: functions in `extern` blocks cannot have qualifiers
28+
--> $DIR/extern-headerless.rs:13:5
29+
|
30+
LL | extern "C" {
31+
| ---------- in this `extern` block
32+
...
33+
LL | extern fn d();
34+
| ^^^^^^ help: remove this qualifier
35+
36+
error: functions in `extern` blocks cannot have qualifiers
37+
--> $DIR/extern-headerless.rs:16:5
38+
|
39+
LL | extern "C" {
40+
| ---------- in this `extern` block
41+
...
42+
LL | extern "C" fn e();
43+
| ^^^^^^^^^^ help: remove this qualifier
44+
45+
error: aborting due to 5 previous errors
46+

tests/ui/extern/issue-95829.stderr

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,12 @@ LL | | }
1616
= note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
1717

1818
error: functions in `extern` blocks cannot have qualifiers
19-
--> $DIR/issue-95829.rs:4:14
19+
--> $DIR/issue-95829.rs:4:5
2020
|
2121
LL | extern {
2222
| ------ in this `extern` block
2323
LL | async fn L() {
24-
| ^
25-
|
26-
help: remove the qualifiers
27-
|
28-
LL | fn L() {
29-
| ~~
24+
| ^^^^^ help: remove this qualifier
3025

3126
error: aborting due to 2 previous errors
3227

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,28 @@
11
error: functions in `extern` blocks cannot have qualifiers
2-
--> $DIR/no-const-fn-in-extern-block.rs:2:14
2+
--> $DIR/no-const-fn-in-extern-block.rs:2:5
33
|
44
LL | extern "C" {
55
| ---------- in this `extern` block
66
LL | const fn foo();
7-
| ^^^
8-
|
9-
help: remove the qualifiers
10-
|
11-
LL | fn foo();
12-
| ~~
7+
| ^^^^^ help: remove this qualifier
138

149
error: functions in `extern` blocks cannot have qualifiers
15-
--> $DIR/no-const-fn-in-extern-block.rs:4:21
10+
--> $DIR/no-const-fn-in-extern-block.rs:4:11
1611
|
1712
LL | extern "C" {
1813
| ---------- in this `extern` block
1914
...
2015
LL | const unsafe fn bar();
21-
| ^^^
22-
|
23-
help: remove the qualifiers
16+
| ^^^^^^ help: remove this qualifier
17+
18+
error: functions in `extern` blocks cannot have qualifiers
19+
--> $DIR/no-const-fn-in-extern-block.rs:4:5
2420
|
25-
LL | fn bar();
26-
| ~~
21+
LL | extern "C" {
22+
| ---------- in this `extern` block
23+
...
24+
LL | const unsafe fn bar();
25+
| ^^^^^ help: remove this qualifier
2726

28-
error: aborting due to 2 previous errors
27+
error: aborting due to 3 previous errors
2928

0 commit comments

Comments
 (0)