1
1
pub use BinOpToken :: * ;
2
2
pub use LitKind :: * ;
3
+ pub use NtExprKind :: * ;
4
+ pub use NtPatKind :: * ;
3
5
pub use TokenKind :: * ;
4
6
5
7
use crate :: ast;
@@ -38,7 +40,7 @@ pub enum BinOpToken {
38
40
#[ derive( Copy , Clone , Debug , PartialEq , Eq , Encodable , Decodable , Hash , HashStable_Generic ) ]
39
41
pub enum InvisibleOrigin {
40
42
// From the expansion of a metavariable in a declarative macro.
41
- MetaVar ( NonterminalKind ) ,
43
+ MetaVar ( MetaVarKind ) ,
42
44
43
45
// Converted from `proc_macro::Delimiter` in
44
46
// `proc_macro::Delimiter::to_internal`, i.e. returned by a proc macro.
@@ -49,6 +51,54 @@ pub enum InvisibleOrigin {
49
51
FlattenToken ,
50
52
}
51
53
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
+
52
102
/// Describes how a sequence of token trees is delimited.
53
103
/// Cannot use `proc_macro::Delimiter` directly because this
54
104
/// structure should implement some additional traits.
@@ -136,15 +186,17 @@ impl Lit {
136
186
match token. uninterpolate ( ) . kind {
137
187
Ident ( name, IdentIsRaw :: No ) if name. is_bool_lit ( ) => Some ( Lit :: new ( Bool , name, None ) ) ,
138
188
Literal ( token_lit) => Some ( token_lit) ,
139
- OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar ( NonterminalKind :: Literal ) ) ) => {
189
+ OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar ( MetaVarKind :: Literal ) ) ) => {
140
190
panic ! ( "njn: FROM_TOKEN (1)" ) ;
141
191
// if let NtExpr(expr) | NtLiteral(expr) = &**nt
142
192
// && let ast::ExprKind::Lit(token_lit) = expr.kind =>
143
193
// {
144
194
// Some(token_lit)
145
195
// }
146
196
}
147
- OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar ( NonterminalKind :: Expr ) ) ) => {
197
+ OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar ( MetaVarKind :: Expr {
198
+ ..
199
+ } ) ) ) => {
148
200
panic ! ( "njn: FROM_TOKEN (2)" ) ;
149
201
// if let NtExpr(expr) | NtLiteral(expr) = &**nt
150
202
// && let ast::ExprKind::Lit(token_lit) = expr.kind =>
@@ -509,11 +561,10 @@ impl Token {
509
561
Lifetime ( ..) | // labeled loop
510
562
Pound => true , // expression attributes
511
563
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
517
568
) ) ) => true ,
518
569
_ => false ,
519
570
}
@@ -536,11 +587,10 @@ impl Token {
536
587
| Lt | BinOp ( Shl ) // associated path
537
588
| PathSep => true , // global path
538
589
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
544
594
) ) ) => true ,
545
595
_ => false ,
546
596
}
@@ -562,8 +612,8 @@ impl Token {
562
612
Lt | BinOp ( Shl ) | // associated path
563
613
PathSep => true , // global path
564
614
OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar (
565
- NonterminalKind :: Ty |
566
- NonterminalKind :: Path
615
+ MetaVarKind :: Ty |
616
+ MetaVarKind :: Path
567
617
) ) ) => true ,
568
618
// For anonymous structs or unions, which only appear in specific positions
569
619
// (type of struct fields or union fields), we don't consider them as regular types
@@ -577,10 +627,7 @@ impl Token {
577
627
OpenDelim ( Delimiter :: Brace ) | Literal ( ..) | BinOp ( Minus ) => true ,
578
628
Ident ( name, IdentIsRaw :: No ) if name. is_bool_lit ( ) => true ,
579
629
OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar (
580
- NonterminalKind :: Expr
581
- | NonterminalKind :: Expr2021 { .. }
582
- | NonterminalKind :: Block
583
- | NonterminalKind :: Literal ,
630
+ MetaVarKind :: Expr { .. } | MetaVarKind :: Block | MetaVarKind :: Literal ,
584
631
) ) ) => true ,
585
632
_ => false ,
586
633
}
@@ -628,42 +675,25 @@ impl Token {
628
675
match self . uninterpolate ( ) . kind {
629
676
Literal ( ..) | BinOp ( Minus ) => true ,
630
677
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
+ } ,
647
685
_ => false ,
648
686
}
649
687
}
650
688
651
689
pub fn can_begin_string_literal ( & self ) -> bool {
652
690
match self . uninterpolate ( ) . kind {
653
691
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
+ } ,
667
697
_ => false ,
668
698
}
669
699
}
@@ -718,24 +748,24 @@ impl Token {
718
748
self . ident ( ) . is_some_and ( |( ident, _) | ident. name == name)
719
749
}
720
750
721
- /// Would `maybe_reparse_metavar_expr ` in `parser.rs` return `Ok(..)`?
751
+ /// Would `eat_metavar_expr ` in `parser.rs` return `Ok(..)`?
722
752
/// That is, is this a pre-parsed expression dropped into the token stream
723
753
/// (which happens while parsing the result of macro expansion)?
724
754
pub fn is_metavar_expr ( & self ) -> bool {
725
755
matches ! (
726
756
self . is_metavar_seq( ) ,
727
757
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
732
762
)
733
763
)
734
764
}
735
765
736
766
/// Are we at a block from a metavar (`$b:block`)?
737
767
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 ) )
739
769
}
740
770
741
771
/// Returns `true` if the token is either the `mut` or `const` keyword.
@@ -750,7 +780,7 @@ impl Token {
750
780
pub fn is_path_start ( & self ) -> bool {
751
781
self == & PathSep
752
782
|| self . is_qpath_start ( )
753
- || matches ! ( self . is_metavar_seq( ) , Some ( NonterminalKind :: Path ) )
783
+ || matches ! ( self . is_metavar_seq( ) , Some ( MetaVarKind :: Path ) )
754
784
|| self . is_path_segment_keyword ( )
755
785
|| self . is_ident ( ) && !self . is_reserved_ident ( )
756
786
}
@@ -822,7 +852,7 @@ impl Token {
822
852
823
853
/// Is this an invisible open delimiter at the start of a token sequence
824
854
/// from an expanded metavar?
825
- pub fn is_metavar_seq ( & self ) -> Option < NonterminalKind > {
855
+ pub fn is_metavar_seq ( & self ) -> Option < MetaVarKind > {
826
856
match self . kind {
827
857
OpenDelim ( Delimiter :: Invisible ( InvisibleOrigin :: MetaVar ( kind) ) ) => Some ( kind) ,
828
858
_ => None ,
@@ -898,24 +928,34 @@ impl PartialEq<TokenKind> for Token {
898
928
}
899
929
}
900
930
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
+
901
952
#[ derive( Debug , Copy , Clone , PartialEq , Eq , Encodable , Decodable , Hash , HashStable_Generic ) ]
902
953
pub enum NonterminalKind {
903
954
Item ,
904
955
Block ,
905
956
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 ) ,
919
959
Ty ,
920
960
Ident ,
921
961
Lifetime ,
@@ -937,20 +977,22 @@ impl NonterminalKind {
937
977
sym:: item => NonterminalKind :: Item ,
938
978
sym:: block => NonterminalKind :: Block ,
939
979
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 } )
943
985
}
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 } )
950
993
}
951
- Edition :: Edition2024 => NonterminalKind :: Expr ,
952
- } ,
953
- sym:: expr_2021 => NonterminalKind :: Expr2021 { inferred : false } ,
994
+ }
995
+ sym:: expr_2021 => NonterminalKind :: Expr ( Expr2021 { inferred : false } ) ,
954
996
sym:: ty => NonterminalKind :: Ty ,
955
997
sym:: ident => NonterminalKind :: Ident ,
956
998
sym:: lifetime => NonterminalKind :: Lifetime ,
@@ -962,15 +1004,16 @@ impl NonterminalKind {
962
1004
_ => return None ,
963
1005
} )
964
1006
}
1007
+
965
1008
fn symbol ( self ) -> Symbol {
966
1009
match self {
967
1010
NonterminalKind :: Item => sym:: item,
968
1011
NonterminalKind :: Block => sym:: block,
969
1012
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,
974
1017
NonterminalKind :: Ty => sym:: ty,
975
1018
NonterminalKind :: Ident => sym:: ident,
976
1019
NonterminalKind :: Lifetime => sym:: lifetime,
0 commit comments