Skip to content

Commit 6322c04

Browse files
committed
fix: Accept parenthesized paths in asm sym operand parser
1 parent 1433910 commit 6322c04

5 files changed

Lines changed: 91 additions & 1 deletion

File tree

crates/ide-diagnostics/src/handlers/typed_hole.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,4 +442,30 @@ fn rdtscp() -> u64 {
442442
}"#,
443443
);
444444
}
445+
446+
#[test]
447+
fn asm_sym_with_macro_expr_fragment() {
448+
// Regression test for issue #21582
449+
// When `$e:expr` captures a path and is used in `sym $e`, the path gets
450+
// wrapped in parentheses during macro expansion due to invisible delimiters.
451+
// This should not cause false positive typed-hole errors.
452+
check_diagnostics(
453+
r#"
454+
//- minicore: asm
455+
macro_rules! m {
456+
($e:expr) => {
457+
core::arch::asm!("/*{f}*/", f = sym $e, out("ax") _)
458+
};
459+
}
460+
461+
fn generic<T>() {}
462+
463+
fn main() {
464+
unsafe {
465+
m!(generic::<i32>);
466+
}
467+
}
468+
"#,
469+
);
470+
}
445471
}

crates/parser/src/grammar/expressions/atom.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,18 @@ pub(crate) fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedM
407407
op.complete(p, ASM_CONST);
408408
op_n.complete(p, ASM_OPERAND_NAMED);
409409
} else if p.eat_contextual_kw(T![sym]) {
410+
// test asm_sym_paren
411+
// fn foo() {
412+
// builtin#asm("", f = sym (foo::bar));
413+
// }
410414
dir_spec.abandon(p);
411-
paths::type_path(p);
415+
if p.at(T!['(']) {
416+
p.bump(T!['(']);
417+
paths::type_path(p);
418+
p.expect(T![')']);
419+
} else {
420+
paths::type_path(p);
421+
}
412422
op.complete(p, ASM_SYM);
413423
op_n.complete(p, ASM_OPERAND_NAMED);
414424
} else if allow_templates {

crates/parser/test_data/generated/runner.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ mod ok {
2525
#[test]
2626
fn asm_label() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_label.rs"); }
2727
#[test]
28+
fn asm_sym_paren() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_sym_paren.rs"); }
29+
#[test]
2830
fn assoc_const_eq() {
2931
run_and_expect_no_errors("test_data/parser/inline/ok/assoc_const_eq.rs");
3032
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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+
ASM_EXPR
17+
BUILTIN_KW "builtin"
18+
POUND "#"
19+
ASM_KW "asm"
20+
L_PAREN "("
21+
LITERAL
22+
STRING "\"\""
23+
COMMA ","
24+
WHITESPACE " "
25+
ASM_OPERAND_NAMED
26+
NAME
27+
IDENT "f"
28+
WHITESPACE " "
29+
EQ "="
30+
WHITESPACE " "
31+
ASM_SYM
32+
SYM_KW "sym"
33+
WHITESPACE " "
34+
L_PAREN "("
35+
PATH
36+
PATH
37+
PATH_SEGMENT
38+
NAME_REF
39+
IDENT "foo"
40+
COLON2 "::"
41+
PATH_SEGMENT
42+
NAME_REF
43+
IDENT "bar"
44+
R_PAREN ")"
45+
R_PAREN ")"
46+
SEMICOLON ";"
47+
WHITESPACE "\n"
48+
R_CURLY "}"
49+
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#asm("", f = sym (foo::bar));
3+
}

0 commit comments

Comments
 (0)