1
+ use std:: ops:: DerefMut ;
2
+
1
3
use rustc_ast:: mut_visit:: * ;
2
4
use rustc_ast:: ptr:: P ;
3
5
use rustc_ast:: token:: Delimiter ;
@@ -12,20 +14,21 @@ use thin_vec::ThinVec;
12
14
use crate :: expand:: { AstFragment , AstFragmentKind } ;
13
15
14
16
pub ( crate ) fn placeholder (
15
- kind : AstFragmentKind ,
17
+ is_bang_brace : bool ,
18
+ fragment_kind : AstFragmentKind ,
16
19
id : ast:: NodeId ,
17
20
vis : Option < ast:: Visibility > ,
18
21
) -> AstFragment {
19
- fn mac_placeholder ( ) -> P < ast:: MacCall > {
22
+ let mac_placeholder = || -> P < ast:: MacCall > {
20
23
P ( ast:: MacCall {
21
24
path : ast:: Path { span : DUMMY_SP , segments : ThinVec :: new ( ) , tokens : None } ,
22
25
args : P ( ast:: DelimArgs {
23
26
dspan : ast:: tokenstream:: DelimSpan :: dummy ( ) ,
24
- delim : Delimiter :: Parenthesis ,
27
+ delim : if is_bang_brace { Delimiter :: Brace } else { Delimiter :: Parenthesis } ,
25
28
tokens : ast:: tokenstream:: TokenStream :: new ( Vec :: new ( ) ) ,
26
29
} ) ,
27
30
} )
28
- }
31
+ } ;
29
32
30
33
let ident = Ident :: empty ( ) ;
31
34
let attrs = ast:: AttrVec :: new ( ) ;
@@ -49,7 +52,7 @@ pub(crate) fn placeholder(
49
52
let pat =
50
53
|| P ( ast:: Pat { id, kind : ast:: PatKind :: MacCall ( mac_placeholder ( ) ) , span, tokens : None } ) ;
51
54
52
- match kind {
55
+ match fragment_kind {
53
56
AstFragmentKind :: Crate => AstFragment :: Crate ( ast:: Crate {
54
57
attrs : Default :: default ( ) ,
55
58
items : Default :: default ( ) ,
@@ -194,6 +197,7 @@ pub(crate) fn placeholder(
194
197
#[ derive( Default ) ]
195
198
pub ( crate ) struct PlaceholderExpander {
196
199
expanded_fragments : FxHashMap < ast:: NodeId , AstFragment > ,
200
+ expr_under_let_init_else : bool ,
197
201
}
198
202
199
203
impl PlaceholderExpander {
@@ -301,8 +305,48 @@ impl MutVisitor for PlaceholderExpander {
301
305
}
302
306
}
303
307
308
+ fn visit_local ( & mut self , local : & mut P < ast:: Local > ) {
309
+ let ast:: Local { id, pat, ty, kind, span, colon_sp, attrs, tokens } = local. deref_mut ( ) ;
310
+ self . visit_id ( id) ;
311
+ for attr in attrs. iter_mut ( ) {
312
+ self . visit_attribute ( attr) ;
313
+ }
314
+ self . visit_pat ( pat) ;
315
+ if let Some ( ty) = ty {
316
+ self . visit_ty ( ty) ;
317
+ }
318
+ match kind {
319
+ ast:: LocalKind :: Decl => { }
320
+ ast:: LocalKind :: Init ( init) => {
321
+ self . visit_expr ( init) ;
322
+ }
323
+ ast:: LocalKind :: InitElse ( init, els) => {
324
+ self . expr_under_let_init_else = true ;
325
+ self . visit_expr ( init) ;
326
+ self . expr_under_let_init_else = false ;
327
+ self . visit_block ( els) ;
328
+ }
329
+ }
330
+ visit_lazy_tts ( self , tokens) ;
331
+ if let Some ( sp) = colon_sp {
332
+ self . visit_span ( sp) ;
333
+ }
334
+ self . visit_span ( span) ;
335
+ }
336
+
304
337
fn visit_expr ( & mut self , expr : & mut P < ast:: Expr > ) {
305
- match expr. kind {
338
+ tracing:: debug!( "visit: {:?}" , expr) ;
339
+ match & mut expr. kind {
340
+ ast:: ExprKind :: Paren ( paren) => {
341
+ if self . expr_under_let_init_else
342
+ && let ast:: ExprKind :: MacCall ( mac) = & paren. kind
343
+ && matches ! ( mac. args. delim, Delimiter :: Brace )
344
+ {
345
+ * expr = self . remove ( paren. id ) . make_expr ( ) ;
346
+ } else {
347
+ walk_expr ( self , expr) ;
348
+ }
349
+ }
306
350
ast:: ExprKind :: MacCall ( _) => * expr = self . remove ( expr. id ) . make_expr ( ) ,
307
351
_ => walk_expr ( self , expr) ,
308
352
}
0 commit comments