Skip to content

Commit 3a8dc27

Browse files
Only parse safe as contextual kw in extern blocks
I don't like the party of `bool`s that is becoming, but two isn't worth a refactoring yet IMO.
1 parent cd206f5 commit 3a8dc27

File tree

7 files changed

+47
-8
lines changed

7 files changed

+47
-8
lines changed

crates/parser/src/grammar.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ pub(crate) mod entry {
8080
paths::type_path(p);
8181
}
8282
pub(crate) fn item(p: &mut Parser<'_>) {
83-
items::item_or_macro(p, true);
83+
// We can set `is_in_extern=true`, because it only allows `safe fn`, and there is no ambiguity here.
84+
items::item_or_macro(p, true, true);
8485
}
8586
// Parse a meta item , which excluded [], e.g : #[ MetaItem ]
8687
pub(crate) fn meta_item(p: &mut Parser<'_>) {

crates/parser/src/grammar/expressions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub(super) fn stmt(p: &mut Parser<'_>, semicolon: Semicolon) {
6666

6767
// test block_items
6868
// fn a() { fn b() {} }
69-
let m = match items::opt_item(p, m) {
69+
let m = match items::opt_item(p, m, false) {
7070
Ok(()) => return,
7171
Err(m) => m,
7272
};

crates/parser/src/grammar/items.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ use super::*;
2020
pub(super) fn mod_contents(p: &mut Parser<'_>, stop_on_r_curly: bool) {
2121
attributes::inner_attrs(p);
2222
while !(p.at(EOF) || (p.at(T!['}']) && stop_on_r_curly)) {
23-
item_or_macro(p, stop_on_r_curly);
23+
// We can set `is_in_extern=true`, because it only allows `safe fn`, and there is no ambiguity here.
24+
item_or_macro(p, stop_on_r_curly, true);
2425
}
2526
}
2627

@@ -41,11 +42,11 @@ pub(super) const ITEM_RECOVERY_SET: TokenSet = TokenSet::new(&[
4142
T![;],
4243
]);
4344

44-
pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool) {
45+
pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool, is_in_extern: bool) {
4546
let m = p.start();
4647
attributes::outer_attrs(p);
4748

48-
let m = match opt_item(p, m) {
49+
let m = match opt_item(p, m, is_in_extern) {
4950
Ok(()) => {
5051
if p.at(T![;]) {
5152
p.err_and_bump(
@@ -91,7 +92,7 @@ pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool) {
9192
}
9293

9394
/// Try to parse an item, completing `m` in case of success.
94-
pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
95+
pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker, is_in_extern: bool) -> Result<(), Marker> {
9596
// test_err pub_expr
9697
// fn foo() { pub 92; }
9798
let has_visibility = opt_visibility(p, false);
@@ -135,7 +136,9 @@ pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
135136
has_mods = true;
136137
}
137138

138-
if p.at_contextual_kw(T![safe]) {
139+
// test safe_outside_of_extern
140+
// fn foo() { safe = true; }
141+
if is_in_extern && p.at_contextual_kw(T![safe]) {
139142
p.eat_contextual_kw(T![safe]);
140143
has_mods = true;
141144
}

crates/parser/src/grammar/items/traits.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ pub(crate) fn assoc_item_list(p: &mut Parser<'_>) {
9494
error_block(p, "expected an item");
9595
continue;
9696
}
97-
item_or_macro(p, true);
97+
item_or_macro(p, true, false);
9898
}
9999
p.expect(T!['}']);
100100
m.complete(p, ASSOC_ITEM_LIST);

crates/parser/test_data/generated/runner.rs

+4
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,10 @@ mod ok {
527527
run_and_expect_no_errors("test_data/parser/inline/ok/return_type_syntax_in_path.rs");
528528
}
529529
#[test]
530+
fn safe_outside_of_extern() {
531+
run_and_expect_no_errors("test_data/parser/inline/ok/safe_outside_of_extern.rs");
532+
}
533+
#[test]
530534
fn self_param() { run_and_expect_no_errors("test_data/parser/inline/ok/self_param.rs"); }
531535
#[test]
532536
fn self_param_outer_attr() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
SOURCE_FILE
2+
FN
3+
FN_KW "fn"
4+
WHITESPACE " "
5+
NAME
6+
IDENT "foo"
7+
PARAM_LIST
8+
L_PAREN "("
9+
R_PAREN ")"
10+
WHITESPACE " "
11+
BLOCK_EXPR
12+
STMT_LIST
13+
L_CURLY "{"
14+
WHITESPACE " "
15+
EXPR_STMT
16+
BIN_EXPR
17+
PATH_EXPR
18+
PATH
19+
PATH_SEGMENT
20+
NAME_REF
21+
IDENT "safe"
22+
WHITESPACE " "
23+
EQ "="
24+
WHITESPACE " "
25+
LITERAL
26+
TRUE_KW "true"
27+
SEMICOLON ";"
28+
WHITESPACE " "
29+
R_CURLY "}"
30+
WHITESPACE "\n"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn foo() { safe = true; }

0 commit comments

Comments
 (0)