Merge #10085
10085: fix: avoid panic when parsing extern block r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
bb1987b45e
@ -93,6 +93,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut has_mods = false;
|
let mut has_mods = false;
|
||||||
|
let mut has_extern = false;
|
||||||
|
|
||||||
// modifiers
|
// modifiers
|
||||||
if p.at(T![const]) && p.nth(1) != T!['{'] {
|
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
|
// test_err async_without_semicolon
|
||||||
// fn foo() { let _ = async {} }
|
// 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]);
|
p.eat(T![async]);
|
||||||
has_mods = true;
|
has_mods = true;
|
||||||
}
|
}
|
||||||
@ -114,7 +115,8 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
|
|||||||
has_mods = true;
|
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;
|
has_mods = true;
|
||||||
abi(p);
|
abi(p);
|
||||||
}
|
}
|
||||||
@ -211,25 +213,24 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> {
|
|||||||
type_alias(p, m);
|
type_alias(p, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test extern_block
|
||||||
// unsafe extern "C" {}
|
// unsafe extern "C" {}
|
||||||
T![extern] => {
|
// extern {}
|
||||||
abi(p);
|
T!['{'] if has_extern => {
|
||||||
extern_item_list(p);
|
extern_item_list(p);
|
||||||
m.complete(p, EXTERN_BLOCK);
|
m.complete(p, EXTERN_BLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ if has_visibility || has_mods => {
|
||||||
if !has_visibility && !has_mods {
|
if has_mods {
|
||||||
return Err(m);
|
p.error("expected existential, fn, trait or impl");
|
||||||
} else {
|
} else {
|
||||||
if has_mods {
|
p.error("expected an item");
|
||||||
p.error("expected existential, fn, trait or impl");
|
|
||||||
} else {
|
|
||||||
p.error("expected an item");
|
|
||||||
}
|
|
||||||
m.complete(p, ERROR);
|
|
||||||
}
|
}
|
||||||
|
m.complete(p, ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ => return Err(m),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -240,10 +241,11 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
|
|||||||
// test extern_crate
|
// test extern_crate
|
||||||
// extern crate foo;
|
// extern crate foo;
|
||||||
T![extern] if la == T![crate] => extern_crate(p, m),
|
T![extern] if la == T![crate] => extern_crate(p, m),
|
||||||
T![type] => {
|
T![use] => use_item::use_(p, m),
|
||||||
type_alias(p, m);
|
|
||||||
}
|
|
||||||
T![mod] => mod_item(p, m),
|
T![mod] => mod_item(p, m),
|
||||||
|
|
||||||
|
T![type] => type_alias(p, m),
|
||||||
|
|
||||||
T![struct] => {
|
T![struct] => {
|
||||||
// test struct_items
|
// test struct_items
|
||||||
// struct Foo;
|
// struct Foo;
|
||||||
@ -256,14 +258,7 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
|
|||||||
// }
|
// }
|
||||||
adt::strukt(p, m);
|
adt::strukt(p, m);
|
||||||
}
|
}
|
||||||
// test pub_macro_def
|
T![enum] => adt::enum_(p, m),
|
||||||
// pub macro m($:ident) {}
|
|
||||||
T![macro] => {
|
|
||||||
macro_def(p, m);
|
|
||||||
}
|
|
||||||
IDENT if p.at_contextual_kw("macro_rules") && p.nth(1) == BANG => {
|
|
||||||
macro_rules(p, m);
|
|
||||||
}
|
|
||||||
IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => {
|
IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => {
|
||||||
// test union_items
|
// test union_items
|
||||||
// union Foo {}
|
// union Foo {}
|
||||||
@ -273,17 +268,19 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
|
|||||||
// }
|
// }
|
||||||
adt::union(p, m);
|
adt::union(p, m);
|
||||||
}
|
}
|
||||||
T![enum] => adt::enum_(p, m),
|
|
||||||
T![use] => use_item::use_(p, m),
|
// test pub_macro_def
|
||||||
|
// pub macro m($:ident) {}
|
||||||
|
T![macro] => {
|
||||||
|
macro_def(p, m);
|
||||||
|
}
|
||||||
|
IDENT if p.at_contextual_kw("macro_rules") && p.nth(1) == BANG => {
|
||||||
|
macro_rules(p, m);
|
||||||
|
}
|
||||||
|
|
||||||
T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::konst(p, m),
|
T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::konst(p, m),
|
||||||
T![static] => consts::static_(p, m),
|
T![static] => consts::static_(p, m),
|
||||||
// test extern_block
|
|
||||||
// extern {}
|
|
||||||
T![extern] if la == T!['{'] || (la == STRING && p.nth(2) == T!['{']) => {
|
|
||||||
abi(p);
|
|
||||||
extern_item_list(p);
|
|
||||||
m.complete(p, EXTERN_BLOCK);
|
|
||||||
}
|
|
||||||
_ => return Err(m),
|
_ => return Err(m),
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -292,6 +289,7 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
|
|||||||
fn extern_crate(p: &mut Parser, m: Marker) {
|
fn extern_crate(p: &mut Parser, m: Marker) {
|
||||||
assert!(p.at(T![extern]));
|
assert!(p.at(T![extern]));
|
||||||
p.bump(T![extern]);
|
p.bump(T![extern]);
|
||||||
|
|
||||||
assert!(p.at(T![crate]));
|
assert!(p.at(T![crate]));
|
||||||
p.bump(T![crate]);
|
p.bump(T![crate]);
|
||||||
|
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
SOURCE_FILE@0..22
|
||||||
|
ERROR@0..10
|
||||||
|
ABI@0..10
|
||||||
|
EXTERN_KW@0..6 "extern"
|
||||||
|
WHITESPACE@6..7 " "
|
||||||
|
STRING@7..10 "\"C\""
|
||||||
|
WHITESPACE@10..11 " "
|
||||||
|
ERROR@11..21
|
||||||
|
ABI@11..21
|
||||||
|
EXTERN_KW@11..17 "extern"
|
||||||
|
WHITESPACE@17..18 " "
|
||||||
|
STRING@18..21 "\"C\""
|
||||||
|
WHITESPACE@21..22 "\n"
|
||||||
|
error 10..10: expected existential, fn, trait or impl
|
||||||
|
error 21..21: expected existential, fn, trait or impl
|
@ -0,0 +1 @@
|
|||||||
|
extern "C" extern "C"
|
@ -1,9 +1,21 @@
|
|||||||
SOURCE_FILE@0..10
|
SOURCE_FILE@0..31
|
||||||
EXTERN_BLOCK@0..9
|
EXTERN_BLOCK@0..20
|
||||||
ABI@0..6
|
UNSAFE_KW@0..6 "unsafe"
|
||||||
EXTERN_KW@0..6 "extern"
|
|
||||||
WHITESPACE@6..7 " "
|
WHITESPACE@6..7 " "
|
||||||
EXTERN_ITEM_LIST@7..9
|
ABI@7..17
|
||||||
L_CURLY@7..8 "{"
|
EXTERN_KW@7..13 "extern"
|
||||||
R_CURLY@8..9 "}"
|
WHITESPACE@13..14 " "
|
||||||
WHITESPACE@9..10 "\n"
|
STRING@14..17 "\"C\""
|
||||||
|
WHITESPACE@17..18 " "
|
||||||
|
EXTERN_ITEM_LIST@18..20
|
||||||
|
L_CURLY@18..19 "{"
|
||||||
|
R_CURLY@19..20 "}"
|
||||||
|
WHITESPACE@20..21 "\n"
|
||||||
|
EXTERN_BLOCK@21..30
|
||||||
|
ABI@21..27
|
||||||
|
EXTERN_KW@21..27 "extern"
|
||||||
|
WHITESPACE@27..28 " "
|
||||||
|
EXTERN_ITEM_LIST@28..30
|
||||||
|
L_CURLY@28..29 "{"
|
||||||
|
R_CURLY@29..30 "}"
|
||||||
|
WHITESPACE@30..31 "\n"
|
||||||
|
@ -1 +1,2 @@
|
|||||||
|
unsafe extern "C" {}
|
||||||
extern {}
|
extern {}
|
||||||
|
Loading…
Reference in New Issue
Block a user