Skip to content

Commit bb1987b

Browse files
bors[bot]matklad
andauthored
Merge #10085
10085: fix: avoid panic when parsing extern block r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
2 parents cbae596 + 4452f9e commit bb1987b

File tree

5 files changed

+68
-41
lines changed

5 files changed

+68
-41
lines changed

crates/parser/src/grammar/items.rs

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
9393
};
9494

9595
let mut has_mods = false;
96+
let mut has_extern = false;
9697

9798
// modifiers
9899
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> {
102103

103104
// test_err async_without_semicolon
104105
// fn foo() { let _ = async {} }
105-
if p.at(T![async]) && p.nth(1) != T!['{'] && p.nth(1) != T![move] && p.nth(1) != T![|] {
106+
if p.at(T![async]) && !matches!(p.nth(1), T!['{'] | T![move] | T![|]) {
106107
p.eat(T![async]);
107108
has_mods = true;
108109
}
@@ -114,7 +115,8 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
114115
has_mods = true;
115116
}
116117

117-
if p.at(T![extern]) && p.nth(1) != T!['{'] && (p.nth(1) != STRING || p.nth(2) != T!['{']) {
118+
if p.at(T![extern]) {
119+
has_extern = true;
118120
has_mods = true;
119121
abi(p);
120122
}
@@ -211,25 +213,24 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
211213
type_alias(p, m);
212214
}
213215

216+
// test extern_block
214217
// unsafe extern "C" {}
215-
T![extern] => {
216-
abi(p);
218+
// extern {}
219+
T!['{'] if has_extern => {
217220
extern_item_list(p);
218221
m.complete(p, EXTERN_BLOCK);
219222
}
220223

221-
_ => {
222-
if !has_visibility && !has_mods {
223-
return Err(m);
224+
_ if has_visibility || has_mods => {
225+
if has_mods {
226+
p.error("expected existential, fn, trait or impl");
224227
} else {
225-
if has_mods {
226-
p.error("expected existential, fn, trait or impl");
227-
} else {
228-
p.error("expected an item");
229-
}
230-
m.complete(p, ERROR);
228+
p.error("expected an item");
231229
}
230+
m.complete(p, ERROR);
232231
}
232+
233+
_ => return Err(m),
233234
}
234235
Ok(())
235236
}
@@ -240,10 +241,11 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
240241
// test extern_crate
241242
// extern crate foo;
242243
T![extern] if la == T![crate] => extern_crate(p, m),
243-
T![type] => {
244-
type_alias(p, m);
245-
}
244+
T![use] => use_item::use_(p, m),
246245
T![mod] => mod_item(p, m),
246+
247+
T![type] => type_alias(p, m),
248+
247249
T![struct] => {
248250
// test struct_items
249251
// struct Foo;
@@ -256,14 +258,7 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
256258
// }
257259
adt::strukt(p, m);
258260
}
259-
// test pub_macro_def
260-
// pub macro m($:ident) {}
261-
T![macro] => {
262-
macro_def(p, m);
263-
}
264-
IDENT if p.at_contextual_kw("macro_rules") && p.nth(1) == BANG => {
265-
macro_rules(p, m);
266-
}
261+
T![enum] => adt::enum_(p, m),
267262
IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => {
268263
// test union_items
269264
// union Foo {}
@@ -273,17 +268,19 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
273268
// }
274269
adt::union(p, m);
275270
}
276-
T![enum] => adt::enum_(p, m),
277-
T![use] => use_item::use_(p, m),
271+
272+
// test pub_macro_def
273+
// pub macro m($:ident) {}
274+
T![macro] => {
275+
macro_def(p, m);
276+
}
277+
IDENT if p.at_contextual_kw("macro_rules") && p.nth(1) == BANG => {
278+
macro_rules(p, m);
279+
}
280+
278281
T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::konst(p, m),
279282
T![static] => consts::static_(p, m),
280-
// test extern_block
281-
// extern {}
282-
T![extern] if la == T!['{'] || (la == STRING && p.nth(2) == T!['{']) => {
283-
abi(p);
284-
extern_item_list(p);
285-
m.complete(p, EXTERN_BLOCK);
286-
}
283+
287284
_ => return Err(m),
288285
};
289286
Ok(())
@@ -292,6 +289,7 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
292289
fn extern_crate(p: &mut Parser, m: Marker) {
293290
assert!(p.at(T![extern]));
294291
p.bump(T![extern]);
292+
295293
assert!(p.at(T![crate]));
296294
p.bump(T![crate]);
297295

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
3+
4+
5+
6+
7+
8+
9+
10+
11+
12+
13+
14+
error 10..10: expected existential, fn, trait or impl
15+
error 21..21: expected existential, fn, trait or impl
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
extern "C" extern "C"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
unsafe extern "C" {}
12
extern {}

0 commit comments

Comments
 (0)