@@ -744,70 +744,77 @@ pub(super) fn parse_tt(
744744 // unnecessary implicit clone later in `Rc::make_mut`.
745745 drop ( eof_items) ;
746746
747- // If there are no possible next positions AND we aren't waiting for the black-box parser,
748- // then there is a syntax error.
749- if bb_items. is_empty ( ) && next_items. is_empty ( ) {
750- return Failure ( parser. token . clone ( ) , "no rules expected this token in macro call" ) ;
751- }
747+ match ( next_items. len ( ) , bb_items. len ( ) ) {
748+ ( 0 , 0 ) => {
749+ // There are no possible next positions AND we aren't waiting for the black-box
750+ // parser: syntax error.
751+ return Failure ( parser. token . clone ( ) , "no rules expected this token in macro call" ) ;
752+ }
752753
753- if ( !bb_items. is_empty ( ) && !next_items. is_empty ( ) ) || bb_items. len ( ) > 1 {
754- // We need to call out to parse some rust nonterminal (black-box) parser. But something
755- // is wrong, because there is not EXACTLY ONE of these.
756- let nts = bb_items
757- . iter ( )
758- . map ( |item| match item. top_elts . get_tt ( item. idx ) {
759- TokenTree :: MetaVarDecl ( _, bind, Some ( kind) ) => format ! ( "{} ('{}')" , kind, bind) ,
760- _ => panic ! ( ) ,
761- } )
762- . collect :: < Vec < String > > ( )
763- . join ( " or " ) ;
764-
765- return Error (
766- parser. token . span ,
767- format ! (
768- "local ambiguity when calling macro `{macro_name}`: multiple parsing options: {}" ,
769- match next_items. len( ) {
770- 0 => format!( "built-in NTs {}." , nts) ,
771- 1 => format!( "built-in NTs {} or 1 other option." , nts) ,
772- n => format!( "built-in NTs {} or {} other options." , nts, n) ,
773- }
774- ) ,
775- ) ;
776- }
754+ ( _, 0 ) => {
755+ // Dump all possible `next_items` into `cur_items` for the next iteration. Then
756+ // process the next token.
757+ cur_items. extend ( next_items. drain ( ..) ) ;
758+ parser. to_mut ( ) . bump ( ) ;
759+ }
777760
778- if !next_items. is_empty ( ) {
779- // Dump all possible `next_items` into `cur_items` for the next iteration. Then process
780- // the next token.
781- cur_items. extend ( next_items. drain ( ..) ) ;
782- parser. to_mut ( ) . bump ( ) ;
783- } else {
784- // Finally, we have the case where we need to call the black-box parser to get some
785- // nonterminal.
786- assert_eq ! ( bb_items. len( ) , 1 ) ;
787-
788- let mut item = bb_items. pop ( ) . unwrap ( ) ;
789- if let TokenTree :: MetaVarDecl ( span, _, Some ( kind) ) = item. top_elts . get_tt ( item. idx ) {
790- let match_cur = item. match_cur ;
791- // We use the span of the metavariable declaration to determine any
792- // edition-specific matching behavior for non-terminals.
793- let nt = match parser. to_mut ( ) . parse_nonterminal ( kind) {
794- Err ( mut err) => {
795- err. span_label (
796- span,
797- format ! ( "while parsing argument for this `{}` macro fragment" , kind) ,
798- )
799- . emit ( ) ;
800- return ErrorReported ;
801- }
802- Ok ( nt) => nt,
803- } ;
804- item. push_match ( match_cur, MatchedNonterminal ( Lrc :: new ( nt) ) ) ;
805- item. idx += 1 ;
806- item. match_cur += 1 ;
807- } else {
808- unreachable ! ( )
761+ ( 0 , 1 ) => {
762+ // We need to call the black-box parser to get some nonterminal.
763+ let mut item = bb_items. pop ( ) . unwrap ( ) ;
764+ if let TokenTree :: MetaVarDecl ( span, _, Some ( kind) ) = item. top_elts . get_tt ( item. idx )
765+ {
766+ let match_cur = item. match_cur ;
767+ // We use the span of the metavariable declaration to determine any
768+ // edition-specific matching behavior for non-terminals.
769+ let nt = match parser. to_mut ( ) . parse_nonterminal ( kind) {
770+ Err ( mut err) => {
771+ err. span_label (
772+ span,
773+ format ! (
774+ "while parsing argument for this `{}` macro fragment" ,
775+ kind
776+ ) ,
777+ )
778+ . emit ( ) ;
779+ return ErrorReported ;
780+ }
781+ Ok ( nt) => nt,
782+ } ;
783+ item. push_match ( match_cur, MatchedNonterminal ( Lrc :: new ( nt) ) ) ;
784+ item. idx += 1 ;
785+ item. match_cur += 1 ;
786+ } else {
787+ unreachable ! ( )
788+ }
789+ cur_items. push ( item) ;
790+ }
791+
792+ ( _, _) => {
793+ // We need to call the black-box parser to get some nonterminal, but something is
794+ // wrong.
795+ let nts = bb_items
796+ . iter ( )
797+ . map ( |item| match item. top_elts . get_tt ( item. idx ) {
798+ TokenTree :: MetaVarDecl ( _, bind, Some ( kind) ) => {
799+ format ! ( "{} ('{}')" , kind, bind)
800+ }
801+ _ => panic ! ( ) ,
802+ } )
803+ . collect :: < Vec < String > > ( )
804+ . join ( " or " ) ;
805+
806+ return Error (
807+ parser. token . span ,
808+ format ! (
809+ "local ambiguity when calling macro `{macro_name}`: multiple parsing options: {}" ,
810+ match next_items. len( ) {
811+ 0 => format!( "built-in NTs {}." , nts) ,
812+ 1 => format!( "built-in NTs {} or 1 other option." , nts) ,
813+ n => format!( "built-in NTs {} or {} other options." , nts, n) ,
814+ }
815+ ) ,
816+ ) ;
809817 }
810- cur_items. push ( item) ;
811818 }
812819
813820 assert ! ( !cur_items. is_empty( ) ) ;
0 commit comments