about summary refs log tree commit diff
diff options
context:
space:
mode:
authorfee1-dead <ent3rm4n@gmail.com>2023-07-06 09:20:34 +0800
committerGitHub <noreply@github.com>2023-07-06 09:20:34 +0800
commit2bc0ae3f33f014f043efecd5b91bb574ea4a855d (patch)
treeebc903e34bb804bb88829245425836b6d8c95add
parent1830b80c2daf5b03d45ec69289e15b25cee97c7f (diff)
parentf25463e8483d8dcfb64cda4e96d5b4fbd11a19c8 (diff)
downloadrust-2bc0ae3f33f014f043efecd5b91bb574ea4a855d.tar.gz
rust-2bc0ae3f33f014f043efecd5b91bb574ea4a855d.zip
Rollup merge of #113350 - chenyukang:yukang-fix-113342-parser, r=compiler-errors
Fix the issue of wrong diagnosis for extern pub fn

Fixes #113342
-rw-r--r--compiler/rustc_parse/src/parser/item.rs6
-rw-r--r--tests/ui/parser/issue-113342.rs9
-rw-r--r--tests/ui/parser/issue-113342.stderr11
3 files changed, 25 insertions, 1 deletions
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 3783ec41b7e..1470180dea7 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -2182,7 +2182,11 @@ impl<'a> Parser<'a> {
             // `extern ABI fn`
             || self.check_keyword_case(kw::Extern, case)
                 && self.look_ahead(1, |t| t.can_begin_literal_maybe_minus())
-                && self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case))
+                && (self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case)) ||
+                    // this branch is only for better diagnostic in later, `pub` is not allowed here
+                    (self.may_recover()
+                        && self.look_ahead(2, |t| t.is_keyword(kw::Pub))
+                        && self.look_ahead(3, |t| t.is_keyword_case(kw::Fn, case))))
     }
 
     /// Parses all the "front matter" (or "qualifiers") for a `fn` declaration,
diff --git a/tests/ui/parser/issue-113342.rs b/tests/ui/parser/issue-113342.rs
new file mode 100644
index 00000000000..18b502736f7
--- /dev/null
+++ b/tests/ui/parser/issue-113342.rs
@@ -0,0 +1,9 @@
+#[link(name = "my_c_library")]
+extern "C" {
+    fn my_c_function(x: i32) -> bool;
+}
+
+#[no_mangle]
+extern "C" pub fn id(x: i32) -> i32 { x } //~ ERROR expected `fn`, found keyword `pub`
+
+fn main() {}
diff --git a/tests/ui/parser/issue-113342.stderr b/tests/ui/parser/issue-113342.stderr
new file mode 100644
index 00000000000..a0c5e665ff8
--- /dev/null
+++ b/tests/ui/parser/issue-113342.stderr
@@ -0,0 +1,11 @@
+error: expected `fn`, found keyword `pub`
+  --> $DIR/issue-113342.rs:7:12
+   |
+LL | extern "C" pub fn id(x: i32) -> i32 { x }
+   | -----------^^^
+   | |          |
+   | |          expected `fn`
+   | help: visibility `pub` must come before `extern "C"`: `pub extern "C"`
+
+error: aborting due to previous error
+