@@ -50,20 +50,23 @@ macro_rules! ast_fragments {
5050 /// Can also serve as an input and intermediate result for macro expansion operations.
5151 pub enum AstFragment {
5252 OptExpr ( Option <P <ast:: Expr >>) ,
53+ MethodReceiverExpr ( P <ast:: Expr >) ,
5354 $( $Kind( $AstTy) , ) *
5455 }
5556
5657 /// "Discriminant" of an AST fragment.
5758 #[ derive( Copy , Clone , PartialEq , Eq ) ]
5859 pub enum AstFragmentKind {
5960 OptExpr ,
61+ MethodReceiverExpr ,
6062 $( $Kind, ) *
6163 }
6264
6365 impl AstFragmentKind {
6466 pub fn name( self ) -> & ' static str {
6567 match self {
6668 AstFragmentKind :: OptExpr => "expression" ,
69+ AstFragmentKind :: MethodReceiverExpr => "expression" ,
6770 $( AstFragmentKind :: $Kind => $kind_name, ) *
6871 }
6972 }
@@ -72,6 +75,8 @@ macro_rules! ast_fragments {
7275 match self {
7376 AstFragmentKind :: OptExpr =>
7477 result. make_expr( ) . map( Some ) . map( AstFragment :: OptExpr ) ,
78+ AstFragmentKind :: MethodReceiverExpr =>
79+ result. make_expr( ) . map( AstFragment :: MethodReceiverExpr ) ,
7580 $( AstFragmentKind :: $Kind => result. $make_ast( ) . map( AstFragment :: $Kind) , ) *
7681 }
7782 }
@@ -98,6 +103,13 @@ macro_rules! ast_fragments {
98103 }
99104 }
100105
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+
101113 $( pub fn $make_ast( self ) -> $AstTy {
102114 match self {
103115 AstFragment :: $Kind( ast) => ast,
@@ -120,6 +132,7 @@ macro_rules! ast_fragments {
120132 }
121133 } ) ;
122134 }
135+ AstFragment :: MethodReceiverExpr ( expr) => vis. visit_method_receiver_expr( expr) ,
123136 $( $( AstFragment :: $Kind( ast) => vis. $mut_visit_ast( ast) , ) ?) *
124137 $( $( AstFragment :: $Kind( ast) =>
125138 ast. flat_map_in_place( |ast| vis. $flat_map_ast_elt( ast) ) , ) ?) *
@@ -130,6 +143,7 @@ macro_rules! ast_fragments {
130143 match * self {
131144 AstFragment :: OptExpr ( Some ( ref expr) ) => visitor. visit_expr( expr) ,
132145 AstFragment :: OptExpr ( None ) => { }
146+ AstFragment :: MethodReceiverExpr ( ref expr) => visitor. visit_method_receiver_expr( expr) ,
133147 $( $( AstFragment :: $Kind( ref ast) => visitor. $visit_ast( ast) , ) ?) *
134148 $( $( AstFragment :: $Kind( ref ast) => for ast_elt in & ast[ ..] {
135149 visitor. $visit_ast_elt( ast_elt, $( $args) * ) ;
@@ -222,6 +236,7 @@ impl AstFragmentKind {
222236 match self {
223237 AstFragmentKind :: OptExpr
224238 | AstFragmentKind :: Expr
239+ | AstFragmentKind :: MethodReceiverExpr
225240 | AstFragmentKind :: Stmts
226241 | AstFragmentKind :: Ty
227242 | AstFragmentKind :: Pat => SupportsMacroExpansion :: Yes { supports_inner_attrs : false } ,
@@ -285,6 +300,9 @@ impl AstFragmentKind {
285300 AstFragmentKind :: Expr => AstFragment :: Expr (
286301 items. next ( ) . expect ( "expected exactly one expression" ) . expect_expr ( ) ,
287302 ) ,
303+ AstFragmentKind :: MethodReceiverExpr => AstFragment :: MethodReceiverExpr (
304+ items. next ( ) . expect ( "expected exactly one expression" ) . expect_expr ( ) ,
305+ ) ,
288306 AstFragmentKind :: OptExpr => {
289307 AstFragment :: OptExpr ( items. next ( ) . map ( Annotatable :: expect_expr) )
290308 }
@@ -893,6 +911,7 @@ pub fn parse_ast_fragment<'a>(
893911 AstFragment :: Stmts ( stmts)
894912 }
895913 AstFragmentKind :: Expr => AstFragment :: Expr ( this. parse_expr ( ) ?) ,
914+ AstFragmentKind :: MethodReceiverExpr => AstFragment :: MethodReceiverExpr ( this. parse_expr ( ) ?) ,
896915 AstFragmentKind :: OptExpr => {
897916 if this. token != token:: Eof {
898917 AstFragment :: OptExpr ( Some ( this. parse_expr ( ) ?) )
@@ -1477,6 +1496,42 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> {
14771496 }
14781497}
14791498
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+
14801535struct InvocationCollector < ' a , ' b > {
14811536 cx : & ' a mut ExtCtxt < ' b > ,
14821537 invocations : Vec < ( Invocation , Option < Lrc < SyntaxExtension > > ) > ,
@@ -1840,6 +1895,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
18401895 self . visit_node ( node)
18411896 }
18421897
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+
18431906 fn filter_map_expr ( & mut self , node : P < ast:: Expr > ) -> Option < P < ast:: Expr > > {
18441907 self . flat_map_node ( AstNodeWrapper :: new ( node, OptExprTag ) )
18451908 }
0 commit comments