@@ -66,7 +66,7 @@ use syntax::SmolStr;
66
66
67
67
use crate :: {
68
68
expander:: { Binding , Bindings , ExpandResult , Fragment } ,
69
- parser:: { Op , RepeatKind , Separator } ,
69
+ parser:: { MetaVarKind , Op , RepeatKind , Separator } ,
70
70
tt_iter:: TtIter ,
71
71
ExpandError , MetaTemplate ,
72
72
} ;
@@ -119,6 +119,7 @@ pub(super) fn match_(pattern: &MetaTemplate, input: &tt::Subtree) -> Match {
119
119
. map ( |it| match it {
120
120
Binding :: Fragment ( _) => 1 ,
121
121
Binding :: Empty => 1 ,
122
+ Binding :: Missing ( _) => 1 ,
122
123
Binding :: Nested ( it) => count ( it. iter ( ) ) ,
123
124
} )
124
125
. sum ( )
@@ -130,6 +131,7 @@ enum BindingKind {
130
131
Empty ( SmolStr ) ,
131
132
Optional ( SmolStr ) ,
132
133
Fragment ( SmolStr , Fragment ) ,
134
+ Missing ( SmolStr , MetaVarKind ) ,
133
135
Nested ( usize , usize ) ,
134
136
}
135
137
@@ -190,6 +192,10 @@ impl BindingsBuilder {
190
192
. push ( LinkNode :: Node ( Rc :: new ( BindingKind :: Fragment ( var. clone ( ) , fragment) ) ) ) ;
191
193
}
192
194
195
+ fn push_missing ( & mut self , idx : & mut BindingsIdx , var : & SmolStr , kind : MetaVarKind ) {
196
+ self . nodes [ idx. 0 ] . push ( LinkNode :: Node ( Rc :: new ( BindingKind :: Missing ( var. clone ( ) , kind) ) ) ) ;
197
+ }
198
+
193
199
fn push_nested ( & mut self , parent : & mut BindingsIdx , child : & BindingsIdx ) {
194
200
let BindingsIdx ( idx, nidx) = self . copy ( child) ;
195
201
self . nodes [ parent. 0 ] . push ( LinkNode :: Node ( Rc :: new ( BindingKind :: Nested ( idx, nidx) ) ) ) ;
@@ -222,6 +228,9 @@ impl BindingsBuilder {
222
228
BindingKind :: Fragment ( name, fragment) => {
223
229
bindings. inner . insert ( name. clone ( ) , Binding :: Fragment ( fragment. clone ( ) ) ) ;
224
230
}
231
+ BindingKind :: Missing ( name, kind) => {
232
+ bindings. inner . insert ( name. clone ( ) , Binding :: Missing ( * kind) ) ;
233
+ }
225
234
BindingKind :: Nested ( idx, nested_idx) => {
226
235
let mut nested_nodes = Vec :: new ( ) ;
227
236
self . collect_nested ( * idx, * nested_idx, & mut nested_nodes) ;
@@ -458,9 +467,9 @@ fn match_loop_inner<'t>(
458
467
}
459
468
}
460
469
OpDelimited :: Op ( Op :: Var { kind, name, .. } ) => {
461
- if let Some ( kind) = kind {
470
+ if let & Some ( kind) = kind {
462
471
let mut fork = src. clone ( ) ;
463
- let match_res = match_meta_var ( kind. as_str ( ) , & mut fork) ;
472
+ let match_res = match_meta_var ( kind, & mut fork) ;
464
473
match match_res. err {
465
474
None => {
466
475
// Some meta variables are optional (e.g. vis)
@@ -475,8 +484,15 @@ fn match_loop_inner<'t>(
475
484
}
476
485
Some ( err) => {
477
486
res. add_err ( err) ;
478
- if let Some ( fragment) = match_res. value {
479
- bindings_builder. push_fragment ( & mut item. bindings , name, fragment) ;
487
+ match match_res. value {
488
+ Some ( fragment) => bindings_builder. push_fragment (
489
+ & mut item. bindings ,
490
+ name,
491
+ fragment,
492
+ ) ,
493
+ None => {
494
+ bindings_builder. push_missing ( & mut item. bindings , name, kind)
495
+ }
480
496
}
481
497
item. is_error = true ;
482
498
error_items. push ( item) ;
@@ -668,20 +684,20 @@ fn match_leaf(lhs: &tt::Leaf, src: &mut TtIter<'_>) -> Result<(), ExpandError> {
668
684
}
669
685
}
670
686
671
- fn match_meta_var ( kind : & str , input : & mut TtIter < ' _ > ) -> ExpandResult < Option < Fragment > > {
687
+ fn match_meta_var ( kind : MetaVarKind , input : & mut TtIter < ' _ > ) -> ExpandResult < Option < Fragment > > {
672
688
let fragment = match kind {
673
- "path" => parser:: PrefixEntryPoint :: Path ,
674
- "ty" => parser:: PrefixEntryPoint :: Ty ,
689
+ MetaVarKind :: Path => parser:: PrefixEntryPoint :: Path ,
690
+ MetaVarKind :: Ty => parser:: PrefixEntryPoint :: Ty ,
675
691
// FIXME: These two should actually behave differently depending on the edition.
676
692
//
677
693
// https://doc.rust-lang.org/edition-guide/rust-2021/or-patterns-macro-rules.html
678
- "pat" | "pat_param" => parser:: PrefixEntryPoint :: Pat ,
679
- "stmt" => parser:: PrefixEntryPoint :: Stmt ,
680
- "block" => parser:: PrefixEntryPoint :: Block ,
681
- "meta" => parser:: PrefixEntryPoint :: MetaItem ,
682
- "item" => parser:: PrefixEntryPoint :: Item ,
683
- "vis" => parser:: PrefixEntryPoint :: Vis ,
684
- "expr" => {
694
+ MetaVarKind :: Pat | MetaVarKind :: PatParam => parser:: PrefixEntryPoint :: Pat ,
695
+ MetaVarKind :: Stmt => parser:: PrefixEntryPoint :: Stmt ,
696
+ MetaVarKind :: Block => parser:: PrefixEntryPoint :: Block ,
697
+ MetaVarKind :: Meta => parser:: PrefixEntryPoint :: MetaItem ,
698
+ MetaVarKind :: Item => parser:: PrefixEntryPoint :: Item ,
699
+ MetaVarKind :: Vis => parser:: PrefixEntryPoint :: Vis ,
700
+ MetaVarKind :: Expr => {
685
701
// `expr` should not match underscores.
686
702
// HACK: Macro expansion should not be done using "rollback and try another alternative".
687
703
// rustc [explicitly checks the next token][0].
@@ -698,17 +714,17 @@ fn match_meta_var(kind: &str, input: &mut TtIter<'_>) -> ExpandResult<Option<Fra
698
714
}
699
715
_ => {
700
716
let tt_result = match kind {
701
- "ident" => input
717
+ MetaVarKind :: Ident => input
702
718
. expect_ident ( )
703
719
. map ( |ident| tt:: Leaf :: from ( ident. clone ( ) ) . into ( ) )
704
720
. map_err ( |( ) | ExpandError :: binding_error ( "expected ident" ) ) ,
705
- "tt" => input
721
+ MetaVarKind :: Tt => input
706
722
. expect_tt ( )
707
723
. map_err ( |( ) | ExpandError :: binding_error ( "expected token tree" ) ) ,
708
- "lifetime" => input
724
+ MetaVarKind :: Lifetime => input
709
725
. expect_lifetime ( )
710
726
. map_err ( |( ) | ExpandError :: binding_error ( "expected lifetime" ) ) ,
711
- "literal" => {
727
+ MetaVarKind :: Literal => {
712
728
let neg = input. eat_char ( '-' ) ;
713
729
input
714
730
. expect_literal ( )
0 commit comments