Skip to content

Commit 5e544ed

Browse files
Allow wrapping builtin#offset_of fields argument in parentheses
This is necessary to correctly handle nested fields (`foo.bar`), see the comments in the code for explanation.
1 parent 42de0a5 commit 5e544ed

File tree

4 files changed

+61
-0
lines changed

4 files changed

+61
-0
lines changed

src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,13 +258,25 @@ fn builtin_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
258258
p.expect(T!['(']);
259259
type_(p);
260260
p.expect(T![,]);
261+
// Due to our incomplete handling of macro groups, especially
262+
// those with empty delimiters, we wrap `expr` fragments in
263+
// parentheses sometimes. Since `offset_of` is a macro, and takes
264+
// `expr`, the field names could be wrapped in parentheses.
265+
let wrapped_in_parens = p.eat(T!['(']);
266+
// test offset_of_parens
267+
// fn foo() {
268+
// builtin#offset_of(Foo, (bar.baz.0));
269+
// }
261270
while !p.at(EOF) && !p.at(T![')']) {
262271
name_ref_mod_path_or_index(p);
263272
if !p.at(T![')']) {
264273
p.expect(T![.]);
265274
}
266275
}
267276
p.expect(T![')']);
277+
if wrapped_in_parens {
278+
p.expect(T![')']);
279+
}
268280
Some(m.complete(p, OFFSET_OF_EXPR))
269281
} else if p.at_contextual_kw(T![format_args]) {
270282
p.bump_remap(T![format_args]);

src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,10 @@ mod ok {
416416
run_and_expect_no_errors("test_data/parser/inline/ok/nocontentexpr_after_item.rs");
417417
}
418418
#[test]
419+
fn offset_of_parens() {
420+
run_and_expect_no_errors("test_data/parser/inline/ok/offset_of_parens.rs");
421+
}
422+
#[test]
419423
fn or_pattern() { run_and_expect_no_errors("test_data/parser/inline/ok/or_pattern.rs"); }
420424
#[test]
421425
fn param_list() { run_and_expect_no_errors("test_data/parser/inline/ok/param_list.rs"); }
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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 "\n "
15+
EXPR_STMT
16+
OFFSET_OF_EXPR
17+
BUILTIN_KW "builtin"
18+
POUND "#"
19+
OFFSET_OF_KW "offset_of"
20+
L_PAREN "("
21+
PATH_TYPE
22+
PATH
23+
PATH_SEGMENT
24+
NAME_REF
25+
IDENT "Foo"
26+
COMMA ","
27+
WHITESPACE " "
28+
L_PAREN "("
29+
NAME_REF
30+
IDENT "bar"
31+
DOT "."
32+
NAME_REF
33+
IDENT "baz"
34+
DOT "."
35+
NAME_REF
36+
INT_NUMBER "0"
37+
R_PAREN ")"
38+
R_PAREN ")"
39+
SEMICOLON ";"
40+
WHITESPACE "\n"
41+
R_CURLY "}"
42+
WHITESPACE "\n"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn foo() {
2+
builtin#offset_of(Foo, (bar.baz.0));
3+
}

0 commit comments

Comments
 (0)