Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/parser/src/grammar/items.rs26
-rw-r--r--crates/syntax/test_data/parser/err/0048_repated_extern_modifier.rast15
-rw-r--r--crates/syntax/test_data/parser/err/0048_repated_extern_modifier.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0167_unsafe_extern_block.rast13
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0167_unsafe_extern_block.rs1
5 files changed, 43 insertions, 13 deletions
diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs
index 1057ca8c29..9763df63f2 100644
--- a/crates/parser/src/grammar/items.rs
+++ b/crates/parser/src/grammar/items.rs
@@ -93,6 +93,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
};
let mut has_mods = false;
+ let mut has_extern = false;
// modifiers
if p.at(T![const]) && p.nth(1) != T!['{'] {
@@ -102,7 +103,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
// test_err async_without_semicolon
// fn foo() { let _ = async {} }
- if p.at(T![async]) && p.nth(1) != T!['{'] && p.nth(1) != T![move] && p.nth(1) != T![|] {
+ if p.at(T![async]) && !matches!(p.nth(1), T!['{'] | T![move] | T![|]) {
p.eat(T![async]);
has_mods = true;
}
@@ -114,7 +115,8 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
has_mods = true;
}
- if p.at(T![extern]) && p.nth(1) != T!['{'] && (p.nth(1) != STRING || p.nth(2) != T!['{']) {
+ if p.at(T![extern]) {
+ has_extern = true;
has_mods = true;
abi(p);
}
@@ -211,25 +213,23 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
type_alias(p, m);
}
+ // test unsafe_extern_block
// unsafe extern "C" {}
- T![extern] => {
- abi(p);
+ T!['{'] if has_extern => {
extern_item_list(p);
m.complete(p, EXTERN_BLOCK);
}
- _ => {
- if !has_visibility && !has_mods {
- return Err(m);
+ _ if has_visibility || has_mods => {
+ if has_mods {
+ p.error("expected existential, fn, trait or impl");
} else {
- if has_mods {
- p.error("expected existential, fn, trait or impl");
- } else {
- p.error("expected an item");
- }
- m.complete(p, ERROR);
+ p.error("expected an item");
}
+ m.complete(p, ERROR);
}
+
+ _ => return Err(m),
}
Ok(())
}
diff --git a/crates/syntax/test_data/parser/err/0048_repated_extern_modifier.rast b/crates/syntax/test_data/parser/err/0048_repated_extern_modifier.rast
new file mode 100644
index 0000000000..85e10ca36d
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0048_repated_extern_modifier.rast
@@ -0,0 +1,15 @@
+error 10..10: expected existential, fn, trait or impl
+error 21..21: expected existential, fn, trait or impl
diff --git a/crates/syntax/test_data/parser/err/0048_repated_extern_modifier.rs b/crates/syntax/test_data/parser/err/0048_repated_extern_modifier.rs
new file mode 100644
index 0000000000..1fb18eaf1b
--- /dev/null
+++ b/crates/syntax/test_data/parser/err/0048_repated_extern_modifier.rs
@@ -0,0 +1 @@
+extern "C" extern "C"
diff --git a/crates/syntax/test_data/parser/inline/ok/0167_unsafe_extern_block.rast b/crates/syntax/test_data/parser/inline/ok/0167_unsafe_extern_block.rast
new file mode 100644
index 0000000000..8044e6674d
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0167_unsafe_extern_block.rast
@@ -0,0 +1,13 @@
diff --git a/crates/syntax/test_data/parser/inline/ok/0167_unsafe_extern_block.rs b/crates/syntax/test_data/parser/inline/ok/0167_unsafe_extern_block.rs
new file mode 100644
index 0000000000..9475aec15c
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0167_unsafe_extern_block.rs
@@ -0,0 +1 @@
+unsafe extern "C" {}