@@ -66,7 +66,7 @@ use syntax::SmolStr;
6666
6767use crate :: {
6868 expander:: { Binding , Bindings , ExpandResult , Fragment } ,
69- parser:: { Op , RepeatKind , Separator } ,
69+ parser:: { MetaVarKind , Op , RepeatKind , Separator } ,
7070 tt_iter:: TtIter ,
7171 ExpandError , MetaTemplate ,
7272} ;
@@ -119,6 +119,7 @@ pub(super) fn match_(pattern: &MetaTemplate, input: &tt::Subtree) -> Match {
119119 . map ( |it| match it {
120120 Binding :: Fragment ( _) => 1 ,
121121 Binding :: Empty => 1 ,
122+ Binding :: Missing ( _) => 1 ,
122123 Binding :: Nested ( it) => count ( it. iter ( ) ) ,
123124 } )
124125 . sum ( )
@@ -130,6 +131,7 @@ enum BindingKind {
130131 Empty ( SmolStr ) ,
131132 Optional ( SmolStr ) ,
132133 Fragment ( SmolStr , Fragment ) ,
134+ Missing ( SmolStr , MetaVarKind ) ,
133135 Nested ( usize , usize ) ,
134136}
135137
@@ -190,6 +192,10 @@ impl BindingsBuilder {
190192 . push ( LinkNode :: Node ( Rc :: new ( BindingKind :: Fragment ( var. clone ( ) , fragment) ) ) ) ;
191193 }
192194
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+
193199 fn push_nested ( & mut self , parent : & mut BindingsIdx , child : & BindingsIdx ) {
194200 let BindingsIdx ( idx, nidx) = self . copy ( child) ;
195201 self . nodes [ parent. 0 ] . push ( LinkNode :: Node ( Rc :: new ( BindingKind :: Nested ( idx, nidx) ) ) ) ;
@@ -222,6 +228,9 @@ impl BindingsBuilder {
222228 BindingKind :: Fragment ( name, fragment) => {
223229 bindings. inner . insert ( name. clone ( ) , Binding :: Fragment ( fragment. clone ( ) ) ) ;
224230 }
231+ BindingKind :: Missing ( name, kind) => {
232+ bindings. inner . insert ( name. clone ( ) , Binding :: Missing ( * kind) ) ;
233+ }
225234 BindingKind :: Nested ( idx, nested_idx) => {
226235 let mut nested_nodes = Vec :: new ( ) ;
227236 self . collect_nested ( * idx, * nested_idx, & mut nested_nodes) ;
@@ -458,9 +467,9 @@ fn match_loop_inner<'t>(
458467 }
459468 }
460469 OpDelimited :: Op ( Op :: Var { kind, name, .. } ) => {
461- if let Some ( kind) = kind {
470+ if let & Some ( kind) = kind {
462471 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) ;
464473 match match_res. err {
465474 None => {
466475 // Some meta variables are optional (e.g. vis)
@@ -475,8 +484,15 @@ fn match_loop_inner<'t>(
475484 }
476485 Some ( err) => {
477486 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+ }
480496 }
481497 item. is_error = true ;
482498 error_items. push ( item) ;
@@ -668,20 +684,20 @@ fn match_leaf(lhs: &tt::Leaf, src: &mut TtIter<'_>) -> Result<(), ExpandError> {
668684 }
669685}
670686
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 > > {
672688 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 ,
675691 // FIXME: These two should actually behave differently depending on the edition.
676692 //
677693 // 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 => {
685701 // `expr` should not match underscores.
686702 // HACK: Macro expansion should not be done using "rollback and try another alternative".
687703 // rustc [explicitly checks the next token][0].
@@ -698,17 +714,17 @@ fn match_meta_var(kind: &str, input: &mut TtIter<'_>) -> ExpandResult<Option<Fra
698714 }
699715 _ => {
700716 let tt_result = match kind {
701- "ident" => input
717+ MetaVarKind :: Ident => input
702718 . expect_ident ( )
703719 . map ( |ident| tt:: Leaf :: from ( ident. clone ( ) ) . into ( ) )
704720 . map_err ( |( ) | ExpandError :: binding_error ( "expected ident" ) ) ,
705- "tt" => input
721+ MetaVarKind :: Tt => input
706722 . expect_tt ( )
707723 . map_err ( |( ) | ExpandError :: binding_error ( "expected token tree" ) ) ,
708- "lifetime" => input
724+ MetaVarKind :: Lifetime => input
709725 . expect_lifetime ( )
710726 . map_err ( |( ) | ExpandError :: binding_error ( "expected lifetime" ) ) ,
711- "literal" => {
727+ MetaVarKind :: Literal => {
712728 let neg = input. eat_char ( '-' ) ;
713729 input
714730 . expect_literal ( )
0 commit comments