Skip to content

Commit da8eb29

Browse files
committed
Macro patterns are not confused with expressions.
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!() }`.
1 parent 0e46ed8 commit da8eb29

File tree

7 files changed

+88
-17
lines changed

7 files changed

+88
-17
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/patterns.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
8484
// Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
8585
// (T![x]).
8686
T!['('] | T!['{'] | T![!] => path_or_macro_pat(p),
87-
T![:] if p.nth_at(1, T![::]) => path_pat(p),
87+
T![:] if p.nth_at(1, T![::]) => path_or_macro_pat(p),
8888
_ => bind_pat(p, true),
8989
},
9090

@@ -156,7 +156,7 @@ fn path_or_macro_pat(p: &mut Parser) -> CompletedMarker {
156156
// }
157157
T![!] => {
158158
items::macro_call_after_excl(p);
159-
MACRO_CALL
159+
return m.complete(p, MACRO_CALL).precede(p).complete(p, MACRO_PAT);
160160
}
161161
_ => PATH_PAT,
162162
};

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)