Skip to content

Commit 6a2dd7b

Browse files
bors[bot]matklad
andauthored
Merge #3836
3836: Macro patterns are not confused with expressions. r=matklad a=matklad We treat macro calls as expressions (there's appropriate Into impl), which causes problem if there's expresison and non-expression macro in the same node (like in the match arm). We fix this problem by nesting macor patterns into another node (the same way we nest path into PathExpr or PathPat). Ideally, we probably should add a similar nesting for macro expressions, but that needs some careful thinking about macros in blocks: `{ am_i_expression!() }`. bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
2 parents 795b8cf + da8eb29 commit 6a2dd7b

File tree

8 files changed

+100
-30
lines changed

8 files changed

+100
-30
lines changed

crates/ra_hir_def/src/body/lower.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -672,8 +672,7 @@ impl ExprCollector<'_> {
672672
}
673673

674674
// FIXME: implement
675-
ast::Pat::BoxPat(_) => Pat::Missing,
676-
ast::Pat::RangePat(_) => Pat::Missing,
675+
ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing,
677676
};
678677
let ptr = AstPtr::new(&pat);
679678
self.alloc_pat(pattern, Either::Left(ptr))

crates/ra_hir_ty/src/tests/macros.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
use super::{infer, type_at, type_at_pos};
2-
use crate::test_db::TestDB;
31
use insta::assert_snapshot;
42
use ra_db::fixture::WithFixture;
53

4+
use super::{infer, type_at, type_at_pos};
5+
6+
use crate::test_db::TestDB;
7+
68
#[test]
79
fn cfg_impl_def() {
810
let (db, pos) = TestDB::with_position(
@@ -658,3 +660,28 @@ fn test() {
658660
);
659661
assert_eq!("S", type_at_pos(&db, pos));
660662
}
663+
664+
#[test]
665+
fn macro_in_arm() {
666+
assert_snapshot!(
667+
infer(r#"
668+
macro_rules! unit {
669+
() => { () };
670+
}
671+
672+
fn main() {
673+
let x = match () {
674+
unit!() => 92u32,
675+
};
676+
}
677+
"#),
678+
@r###"
679+
[52; 111) '{ ... }; }': ()
680+
[62; 63) 'x': u32
681+
[66; 108) 'match ... }': u32
682+
[72; 74) '()': ()
683+
[85; 92) 'unit!()': ()
684+
[96; 101) '92u32': u32
685+
"###
686+
);
687+
}

crates/ra_parser/src/grammar/expressions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,6 @@ fn is_expr_stmt_attr_allowed(kind: SyntaxKind) -> bool {
7979
}
8080

8181
pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) {
82-
// test block_items
83-
// fn a() { fn b() {} }
8482
let m = p.start();
8583
// test attr_on_expr_stmt
8684
// fn foo() {
@@ -97,6 +95,8 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) {
9795
return;
9896
}
9997

98+
// test block_items
99+
// fn a() { fn b() {} }
100100
let m = match items::maybe_item(p, m, items::ItemFlavor::Mod) {
101101
Ok(()) => return,
102102
Err(m) => m,

crates/ra_parser/src/grammar/patterns.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,6 @@ fn pattern_single_r(p: &mut Parser, recovery_set: TokenSet) {
7070
return;
7171
}
7272
}
73-
// test marco_pat
74-
// fn main() {
75-
// let m!(x) = 0;
76-
// }
77-
if lhs.kind() == PATH_PAT && p.at(T![!]) {
78-
let m = lhs.undo_completion(p);
79-
items::macro_call_after_excl(p);
80-
m.complete(p, MACRO_CALL);
81-
}
8273
}
8374
}
8475

@@ -92,12 +83,12 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
9283
IDENT => match p.nth(1) {
9384
// Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
9485
// (T![x]).
95-
T!['('] | T!['{'] | T![!] => path_pat(p),
96-
T![:] if p.nth_at(1, T![::]) => path_pat(p),
86+
T!['('] | T!['{'] | T![!] => path_or_macro_pat(p),
87+
T![:] if p.nth_at(1, T![::]) => path_or_macro_pat(p),
9788
_ => bind_pat(p, true),
9889
},
9990

100-
_ if paths::is_use_path_start(p) => path_pat(p),
91+
_ if paths::is_use_path_start(p) => path_or_macro_pat(p),
10192
_ if is_literal_pat_start(p) => literal_pat(p),
10293

10394
T![.] if p.at(T![..]) => dot_dot_pat(p),
@@ -146,7 +137,7 @@ fn literal_pat(p: &mut Parser) -> CompletedMarker {
146137
// let Bar { .. } = ();
147138
// let Bar(..) = ();
148139
// }
149-
fn path_pat(p: &mut Parser) -> CompletedMarker {
140+
fn path_or_macro_pat(p: &mut Parser) -> CompletedMarker {
150141
assert!(paths::is_use_path_start(p));
151142
let m = p.start();
152143
paths::expr_path(p);
@@ -159,6 +150,14 @@ fn path_pat(p: &mut Parser) -> CompletedMarker {
159150
record_field_pat_list(p);
160151
RECORD_PAT
161152
}
153+
// test marco_pat
154+
// fn main() {
155+
// let m!(x) = 0;
156+
// }
157+
T![!] => {
158+
items::macro_call_after_excl(p);
159+
return m.complete(p, MACRO_CALL).precede(p).complete(p, MACRO_PAT);
160+
}
162161
_ => PATH_PAT,
163162
};
164163
m.complete(p, kind)

crates/ra_parser/src/syntax_kind/generated.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ pub enum SyntaxKind {
167167
SLICE_PAT,
168168
RANGE_PAT,
169169
LITERAL_PAT,
170+
MACRO_PAT,
170171
TUPLE_EXPR,
171172
ARRAY_EXPR,
172173
PAREN_EXPR,

crates/ra_syntax/src/ast/generated.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2563,6 +2563,38 @@ impl LiteralPat {
25632563
}
25642564
}
25652565
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2566+
pub struct MacroPat {
2567+
pub(crate) syntax: SyntaxNode,
2568+
}
2569+
impl std::fmt::Display for MacroPat {
2570+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2571+
std::fmt::Display::fmt(self.syntax(), f)
2572+
}
2573+
}
2574+
impl AstNode for MacroPat {
2575+
fn can_cast(kind: SyntaxKind) -> bool {
2576+
match kind {
2577+
MACRO_PAT => true,
2578+
_ => false,
2579+
}
2580+
}
2581+
fn cast(syntax: SyntaxNode) -> Option<Self> {
2582+
if Self::can_cast(syntax.kind()) {
2583+
Some(Self { syntax })
2584+
} else {
2585+
None
2586+
}
2587+
}
2588+
fn syntax(&self) -> &SyntaxNode {
2589+
&self.syntax
2590+
}
2591+
}
2592+
impl MacroPat {
2593+
pub fn macro_call(&self) -> Option<MacroCall> {
2594+
AstChildren::new(&self.syntax).next()
2595+
}
2596+
}
2597+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
25662598
pub struct RecordPat {
25672599
pub(crate) syntax: SyntaxNode,
25682600
}
@@ -4600,6 +4632,7 @@ pub enum Pat {
46004632
SlicePat(SlicePat),
46014633
RangePat(RangePat),
46024634
LiteralPat(LiteralPat),
4635+
MacroPat(MacroPat),
46034636
}
46044637
impl From<OrPat> for Pat {
46054638
fn from(node: OrPat) -> Pat {
@@ -4671,6 +4704,11 @@ impl From<LiteralPat> for Pat {
46714704
Pat::LiteralPat(node)
46724705
}
46734706
}
4707+
impl From<MacroPat> for Pat {
4708+
fn from(node: MacroPat) -> Pat {
4709+
Pat::MacroPat(node)
4710+
}
4711+
}
46744712
impl std::fmt::Display for Pat {
46754713
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
46764714
std::fmt::Display::fmt(self.syntax(), f)
@@ -4681,7 +4719,7 @@ impl AstNode for Pat {
46814719
match kind {
46824720
OR_PAT | PAREN_PAT | REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | DOT_DOT_PAT
46834721
| PATH_PAT | RECORD_PAT | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT
4684-
| LITERAL_PAT => true,
4722+
| LITERAL_PAT | MACRO_PAT => true,
46854723
_ => false,
46864724
}
46874725
}
@@ -4701,6 +4739,7 @@ impl AstNode for Pat {
47014739
SLICE_PAT => Pat::SlicePat(SlicePat { syntax }),
47024740
RANGE_PAT => Pat::RangePat(RangePat { syntax }),
47034741
LITERAL_PAT => Pat::LiteralPat(LiteralPat { syntax }),
4742+
MACRO_PAT => Pat::MacroPat(MacroPat { syntax }),
47044743
_ => return None,
47054744
};
47064745
Some(res)
@@ -4721,6 +4760,7 @@ impl AstNode for Pat {
47214760
Pat::SlicePat(it) => &it.syntax,
47224761
Pat::RangePat(it) => &it.syntax,
47234762
Pat::LiteralPat(it) => &it.syntax,
4763+
Pat::MacroPat(it) => &it.syntax,
47244764
}
47254765
}
47264766
}

crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.txt

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,17 @@ SOURCE_FILE@[0; 33)
1515
LET_STMT@[16; 30)
1616
LET_KW@[16; 19) "let"
1717
WHITESPACE@[19; 20) " "
18-
MACRO_CALL@[20; 25)
19-
PATH@[20; 21)
20-
PATH_SEGMENT@[20; 21)
21-
NAME_REF@[20; 21)
22-
IDENT@[20; 21) "m"
23-
EXCL@[21; 22) "!"
24-
TOKEN_TREE@[22; 25)
25-
L_PAREN@[22; 23) "("
26-
IDENT@[23; 24) "x"
27-
R_PAREN@[24; 25) ")"
18+
MACRO_PAT@[20; 25)
19+
MACRO_CALL@[20; 25)
20+
PATH@[20; 21)
21+
PATH_SEGMENT@[20; 21)
22+
NAME_REF@[20; 21)
23+
IDENT@[20; 21) "m"
24+
EXCL@[21; 22) "!"
25+
TOKEN_TREE@[22; 25)
26+
L_PAREN@[22; 23) "("
27+
IDENT@[23; 24) "x"
28+
R_PAREN@[24; 25) ")"
2829
WHITESPACE@[25; 26) " "
2930
EQ@[26; 27) "="
3031
WHITESPACE@[27; 28) " "

xtask/src/ast_src.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
138138
"SLICE_PAT",
139139
"RANGE_PAT",
140140
"LITERAL_PAT",
141+
"MACRO_PAT",
141142
// atoms
142143
"TUPLE_EXPR",
143144
"ARRAY_EXPR",
@@ -440,6 +441,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
440441
struct SlicePat { args: [Pat] }
441442
struct RangePat {}
442443
struct LiteralPat { Literal }
444+
struct MacroPat { MacroCall }
443445

444446
struct RecordPat { RecordFieldPatList, Path }
445447
struct RecordFieldPatList {
@@ -622,6 +624,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
622624
SlicePat,
623625
RangePat,
624626
LiteralPat,
627+
MacroPat,
625628
}
626629

627630
enum AttrInput { Literal, TokenTree }

0 commit comments

Comments
 (0)