@@ -131,7 +131,7 @@ enum MatcherLoc {
131131 MetaVarDecl {
132132 span : Span ,
133133 bind : Ident ,
134- kind : NonterminalKind ,
134+ kind : Option < NonterminalKind > ,
135135 next_metavar : usize ,
136136 seq_depth : usize ,
137137 } ,
@@ -337,26 +337,22 @@ impl TtParser {
337337 /// recursive. This conversion is fairly cheap and the representation is sufficiently better
338338 /// for matching than `&[TokenTree]` that it's a clear performance win even with the overhead.
339339 /// But it might be possible to move the conversion outwards so it only occurs once per macro.
340- fn compute_locs (
341- & mut self ,
342- sess : & ParseSess ,
343- matcher : & [ TokenTree ] ,
344- ) -> Result < usize , ( Span , String ) > {
340+ fn compute_locs ( & mut self , sess : & ParseSess , matcher : & [ TokenTree ] ) -> usize {
345341 fn inner (
346342 sess : & ParseSess ,
347343 tts : & [ TokenTree ] ,
348344 locs : & mut Vec < MatcherLoc > ,
349345 next_metavar : & mut usize ,
350346 seq_depth : usize ,
351- ) -> Result < ( ) , ( Span , String ) > {
347+ ) {
352348 for tt in tts {
353349 match tt {
354350 TokenTree :: Token ( token) => {
355351 locs. push ( MatcherLoc :: Token { token : token. clone ( ) } ) ;
356352 }
357353 TokenTree :: Delimited ( _, delimited) => {
358354 locs. push ( MatcherLoc :: Delimited ) ;
359- inner ( sess, & delimited. all_tts , locs, next_metavar, seq_depth) ? ;
355+ inner ( sess, & delimited. all_tts , locs, next_metavar, seq_depth) ;
360356 }
361357 TokenTree :: Sequence ( _, seq) => {
362358 // We can't determine `idx_first_after` and construct the final
@@ -370,7 +366,7 @@ impl TtParser {
370366 let op = seq. kleene . op ;
371367 let idx_first = locs. len ( ) ;
372368 let idx_seq = idx_first - 1 ;
373- inner ( sess, & seq. tts , locs, next_metavar, seq_depth + 1 ) ? ;
369+ inner ( sess, & seq. tts , locs, next_metavar, seq_depth + 1 ) ;
374370
375371 if let Some ( separator) = & seq. separator {
376372 locs. push ( MatcherLoc :: SequenceSep { separator : separator. clone ( ) } ) ;
@@ -389,40 +385,29 @@ impl TtParser {
389385 } ;
390386 }
391387 & TokenTree :: MetaVarDecl ( span, bind, kind) => {
392- if let Some ( kind) = kind {
393- locs. push ( MatcherLoc :: MetaVarDecl {
394- span,
395- bind,
396- kind,
397- next_metavar : * next_metavar,
398- seq_depth,
399- } ) ;
400- * next_metavar += 1 ;
401- } else if sess
402- . missing_fragment_specifiers
403- . borrow_mut ( )
404- . remove ( & span)
405- . is_some ( )
406- {
407- // E.g. `$e` instead of `$e:expr`.
408- return Err ( ( span, "missing fragment specifier" . to_string ( ) ) ) ;
409- }
388+ locs. push ( MatcherLoc :: MetaVarDecl {
389+ span,
390+ bind,
391+ kind,
392+ next_metavar : * next_metavar,
393+ seq_depth,
394+ } ) ;
395+ * next_metavar += 1 ;
410396 }
411397 TokenTree :: MetaVar ( ..) | TokenTree :: MetaVarExpr ( ..) => unreachable ! ( ) ,
412398 }
413399 }
414- Ok ( ( ) )
415400 }
416401
417402 self . locs . clear ( ) ;
418403 let mut next_metavar = 0 ;
419- inner ( sess, matcher, & mut self . locs , & mut next_metavar, /* seq_depth */ 0 ) ? ;
404+ inner ( sess, matcher, & mut self . locs , & mut next_metavar, /* seq_depth */ 0 ) ;
420405
421406 // A final entry is needed for eof.
422407 self . locs . push ( MatcherLoc :: Eof ) ;
423408
424409 // This is the number of metavar decls.
425- Ok ( next_metavar)
410+ next_metavar
426411 }
427412
428413 /// Process the matcher positions of `cur_mps` until it is empty. In the process, this will
@@ -434,6 +419,7 @@ impl TtParser {
434419 /// track of through the mps generated.
435420 fn parse_tt_inner (
436421 & mut self ,
422+ sess : & ParseSess ,
437423 num_metavar_decls : usize ,
438424 token : & Token ,
439425 ) -> Option < NamedParseResult > {
@@ -532,12 +518,20 @@ impl TtParser {
532518 mp. idx = idx_first;
533519 self . cur_mps . push ( mp) ;
534520 }
535- MatcherLoc :: MetaVarDecl { kind, .. } => {
521+ & MatcherLoc :: MetaVarDecl { span , kind, .. } => {
536522 // Built-in nonterminals never start with these tokens, so we can eliminate
537523 // them from consideration. We use the span of the metavariable declaration
538524 // to determine any edition-specific matching behavior for non-terminals.
539- if Parser :: nonterminal_may_begin_with ( * kind, token) {
540- self . bb_mps . push ( mp) ;
525+ if let Some ( kind) = kind {
526+ if Parser :: nonterminal_may_begin_with ( kind, token) {
527+ self . bb_mps . push ( mp) ;
528+ }
529+ } else {
530+ // Both this check and the one in `nameize` are necessary, surprisingly.
531+ if sess. missing_fragment_specifiers . borrow_mut ( ) . remove ( & span) . is_some ( ) {
532+ // E.g. `$e` instead of `$e:expr`.
533+ return Some ( Error ( span, "missing fragment specifier" . to_string ( ) ) ) ;
534+ }
541535 }
542536 }
543537 MatcherLoc :: Eof => {
@@ -564,7 +558,7 @@ impl TtParser {
564558 // Need to take ownership of the matches from within the `Lrc`.
565559 Lrc :: make_mut ( & mut eof_mp. matches ) ;
566560 let matches = Lrc :: try_unwrap ( eof_mp. matches ) . unwrap ( ) . into_iter ( ) ;
567- self . nameize ( matches)
561+ self . nameize ( sess , matches)
568562 }
569563 EofMatcherPositions :: Multiple => {
570564 Error ( token. span , "ambiguity: multiple successful parses" . to_string ( ) )
@@ -588,10 +582,7 @@ impl TtParser {
588582 parser : & mut Cow < ' _ , Parser < ' _ > > ,
589583 matcher : & [ TokenTree ] ,
590584 ) -> NamedParseResult {
591- let num_metavar_decls = match self . compute_locs ( parser. sess , matcher) {
592- Ok ( num_metavar_decls) => num_metavar_decls,
593- Err ( ( span, msg) ) => return Error ( span, msg) ,
594- } ;
585+ let num_metavar_decls = self . compute_locs ( parser. sess , matcher) ;
595586
596587 // A queue of possible matcher positions. We initialize it with the matcher position in
597588 // which the "dot" is before the first token of the first token tree in `matcher`.
@@ -607,7 +598,7 @@ impl TtParser {
607598
608599 // Process `cur_mps` until either we have finished the input or we need to get some
609600 // parsing from the black-box parser done.
610- if let Some ( res) = self . parse_tt_inner ( num_metavar_decls, & parser. token ) {
601+ if let Some ( res) = self . parse_tt_inner ( & parser . sess , num_metavar_decls, & parser. token ) {
611602 return res;
612603 }
613604
@@ -637,7 +628,11 @@ impl TtParser {
637628 let mut mp = self . bb_mps . pop ( ) . unwrap ( ) ;
638629 let loc = & self . locs [ mp. idx ] ;
639630 if let & MatcherLoc :: MetaVarDecl {
640- span, kind, next_metavar, seq_depth, ..
631+ span,
632+ kind : Some ( kind) ,
633+ next_metavar,
634+ seq_depth,
635+ ..
641636 } = loc
642637 {
643638 // We use the span of the metavariable declaration to determine any
@@ -682,7 +677,9 @@ impl TtParser {
682677 . bb_mps
683678 . iter ( )
684679 . map ( |mp| match & self . locs [ mp. idx ] {
685- MatcherLoc :: MetaVarDecl { bind, kind, .. } => format ! ( "{} ('{}')" , kind, bind) ,
680+ MatcherLoc :: MetaVarDecl { bind, kind : Some ( kind) , .. } => {
681+ format ! ( "{} ('{}')" , kind, bind)
682+ }
686683 _ => unreachable ! ( ) ,
687684 } )
688685 . collect :: < Vec < String > > ( )
@@ -702,16 +699,30 @@ impl TtParser {
702699 )
703700 }
704701
705- fn nameize < I : Iterator < Item = NamedMatch > > ( & self , mut res : I ) -> NamedParseResult {
702+ fn nameize < I : Iterator < Item = NamedMatch > > (
703+ & self ,
704+ sess : & ParseSess ,
705+ mut res : I ,
706+ ) -> NamedParseResult {
706707 // Make that each metavar has _exactly one_ binding. If so, insert the binding into the
707708 // `NamedParseResult`. Otherwise, it's an error.
708709 let mut ret_val = FxHashMap :: default ( ) ;
709710 for loc in self . locs . iter ( ) {
710- if let & MatcherLoc :: MetaVarDecl { span, bind, .. } = loc {
711- match ret_val. entry ( MacroRulesNormalizedIdent :: new ( bind) ) {
712- Vacant ( spot) => spot. insert ( res. next ( ) . unwrap ( ) ) ,
713- Occupied ( ..) => return Error ( span, format ! ( "duplicated bind name: {}" , bind) ) ,
714- } ;
711+ if let & MatcherLoc :: MetaVarDecl { span, bind, kind, .. } = loc {
712+ if kind. is_some ( ) {
713+ match ret_val. entry ( MacroRulesNormalizedIdent :: new ( bind) ) {
714+ Vacant ( spot) => spot. insert ( res. next ( ) . unwrap ( ) ) ,
715+ Occupied ( ..) => {
716+ return Error ( span, format ! ( "duplicated bind name: {}" , bind) ) ;
717+ }
718+ } ;
719+ } else {
720+ // Both this check and the one in `parse_tt_inner` are necessary, surprisingly.
721+ if sess. missing_fragment_specifiers . borrow_mut ( ) . remove ( & span) . is_some ( ) {
722+ // E.g. `$e` instead of `$e:expr`.
723+ return Error ( span, "missing fragment specifier" . to_string ( ) ) ;
724+ }
725+ }
715726 }
716727 }
717728 Success ( ret_val)
0 commit comments