11pub use BinOpToken :: * ;
22pub use LitKind :: * ;
3+ pub use NtExprKind :: * ;
4+ pub use NtPatKind :: * ;
35pub use TokenKind :: * ;
46
57use crate :: ast;
@@ -38,7 +40,7 @@ pub enum BinOpToken {
3840#[ derive( Copy , Clone , Debug , PartialEq , Eq , Encodable , Decodable , Hash , HashStable_Generic ) ]
3941pub enum InvisibleOrigin {
4042 // From the expansion of a metavariable in a declarative macro.
41- MetaVar ( NonterminalKind ) ,
43+ MetaVar ( MetaVarKind ) ,
4244
4345 // Converted from `proc_macro::Delimiter` in
4446 // `proc_macro::Delimiter::to_internal`, i.e. returned by a proc macro.
@@ -49,6 +51,54 @@ pub enum InvisibleOrigin {
4951 FlattenToken ,
5052}
5153
54+ /// Annoyingly similar to `NonterminalKind`, but the slightly differences are important.
55+ #[ derive( Debug , Copy , Clone , PartialEq , Eq , Encodable , Decodable , Hash , HashStable_Generic ) ]
56+ pub enum MetaVarKind {
57+ Item ,
58+ Block ,
59+ Stmt ,
60+ Pat ( NtPatKind ) ,
61+ Expr {
62+ kind : NtExprKind ,
63+ // This field is needed for `Token::can_begin_literal_maybe_minus`.
64+ can_begin_literal_maybe_minus : bool ,
65+ // This field is needed for `Token::can_begin_string_literal`.
66+ can_begin_string_literal : bool ,
67+ } ,
68+ Ty ,
69+ Ident ,
70+ Lifetime ,
71+ Literal ,
72+ Meta ,
73+ Path ,
74+ Vis ,
75+ TT ,
76+ }
77+
78+ impl fmt:: Display for MetaVarKind {
79+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
80+ use MetaVarKind :: * ;
81+ let sym = match self {
82+ Item => sym:: item,
83+ Block => sym:: block,
84+ Stmt => sym:: stmt,
85+ Pat ( PatParam { inferred : true } | PatWithOr ) => sym:: pat,
86+ Pat ( PatParam { inferred : false } ) => sym:: pat_param,
87+ Expr { kind : Expr2021 { inferred : true } | Expr , .. } => sym:: expr,
88+ Expr { kind : Expr2021 { inferred : false } , .. } => sym:: expr_2021,
89+ Ty => sym:: ty,
90+ Ident => sym:: ident,
91+ Lifetime => sym:: lifetime,
92+ Literal => sym:: literal,
93+ Meta => sym:: meta,
94+ Path => sym:: path,
95+ Vis => sym:: vis,
96+ TT => sym:: tt,
97+ } ;
98+ write ! ( f, "{}" , sym)
99+ }
100+ }
101+
52102/// Describes how a sequence of token trees is delimited.
53103/// Cannot use `proc_macro::Delimiter` directly because this
54104/// structure should implement some additional traits.
@@ -136,15 +186,17 @@ impl Lit {
136186 match token. uninterpolate ( ) . kind {
137187 Ident ( name, IdentIsRaw :: No ) if name. is_bool_lit ( ) => Some ( Lit :: new ( Bool , name, None ) ) ,
138188 Literal ( token_lit) => Some ( token_lit) ,
139- OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar ( NonterminalKind :: Literal ) ) ) => {
189+ OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar ( MetaVarKind :: Literal ) ) ) => {
140190 panic ! ( "njn: FROM_TOKEN (1)" ) ;
141191 // if let NtExpr(expr) | NtLiteral(expr) = &**nt
142192 // && let ast::ExprKind::Lit(token_lit) = expr.kind =>
143193 // {
144194 // Some(token_lit)
145195 // }
146196 }
147- OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar ( NonterminalKind :: Expr ) ) ) => {
197+ OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar ( MetaVarKind :: Expr {
198+ ..
199+ } ) ) ) => {
148200 panic ! ( "njn: FROM_TOKEN (2)" ) ;
149201 // if let NtExpr(expr) | NtLiteral(expr) = &**nt
150202 // && let ast::ExprKind::Lit(token_lit) = expr.kind =>
@@ -509,11 +561,10 @@ impl Token {
509561 Lifetime ( ..) | // labeled loop
510562 Pound => true , // expression attributes
511563 OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar (
512- NonterminalKind :: Block |
513- NonterminalKind :: Expr |
514- NonterminalKind :: Expr2021 { .. } |
515- NonterminalKind :: Literal |
516- NonterminalKind :: Path
564+ MetaVarKind :: Block |
565+ MetaVarKind :: Expr { .. } |
566+ MetaVarKind :: Literal |
567+ MetaVarKind :: Path
517568 ) ) ) => true ,
518569 _ => false ,
519570 }
@@ -536,11 +587,10 @@ impl Token {
536587 | Lt | BinOp ( Shl ) // associated path
537588 | PathSep => true , // global path
538589 OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar (
539- NonterminalKind :: Block |
540- NonterminalKind :: PatParam { .. } |
541- NonterminalKind :: PatWithOr |
542- NonterminalKind :: Path |
543- NonterminalKind :: Literal
590+ MetaVarKind :: Block |
591+ MetaVarKind :: Pat ( _) |
592+ MetaVarKind :: Path |
593+ MetaVarKind :: Literal
544594 ) ) ) => true ,
545595 _ => false ,
546596 }
@@ -562,8 +612,8 @@ impl Token {
562612 Lt | BinOp ( Shl ) | // associated path
563613 PathSep => true , // global path
564614 OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar (
565- NonterminalKind :: Ty |
566- NonterminalKind :: Path
615+ MetaVarKind :: Ty |
616+ MetaVarKind :: Path
567617 ) ) ) => true ,
568618 // For anonymous structs or unions, which only appear in specific positions
569619 // (type of struct fields or union fields), we don't consider them as regular types
@@ -577,10 +627,7 @@ impl Token {
577627 OpenDelim ( Delimiter :: Brace ) | Literal ( ..) | BinOp ( Minus ) => true ,
578628 Ident ( name, IdentIsRaw :: No ) if name. is_bool_lit ( ) => true ,
579629 OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar (
580- NonterminalKind :: Expr
581- | NonterminalKind :: Expr2021 { .. }
582- | NonterminalKind :: Block
583- | NonterminalKind :: Literal ,
630+ MetaVarKind :: Expr { .. } | MetaVarKind :: Block | MetaVarKind :: Literal ,
584631 ) ) ) => true ,
585632 _ => false ,
586633 }
@@ -628,42 +675,25 @@ impl Token {
628675 match self . uninterpolate ( ) . kind {
629676 Literal ( ..) | BinOp ( Minus ) => true ,
630677 Ident ( name, IdentIsRaw :: No ) if name. is_bool_lit ( ) => true ,
631- // njn: fix up
632- // Interpolated(ref nt) => match &**nt {
633- // NtLiteral(_) => true,
634- // NtExpr(e) => match &e.kind {
635- // ast::ExprKind::Lit(_) => true,
636- // ast::ExprKind::Unary(ast::UnOp::Neg, e) => {
637- // matches!(&e.kind, ast::ExprKind::Lit(_))
638- // }
639- // _ => false,
640- // },
641- // _ => false,
642- // },
643- // njn: too simple compared to what's above?
644- OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar (
645- NonterminalKind :: Literal | NonterminalKind :: Expr | NonterminalKind :: Expr2021 { .. } ,
646- ) ) ) => true ,
678+ OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar ( mv_kind) ) ) => match mv_kind {
679+ MetaVarKind :: Literal => true ,
680+ MetaVarKind :: Expr { can_begin_literal_maybe_minus, .. } => {
681+ can_begin_literal_maybe_minus
682+ }
683+ _ => false ,
684+ } ,
647685 _ => false ,
648686 }
649687 }
650688
651689 pub fn can_begin_string_literal ( & self ) -> bool {
652690 match self . uninterpolate ( ) . kind {
653691 Literal ( ..) => true ,
654- // njn: fix up
655- // Interpolated(ref nt) => match &**nt {
656- // NtLiteral(_) => true,
657- // NtExpr(e) => match &e.kind {
658- // ast::ExprKind::Lit(_) => true,
659- // _ => false,
660- // },
661- // _ => false,
662- // },
663- // njn: too simple compared to what's above?
664- OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar (
665- NonterminalKind :: Literal | NonterminalKind :: Expr | NonterminalKind :: Expr2021 ,
666- ) ) ) => true ,
692+ OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar ( mv_kind) ) ) => match mv_kind {
693+ MetaVarKind :: Literal => true ,
694+ MetaVarKind :: Expr { can_begin_string_literal, .. } => can_begin_string_literal,
695+ _ => false ,
696+ } ,
667697 _ => false ,
668698 }
669699 }
@@ -718,24 +748,24 @@ impl Token {
718748 self . ident ( ) . is_some_and ( |( ident, _) | ident. name == name)
719749 }
720750
721- /// Would `maybe_reparse_metavar_expr ` in `parser.rs` return `Ok(..)`?
751+ /// Would `eat_metavar_expr ` in `parser.rs` return `Ok(..)`?
722752 /// That is, is this a pre-parsed expression dropped into the token stream
723753 /// (which happens while parsing the result of macro expansion)?
724754 pub fn is_metavar_expr ( & self ) -> bool {
725755 matches ! (
726756 self . is_metavar_seq( ) ,
727757 Some (
728- NonterminalKind :: Expr
729- | NonterminalKind :: Literal
730- | NonterminalKind :: Path
731- | NonterminalKind :: Block
758+ MetaVarKind :: Expr { .. }
759+ | MetaVarKind :: Literal
760+ | MetaVarKind :: Path
761+ | MetaVarKind :: Block
732762 )
733763 )
734764 }
735765
736766 /// Are we at a block from a metavar (`$b:block`)?
737767 pub fn is_metavar_block ( & self ) -> bool {
738- matches ! ( self . is_metavar_seq( ) , Some ( NonterminalKind :: Block ) )
768+ matches ! ( self . is_metavar_seq( ) , Some ( MetaVarKind :: Block ) )
739769 }
740770
741771 /// Returns `true` if the token is either the `mut` or `const` keyword.
@@ -750,7 +780,7 @@ impl Token {
750780 pub fn is_path_start ( & self ) -> bool {
751781 self == & PathSep
752782 || self . is_qpath_start ( )
753- || matches ! ( self . is_metavar_seq( ) , Some ( NonterminalKind :: Path ) )
783+ || matches ! ( self . is_metavar_seq( ) , Some ( MetaVarKind :: Path ) )
754784 || self . is_path_segment_keyword ( )
755785 || self . is_ident ( ) && !self . is_reserved_ident ( )
756786 }
@@ -822,7 +852,7 @@ impl Token {
822852
823853 /// Is this an invisible open delimiter at the start of a token sequence
824854 /// from an expanded metavar?
825- pub fn is_metavar_seq ( & self ) -> Option < NonterminalKind > {
855+ pub fn is_metavar_seq ( & self ) -> Option < MetaVarKind > {
826856 match self . kind {
827857 OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar ( kind) ) ) => Some ( kind) ,
828858 _ => None ,
@@ -898,24 +928,34 @@ impl PartialEq<TokenKind> for Token {
898928 }
899929}
900930
931+ #[ derive( Debug , Copy , Clone , PartialEq , Eq , Encodable , Decodable , Hash , HashStable_Generic ) ]
932+ pub enum NtPatKind {
933+ // Matches or-patterns. Was written using `pat` in edition 2021 or later.
934+ PatWithOr ,
935+ // Doesn't match or-patterns.
936+ // - `inferred`: was written using `pat` in edition 2015 or 2018.
937+ // - `!inferred`: was written using `pat_param`.
938+ PatParam { inferred : bool } ,
939+ }
940+
941+ #[ derive( Debug , Copy , Clone , PartialEq , Eq , Encodable , Decodable , Hash , HashStable_Generic ) ]
942+ pub enum NtExprKind {
943+ // Matches expressions using the post-edition 2024. Was written using
944+ // `expr` in edition 2024 or later.
945+ Expr ,
946+ // Matches expressions using the pre-edition 2024 rules.
947+ // - `inferred`: was written using `expr` in edition 2021 or earlier.
948+ // - `!inferred`: was written using `expr_2021`.
949+ Expr2021 { inferred : bool } ,
950+ }
951+
901952#[ derive( Debug , Copy , Clone , PartialEq , Eq , Encodable , Decodable , Hash , HashStable_Generic ) ]
902953pub enum NonterminalKind {
903954 Item ,
904955 Block ,
905956 Stmt ,
906- PatParam {
907- /// Keep track of whether the user used `:pat_param` or `:pat` and we inferred it from the
908- /// edition of the span. This is used for diagnostics.
909- inferred : bool ,
910- } ,
911- PatWithOr ,
912- Expr ,
913- /// Matches an expression using the rules from edition 2021 and earlier.
914- Expr2021 {
915- /// Keep track of whether the user used `:expr` or `:expr_2021` and we inferred it from the
916- /// edition of the span. This is used for diagnostics AND feature gating.
917- inferred : bool ,
918- } ,
957+ Pat ( NtPatKind ) ,
958+ Expr ( NtExprKind ) ,
919959 Ty ,
920960 Ident ,
921961 Lifetime ,
@@ -937,20 +977,22 @@ impl NonterminalKind {
937977 sym:: item => NonterminalKind :: Item ,
938978 sym:: block => NonterminalKind :: Block ,
939979 sym:: stmt => NonterminalKind :: Stmt ,
940- sym:: pat => match edition ( ) {
941- Edition :: Edition2015 | Edition :: Edition2018 => {
942- NonterminalKind :: PatParam { inferred : true }
980+ sym:: pat => {
981+ if edition ( ) . at_least_rust_2021 ( ) {
982+ NonterminalKind :: Pat ( PatWithOr )
983+ } else {
984+ NonterminalKind :: Pat ( PatParam { inferred : true } )
943985 }
944- Edition :: Edition2021 | Edition :: Edition2024 => NonterminalKind :: PatWithOr ,
945- } ,
946- sym:: pat_param => NonterminalKind :: PatParam { inferred : false } ,
947- sym:: expr => match edition ( ) {
948- Edition :: Edition2015 | Edition :: Edition2018 | Edition :: Edition2021 => {
949- NonterminalKind :: Expr2021 { inferred : true }
986+ }
987+ sym:: pat_param => NonterminalKind :: Pat ( PatParam { inferred : false } ) ,
988+ sym:: expr => {
989+ if edition ( ) . at_least_rust_2024 ( ) {
990+ NonterminalKind :: Expr ( Expr )
991+ } else {
992+ NonterminalKind :: Expr ( Expr2021 { inferred : true } )
950993 }
951- Edition :: Edition2024 => NonterminalKind :: Expr ,
952- } ,
953- sym:: expr_2021 => NonterminalKind :: Expr2021 { inferred : false } ,
994+ }
995+ sym:: expr_2021 => NonterminalKind :: Expr ( Expr2021 { inferred : false } ) ,
954996 sym:: ty => NonterminalKind :: Ty ,
955997 sym:: ident => NonterminalKind :: Ident ,
956998 sym:: lifetime => NonterminalKind :: Lifetime ,
@@ -962,15 +1004,16 @@ impl NonterminalKind {
9621004 _ => return None ,
9631005 } )
9641006 }
1007+
9651008 fn symbol ( self ) -> Symbol {
9661009 match self {
9671010 NonterminalKind :: Item => sym:: item,
9681011 NonterminalKind :: Block => sym:: block,
9691012 NonterminalKind :: Stmt => sym:: stmt,
970- NonterminalKind :: PatParam { inferred : false } => sym:: pat_param ,
971- NonterminalKind :: PatParam { inferred : true } | NonterminalKind :: PatWithOr => sym:: pat ,
972- NonterminalKind :: Expr | NonterminalKind :: Expr2021 { inferred : true } => sym:: expr,
973- NonterminalKind :: Expr2021 { inferred : false } => sym:: expr_2021,
1013+ NonterminalKind :: Pat ( PatParam { inferred : true } | PatWithOr ) => sym:: pat ,
1014+ NonterminalKind :: Pat ( PatParam { inferred : false } ) => sym:: pat_param ,
1015+ NonterminalKind :: Expr ( Expr2021 { inferred : true } | Expr ) => sym:: expr,
1016+ NonterminalKind :: Expr ( Expr2021 { inferred : false } ) => sym:: expr_2021,
9741017 NonterminalKind :: Ty => sym:: ty,
9751018 NonterminalKind :: Ident => sym:: ident,
9761019 NonterminalKind :: Lifetime => sym:: lifetime,
0 commit comments