@@ -594,7 +594,7 @@ fn check_matcher_firsts(cx: &ExtCtxt, ma: &[TokenTree], mb: &[TokenTree]) -> boo
594
594
// matches A will never match B or vice-versa
595
595
// * we find a case that is too complex to handle and reject it
596
596
// * we reach the end of the macro
597
- for ( ta , tb) in ma. iter ( ) . zip ( mb. iter ( ) ) {
597
+ for ( ( idx_a , ta ) , tb) in ma. iter ( ) . enumerate ( ) . zip ( mb. iter ( ) ) {
598
598
if match_same_input ( ta, tb) {
599
599
continue ;
600
600
}
@@ -608,18 +608,25 @@ fn check_matcher_firsts(cx: &ExtCtxt, ma: &[TokenTree], mb: &[TokenTree]) -> boo
608
608
// not tt, ident, or block (that is, either A or B could match several
609
609
// token trees), we cannot know where we should continue the analysis.
610
610
match ( ta, tb) {
611
- ( & TokenTree :: Sequence ( _, _) , _) |
612
- ( _, & TokenTree :: Sequence ( _, _) ) => return false ,
613
-
614
611
( & TokenTree :: Token ( _, MatchNt ( _, nta) ) ,
615
612
& TokenTree :: Token ( _, MatchNt ( _, ntb) ) ) =>
616
613
if !( nt_is_single_tt ( nta) && nt_is_single_tt ( ntb) ) {
617
614
return false
618
615
} ,
619
616
620
- ( & TokenTree :: Token ( _, MatchNt ( _, nt) ) , _) |
621
- ( _ , & TokenTree :: Token ( _, MatchNt ( _, nt) ) ) =>
622
- if !nt_is_single_tt ( nt) { return false } ,
617
+ ( & TokenTree :: Token ( _, MatchNt ( _, nt) ) , _) if !nt_is_single_tt ( nt) =>
618
+ return false ,
619
+
620
+ // super specific corner case: if one arm is always one token,
621
+ // followed by the end of the macro invocation, then we can accept
622
+ // it.
623
+
624
+ ( & TokenTree :: Sequence ( _, _) , _) |
625
+ ( _, & TokenTree :: Sequence ( _, _) ) =>
626
+ return only_simple_tokens ( & ma[ idx_a..] ) && !need_disambiguation,
627
+
628
+ ( _ , & TokenTree :: Token ( _, MatchNt ( _, nt) ) ) if !nt_is_single_tt ( nt) =>
629
+ return only_simple_tokens ( & ma[ idx_a..] ) && !need_disambiguation,
623
630
624
631
_ => ( )
625
632
}
@@ -662,18 +669,26 @@ fn check_matcher_firsts(cx: &ExtCtxt, ma: &[TokenTree], mb: &[TokenTree]) -> boo
662
669
cx. bug ( "unexpeceted NT vs. Token" )
663
670
} ,
664
671
665
- ( & TokenTree :: Token ( _, MatchNt ( _, nt) ) , & TokenTree :: Delimited ( _, ref delim) ) |
666
- ( & TokenTree :: Delimited ( _, ref delim) , & TokenTree :: Token ( _, MatchNt ( _, nt) ) ) =>
667
- if nt. name . as_str ( ) == "block"
668
- && delim. delim == token:: DelimToken :: Brace {
669
- // we cannot say much here. we cannot look inside. we
670
- // can just hope we will find an obvious disambiguation later
671
- need_disambiguation = true ;
672
- continue
673
- } else {
674
- // again, the other possibilites do not share any FIRST token
675
- cx. bug ( "unexpeceted NT vs. Delim" )
676
- } ,
672
+ ( & TokenTree :: Token ( _, MatchNt ( _, nt) ) ,
673
+ & TokenTree :: Delimited ( _, ref delim) ) => {
674
+ // should be the only possibility.
675
+ assert ! ( nt. name. as_str( ) == "block" &&
676
+ delim. delim == token:: DelimToken :: Brace ) ;
677
+ // we cannot say much here. we cannot look inside. we
678
+ // can just hope we will find an obvious disambiguation later
679
+ need_disambiguation = true ;
680
+ continue
681
+ }
682
+
683
+ ( & TokenTree :: Delimited ( _, ref delim) ,
684
+ & TokenTree :: Token ( _, MatchNt ( _, nt) ) ) => {
685
+ assert ! ( nt. name. as_str( ) == "block" &&
686
+ delim. delim == token:: DelimToken :: Brace ) ;
687
+ // as with several-TTs NTs, if the above is only
688
+ // made of simple tokens this is ok...
689
+ need_disambiguation |= !only_simple_tokens ( & delim. tts ) ;
690
+ continue
691
+ }
677
692
678
693
( & TokenTree :: Delimited ( ..) , & TokenTree :: Delimited ( ..) ) => {
679
694
// they have the same delim. as above.
@@ -707,6 +722,16 @@ fn check_matcher_firsts(cx: &ExtCtxt, ma: &[TokenTree], mb: &[TokenTree]) -> boo
707
722
}
708
723
}
709
724
725
+ // checks that a matcher does not contain any NT except ident
726
+ fn only_simple_tokens ( m : & [ TokenTree ] ) -> bool {
727
+ m. iter ( ) . all ( |tt| match * tt {
728
+ TokenTree :: Token ( _, MatchNt ( _, nt) ) => nt. name . as_str ( ) == "ident" ,
729
+ TokenTree :: Token ( ..) => true ,
730
+ TokenTree :: Delimited ( _, ref delim) => only_simple_tokens ( & delim. tts ) ,
731
+ TokenTree :: Sequence ( _, ref seq) => only_simple_tokens ( & seq. tts )
732
+ } )
733
+ }
734
+
710
735
fn nt_is_single_tt ( nt : ast:: Ident ) -> bool {
711
736
match & nt. name . as_str ( ) as & str {
712
737
"block" | "ident" | "tt" => true ,
0 commit comments