Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/parser/src/grammar/expressions/atom.rs')
-rw-r--r--crates/parser/src/grammar/expressions/atom.rs12
1 files changed, 12 insertions, 0 deletions
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs
index 407320e1d0..c66afed91c 100644
--- a/crates/parser/src/grammar/expressions/atom.rs
+++ b/crates/parser/src/grammar/expressions/atom.rs
@@ -258,6 +258,15 @@ fn builtin_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
p.expect(T!['(']);
type_(p);
p.expect(T![,]);
+ // Due to our incomplete handling of macro groups, especially
+ // those with empty delimiters, we wrap `expr` fragments in
+ // parentheses sometimes. Since `offset_of` is a macro, and takes
+ // `expr`, the field names could be wrapped in parentheses.
+ let wrapped_in_parens = p.eat(T!['(']);
+ // test offset_of_parens
+ // fn foo() {
+ // builtin#offset_of(Foo, (bar.baz.0));
+ // }
while !p.at(EOF) && !p.at(T![')']) {
name_ref_mod_path_or_index(p);
if !p.at(T![')']) {
@@ -265,6 +274,9 @@ fn builtin_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
}
}
p.expect(T![')']);
+ if wrapped_in_parens {
+ p.expect(T![')']);
+ }
Some(m.complete(p, OFFSET_OF_EXPR))
} else if p.at_contextual_kw(T![format_args]) {
p.bump_remap(T![format_args]);