@@ -50,20 +50,23 @@ macro_rules! ast_fragments {
50
50
/// Can also serve as an input and intermediate result for macro expansion operations.
51
51
pub enum AstFragment {
52
52
OptExpr ( Option <P <ast:: Expr >>) ,
53
+ MethodReceiverExpr ( P <ast:: Expr >) ,
53
54
$( $Kind( $AstTy) , ) *
54
55
}
55
56
56
57
/// "Discriminant" of an AST fragment.
57
58
#[ derive( Copy , Clone , PartialEq , Eq ) ]
58
59
pub enum AstFragmentKind {
59
60
OptExpr ,
61
+ MethodReceiverExpr ,
60
62
$( $Kind, ) *
61
63
}
62
64
63
65
impl AstFragmentKind {
64
66
pub fn name( self ) -> & ' static str {
65
67
match self {
66
68
AstFragmentKind :: OptExpr => "expression" ,
69
+ AstFragmentKind :: MethodReceiverExpr => "expression" ,
67
70
$( AstFragmentKind :: $Kind => $kind_name, ) *
68
71
}
69
72
}
@@ -72,6 +75,8 @@ macro_rules! ast_fragments {
72
75
match self {
73
76
AstFragmentKind :: OptExpr =>
74
77
result. make_expr( ) . map( Some ) . map( AstFragment :: OptExpr ) ,
78
+ AstFragmentKind :: MethodReceiverExpr =>
79
+ result. make_expr( ) . map( AstFragment :: MethodReceiverExpr ) ,
75
80
$( AstFragmentKind :: $Kind => result. $make_ast( ) . map( AstFragment :: $Kind) , ) *
76
81
}
77
82
}
@@ -98,6 +103,13 @@ macro_rules! ast_fragments {
98
103
}
99
104
}
100
105
106
+ pub fn make_method_receiver_expr( self ) -> P <ast:: Expr > {
107
+ match self {
108
+ AstFragment :: MethodReceiverExpr ( expr) => expr,
109
+ _ => panic!( "AstFragment::make_* called on the wrong kind of fragment" ) ,
110
+ }
111
+ }
112
+
101
113
$( pub fn $make_ast( self ) -> $AstTy {
102
114
match self {
103
115
AstFragment :: $Kind( ast) => ast,
@@ -120,6 +132,7 @@ macro_rules! ast_fragments {
120
132
}
121
133
} ) ;
122
134
}
135
+ AstFragment :: MethodReceiverExpr ( expr) => vis. visit_method_receiver_expr( expr) ,
123
136
$( $( AstFragment :: $Kind( ast) => vis. $mut_visit_ast( ast) , ) ?) *
124
137
$( $( AstFragment :: $Kind( ast) =>
125
138
ast. flat_map_in_place( |ast| vis. $flat_map_ast_elt( ast) ) , ) ?) *
@@ -130,6 +143,7 @@ macro_rules! ast_fragments {
130
143
match * self {
131
144
AstFragment :: OptExpr ( Some ( ref expr) ) => visitor. visit_expr( expr) ,
132
145
AstFragment :: OptExpr ( None ) => { }
146
+ AstFragment :: MethodReceiverExpr ( ref expr) => visitor. visit_method_receiver_expr( expr) ,
133
147
$( $( AstFragment :: $Kind( ref ast) => visitor. $visit_ast( ast) , ) ?) *
134
148
$( $( AstFragment :: $Kind( ref ast) => for ast_elt in & ast[ ..] {
135
149
visitor. $visit_ast_elt( ast_elt, $( $args) * ) ;
@@ -222,6 +236,7 @@ impl AstFragmentKind {
222
236
match self {
223
237
AstFragmentKind :: OptExpr
224
238
| AstFragmentKind :: Expr
239
+ | AstFragmentKind :: MethodReceiverExpr
225
240
| AstFragmentKind :: Stmts
226
241
| AstFragmentKind :: Ty
227
242
| AstFragmentKind :: Pat => SupportsMacroExpansion :: Yes { supports_inner_attrs : false } ,
@@ -285,6 +300,9 @@ impl AstFragmentKind {
285
300
AstFragmentKind :: Expr => AstFragment :: Expr (
286
301
items. next ( ) . expect ( "expected exactly one expression" ) . expect_expr ( ) ,
287
302
) ,
303
+ AstFragmentKind :: MethodReceiverExpr => AstFragment :: MethodReceiverExpr (
304
+ items. next ( ) . expect ( "expected exactly one expression" ) . expect_expr ( ) ,
305
+ ) ,
288
306
AstFragmentKind :: OptExpr => {
289
307
AstFragment :: OptExpr ( items. next ( ) . map ( Annotatable :: expect_expr) )
290
308
}
@@ -893,6 +911,7 @@ pub fn parse_ast_fragment<'a>(
893
911
AstFragment :: Stmts ( stmts)
894
912
}
895
913
AstFragmentKind :: Expr => AstFragment :: Expr ( this. parse_expr ( ) ?) ,
914
+ AstFragmentKind :: MethodReceiverExpr => AstFragment :: MethodReceiverExpr ( this. parse_expr ( ) ?) ,
896
915
AstFragmentKind :: OptExpr => {
897
916
if this. token != token:: Eof {
898
917
AstFragment :: OptExpr ( Some ( this. parse_expr ( ) ?) )
@@ -1477,6 +1496,42 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> {
1477
1496
}
1478
1497
}
1479
1498
1499
+ /// This struct is a hack to workaround unstable of `stmt_expr_attributes`.
1500
+ /// It can be removed once that feature is stabilized.
1501
+ struct MethodReceiverTag ;
1502
+ impl DummyAstNode for MethodReceiverTag {
1503
+ fn dummy ( ) -> MethodReceiverTag {
1504
+ MethodReceiverTag
1505
+ }
1506
+ }
1507
+ impl InvocationCollectorNode for AstNodeWrapper < P < ast:: Expr > , MethodReceiverTag > {
1508
+ type OutputTy = Self ;
1509
+ type AttrsTy = ast:: AttrVec ;
1510
+ const KIND : AstFragmentKind = AstFragmentKind :: MethodReceiverExpr ;
1511
+ fn descr ( ) -> & ' static str {
1512
+ "an expression"
1513
+ }
1514
+ fn to_annotatable ( self ) -> Annotatable {
1515
+ Annotatable :: Expr ( self . wrapped )
1516
+ }
1517
+ fn fragment_to_output ( fragment : AstFragment ) -> Self :: OutputTy {
1518
+ AstNodeWrapper :: new ( fragment. make_method_receiver_expr ( ) , MethodReceiverTag )
1519
+ }
1520
+ fn noop_visit < V : MutVisitor > ( & mut self , visitor : & mut V ) {
1521
+ noop_visit_expr ( & mut self . wrapped , visitor)
1522
+ }
1523
+ fn is_mac_call ( & self ) -> bool {
1524
+ matches ! ( self . wrapped. kind, ast:: ExprKind :: MacCall ( ..) )
1525
+ }
1526
+ fn take_mac_call ( self ) -> ( P < ast:: MacCall > , Self :: AttrsTy , AddSemicolon ) {
1527
+ let node = self . wrapped . into_inner ( ) ;
1528
+ match node. kind {
1529
+ ExprKind :: MacCall ( mac) => ( mac, node. attrs , AddSemicolon :: No ) ,
1530
+ _ => unreachable ! ( ) ,
1531
+ }
1532
+ }
1533
+ }
1534
+
1480
1535
struct InvocationCollector < ' a , ' b > {
1481
1536
cx : & ' a mut ExtCtxt < ' b > ,
1482
1537
invocations : Vec < ( Invocation , Option < Lrc < SyntaxExtension > > ) > ,
@@ -1840,6 +1895,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1840
1895
self . visit_node ( node)
1841
1896
}
1842
1897
1898
+ fn visit_method_receiver_expr ( & mut self , node : & mut P < ast:: Expr > ) {
1899
+ visit_clobber ( node, |node| {
1900
+ let mut wrapper = AstNodeWrapper :: new ( node, MethodReceiverTag ) ;
1901
+ self . visit_node ( & mut wrapper) ;
1902
+ wrapper. wrapped
1903
+ } )
1904
+ }
1905
+
1843
1906
fn filter_map_expr ( & mut self , node : P < ast:: Expr > ) -> Option < P < ast:: Expr > > {
1844
1907
self . flat_map_node ( AstNodeWrapper :: new ( node, OptExprTag ) )
1845
1908
}
0 commit comments