@@ -2,9 +2,11 @@ use core::fmt;
22use std:: borrow:: Cow ;
33use std:: fmt:: Write ;
44use std:: mem;
5+ use std:: str:: FromStr ;
56
6- use parser:: node:: { Call , Macro , Ws } ;
7+ use parser:: node:: { Call , Macro , MacroArg , Ws } ;
78use parser:: { Expr , Span , WithSpan } ;
9+ use proc_macro2:: TokenStream ;
810use quote:: quote_spanned;
911
1012use crate :: generator:: node:: AstLevel ;
@@ -95,19 +97,37 @@ impl<'a, 'b> MacroInvocation<'a, 'b> {
9597 fn handle_macro_arg < ' h > (
9698 & self ,
9799 expr : & WithSpan < Box < Expr < ' a > > > ,
98- arg_name : & WithSpan < & ' a str > ,
100+ arg : & MacroArg < ' a > ,
99101 buf : & mut Buffer ,
100102 generator : & mut Generator < ' a , ' h > ,
101103 ) -> Result < ( ) , CompileError > {
104+ let mut ty_buf = Buffer :: new ( ) ;
105+ let span = self . callsite_ctx . span_for_node ( arg. name . span ( ) ) ;
106+ if let Some ( ref ty) = arg. ty {
107+ ty_buf. write_token ( syn:: Token ![ : ] , span) ;
108+ // To prevent moving the value/variable, we take a reference of it.
109+ ty_buf. write_token ( syn:: Token ![ & ] , span) ;
110+ generator. visit_ty_generic ( self . callsite_ctx , & mut ty_buf, ty, span) ;
111+ }
112+
102113 match & * * * expr {
103114 // If `expr` is already a form of variable then
104115 // don't reintroduce a new variable. This is
105116 // to avoid moving non-copyable values.
106117 & Expr :: Var ( name) if name != "self" => {
107118 let var = generator. locals . resolve_or_self ( name) ;
108- generator
109- . locals
110- . insert ( Cow :: Borrowed ( * * arg_name) , LocalMeta :: var_with_ref ( var) ) ;
119+ if arg. ty . is_none ( ) {
120+ generator
121+ . locals
122+ . insert ( Cow :: Borrowed ( * arg. name ) , LocalMeta :: var_with_ref ( var) ) ;
123+ } else {
124+ let id = field_new ( & arg. name , span) ;
125+ let var = TokenStream :: from_str ( & var) . expect ( "invalid variable name" ) ;
126+ buf. write_tokens ( quote_spanned ! { span => let #id #ty_buf = & #var; } ) ;
127+ generator
128+ . locals
129+ . insert_with_default ( Cow :: Borrowed ( * arg. name ) ) ;
130+ }
111131 }
112132 Expr :: AssociatedItem ( obj, associated_item) => {
113133 let mut associated_item_buf = Buffer :: new ( ) ;
@@ -125,9 +145,18 @@ impl<'a, 'b> MacroInvocation<'a, 'b> {
125145 . locals
126146 . resolve ( & associated_item)
127147 . unwrap_or ( associated_item) ;
128- generator
129- . locals
130- . insert ( Cow :: Borrowed ( * * arg_name) , LocalMeta :: var_with_ref ( var) ) ;
148+ if arg. ty . is_none ( ) {
149+ generator
150+ . locals
151+ . insert ( Cow :: Borrowed ( * arg. name ) , LocalMeta :: var_with_ref ( var) ) ;
152+ } else {
153+ let id = field_new ( & arg. name , span) ;
154+ let var = TokenStream :: from_str ( & var) . expect ( "invalid variable name" ) ;
155+ buf. write_tokens ( quote_spanned ! { span => let #id #ty_buf = & #var; } ) ;
156+ generator
157+ . locals
158+ . insert_with_default ( Cow :: Borrowed ( * arg. name ) ) ;
159+ }
131160 }
132161 // Everything else still needs to become variables,
133162 // to avoid having the same logic be executed
@@ -136,17 +165,16 @@ impl<'a, 'b> MacroInvocation<'a, 'b> {
136165 _ => {
137166 let mut value = Buffer :: new ( ) ;
138167 value. write_tokens ( generator. visit_expr_root ( self . callsite_ctx , expr) ?) ;
139- let span = self . callsite_ctx . span_for_node ( arg_name. span ( ) ) ;
140- let id = field_new ( arg_name, span) ;
141- buf. write_tokens ( if !is_copyable ( expr) {
142- quote_spanned ! { span => let #id = & ( #value) ; }
168+ let id = field_new ( & arg. name , span) ;
169+ buf. write_tokens ( if !is_copyable ( expr) || arg. ty . is_some ( ) {
170+ quote_spanned ! { span => let #id #ty_buf = & ( #value) ; }
143171 } else {
144- quote_spanned ! { span => let #id = #value; }
172+ quote_spanned ! { span => let #id #ty_buf = #value; }
145173 } ) ;
146174
147175 generator
148176 . locals
149- . insert_with_default ( Cow :: Borrowed ( * * arg_name ) ) ;
177+ . insert_with_default ( Cow :: Borrowed ( * arg . name ) ) ;
150178 }
151179 }
152180
@@ -216,7 +244,7 @@ impl<'a, 'b> MacroInvocation<'a, 'b> {
216244 }
217245 }
218246 } ;
219- self . handle_macro_arg ( expr, & arg. name , buf, generator) ?;
247+ self . handle_macro_arg ( expr, arg, buf, generator) ?;
220248 }
221249
222250 Ok ( ( ) )
0 commit comments