Merge pull request #18446 from ChayimFriedman2/safe-statement

fix: Only parse `safe` as contextual kw in extern blocks
This commit is contained in:
Lukas Wirth 2024-10-30 19:04:56 +00:00 committed by GitHub
commit 2d5b758439
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 47 additions and 8 deletions

View File

@ -80,7 +80,8 @@ pub(crate) fn path(p: &mut Parser<'_>) {
paths::type_path(p); paths::type_path(p);
} }
pub(crate) fn item(p: &mut Parser<'_>) { pub(crate) fn item(p: &mut Parser<'_>) {
items::item_or_macro(p, true); // We can set `is_in_extern=true`, because it only allows `safe fn`, and there is no ambiguity here.
items::item_or_macro(p, true, true);
} }
// Parse a meta item , which excluded [], e.g : #[ MetaItem ] // Parse a meta item , which excluded [], e.g : #[ MetaItem ]
pub(crate) fn meta_item(p: &mut Parser<'_>) { pub(crate) fn meta_item(p: &mut Parser<'_>) {

View File

@ -66,7 +66,7 @@ pub(super) fn stmt(p: &mut Parser<'_>, semicolon: Semicolon) {
// test block_items // test block_items
// fn a() { fn b() {} } // fn a() { fn b() {} }
let m = match items::opt_item(p, m) { let m = match items::opt_item(p, m, false) {
Ok(()) => return, Ok(()) => return,
Err(m) => m, Err(m) => m,
}; };

View File

@ -20,7 +20,8 @@
pub(super) fn mod_contents(p: &mut Parser<'_>, stop_on_r_curly: bool) { pub(super) fn mod_contents(p: &mut Parser<'_>, stop_on_r_curly: bool) {
attributes::inner_attrs(p); attributes::inner_attrs(p);
while !(p.at(EOF) || (p.at(T!['}']) && stop_on_r_curly)) { while !(p.at(EOF) || (p.at(T!['}']) && stop_on_r_curly)) {
item_or_macro(p, stop_on_r_curly); // We can set `is_in_extern=true`, because it only allows `safe fn`, and there is no ambiguity here.
item_or_macro(p, stop_on_r_curly, true);
} }
} }
@ -41,11 +42,11 @@ pub(super) fn mod_contents(p: &mut Parser<'_>, stop_on_r_curly: bool) {
T![;], T![;],
]); ]);
pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool) { pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool, is_in_extern: bool) {
let m = p.start(); let m = p.start();
attributes::outer_attrs(p); attributes::outer_attrs(p);
let m = match opt_item(p, m) { let m = match opt_item(p, m, is_in_extern) {
Ok(()) => { Ok(()) => {
if p.at(T![;]) { if p.at(T![;]) {
p.err_and_bump( p.err_and_bump(
@ -91,7 +92,7 @@ pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool) {
} }
/// Try to parse an item, completing `m` in case of success. /// Try to parse an item, completing `m` in case of success.
pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> { pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker, is_in_extern: bool) -> Result<(), Marker> {
// test_err pub_expr // test_err pub_expr
// fn foo() { pub 92; } // fn foo() { pub 92; }
let has_visibility = opt_visibility(p, false); let has_visibility = opt_visibility(p, false);
@ -135,7 +136,9 @@ pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
has_mods = true; has_mods = true;
} }
if p.at_contextual_kw(T![safe]) { // test safe_outside_of_extern
// fn foo() { safe = true; }
if is_in_extern && p.at_contextual_kw(T![safe]) {
p.eat_contextual_kw(T![safe]); p.eat_contextual_kw(T![safe]);
has_mods = true; has_mods = true;
} }

View File

@ -94,7 +94,7 @@ pub(crate) fn assoc_item_list(p: &mut Parser<'_>) {
error_block(p, "expected an item"); error_block(p, "expected an item");
continue; continue;
} }
item_or_macro(p, true); item_or_macro(p, true, false);
} }
p.expect(T!['}']); p.expect(T!['}']);
m.complete(p, ASSOC_ITEM_LIST); m.complete(p, ASSOC_ITEM_LIST);

View File

@ -527,6 +527,10 @@ fn return_type_syntax_in_path() {
run_and_expect_no_errors("test_data/parser/inline/ok/return_type_syntax_in_path.rs"); run_and_expect_no_errors("test_data/parser/inline/ok/return_type_syntax_in_path.rs");
} }
#[test] #[test]
fn safe_outside_of_extern() {
run_and_expect_no_errors("test_data/parser/inline/ok/safe_outside_of_extern.rs");
}
#[test]
fn self_param() { run_and_expect_no_errors("test_data/parser/inline/ok/self_param.rs"); } fn self_param() { run_and_expect_no_errors("test_data/parser/inline/ok/self_param.rs"); }
#[test] #[test]
fn self_param_outer_attr() { fn self_param_outer_attr() {

View File

@ -0,0 +1,30 @@
SOURCE_FILE
FN
FN_KW "fn"
WHITESPACE " "
NAME
IDENT "foo"
PARAM_LIST
L_PAREN "("
R_PAREN ")"
WHITESPACE " "
BLOCK_EXPR
STMT_LIST
L_CURLY "{"
WHITESPACE " "
EXPR_STMT
BIN_EXPR
PATH_EXPR
PATH
PATH_SEGMENT
NAME_REF
IDENT "safe"
WHITESPACE " "
EQ "="
WHITESPACE " "
LITERAL
TRUE_KW "true"
SEMICOLON ";"
WHITESPACE " "
R_CURLY "}"
WHITESPACE "\n"

View File

@ -0,0 +1 @@
fn foo() { safe = true; }