9
9
//! See [`serde_closure`](https://docs.rs/serde_closure/) for
10
10
//! documentation.
11
11
12
- #![ doc( html_root_url = "https://docs.rs/serde_closure_derive/0.2.8 " ) ]
12
+ #![ doc( html_root_url = "https://docs.rs/serde_closure_derive/0.2.9 " ) ]
13
13
#![ feature( proc_macro_diagnostic) ]
14
14
#![ allow( non_snake_case) ] // due to proc-macro-hack can't apply this directly
15
15
16
16
extern crate proc_macro;
17
17
18
18
use proc_macro2:: { Span , TokenStream } ;
19
19
use proc_macro_hack:: proc_macro_hack;
20
- use quote:: { quote, quote_spanned , ToTokens } ;
21
- use std:: { collections:: HashSet , iter, iter:: successors, str} ;
20
+ use quote:: { quote, ToTokens } ;
21
+ use std:: { collections:: HashSet , iter, iter:: successors, mem :: take , str} ;
22
22
use syn:: {
23
- parse:: { Parse , ParseStream } , parse2, spanned:: Spanned , token:: Bracket , Arm , Error , Expr , ExprArray , ExprAssign , ExprAssignOp , ExprAsync , ExprAwait , ExprBinary , ExprBlock , ExprBox , ExprBreak , ExprCall , ExprCast , ExprClosure , ExprField , ExprForLoop , ExprGroup , ExprIf , ExprIndex , ExprLet , ExprLoop , ExprMacro , ExprMatch , ExprMethodCall , ExprParen , ExprPath , ExprRange , ExprReference , ExprRepeat , ExprReturn , ExprStruct , ExprTry , ExprTryBlock , ExprTuple , ExprType , ExprUnary , ExprUnsafe , ExprWhile , ExprYield , FieldValue , Ident , Local , Member , Pat , PatBox , PatIdent , PatReference , PatSlice , PatTuple , PatTupleStruct , PatType , Path , PathArguments , PathSegment , Stmt , Type , TypeInfer , TypeReference , UnOp
23
+ parse:: { Parse , ParseStream } , parse2, spanned:: Spanned , token:: Bracket , Arm , Block , Error , Expr , ExprArray , ExprAssign , ExprAssignOp , ExprAsync , ExprAwait , ExprBinary , ExprBlock , ExprBox , ExprBreak , ExprCall , ExprCast , ExprClosure , ExprField , ExprForLoop , ExprGroup , ExprIf , ExprIndex , ExprLet , ExprLoop , ExprMacro , ExprMatch , ExprMethodCall , ExprParen , ExprPath , ExprRange , ExprReference , ExprRepeat , ExprReturn , ExprStruct , ExprTry , ExprTryBlock , ExprTuple , ExprType , ExprUnary , ExprUnsafe , ExprWhile , ExprYield , FieldValue , Ident , Local , Member , Pat , PatBox , PatIdent , PatReference , PatSlice , PatTuple , PatTupleStruct , PatType , Path , PathArguments , PathSegment , Stmt , Type , TypeInfer , TypeReference , UnOp
24
24
} ;
25
25
26
26
#[ proc_macro_hack]
@@ -88,18 +88,33 @@ fn impl_fn_once(closure: Closure, kind: Kind) -> Result<TokenStream, Error> {
88
88
let impls_name = Ident :: new ( "__serde_closure_impls" , span) ;
89
89
90
90
let _ = closure. env ;
91
- let closure = closure. closure ;
91
+ let mut closure = closure. closure ;
92
92
let source = closure. to_token_stream ( ) . to_string ( ) ;
93
93
let capture = closure. capture . is_some ( ) ;
94
+ // Convert closure to use block so any not_env_variables can be asserted.
95
+ closure. body = Box :: new ( match * closure. body {
96
+ Expr :: Block ( block) => Expr :: Block ( block) ,
97
+ expr => Expr :: Block ( ExprBlock {
98
+ attrs : vec ! [ ] ,
99
+ label : None ,
100
+ block : Block {
101
+ brace_token : Default :: default ( ) ,
102
+ stmts : vec ! [ Stmt :: Expr ( expr) ] ,
103
+ } ,
104
+ } ) ,
105
+ } ) ;
94
106
let mut closure = Expr :: Closure ( closure) ;
95
107
let mut env_variables = HashSet :: new ( ) ;
108
+ let mut not_env_variables = HashSet :: new ( ) ;
96
109
State :: new (
97
110
& mut env_variables,
111
+ & mut not_env_variables,
98
112
kind != Kind :: FnOnce ,
99
113
kind != Kind :: FnOnce && !capture,
100
114
& env_name,
101
115
)
102
116
. expr ( & mut closure, false ) ;
117
+ assert ! ( not_env_variables. is_empty( ) ) ;
103
118
let mut env_variables: Vec < Ident > = env_variables. into_iter ( ) . collect ( ) ;
104
119
env_variables. sort ( ) ;
105
120
let env_variables = & env_variables;
@@ -476,17 +491,20 @@ fn pat_to_type(pat: &Pat) -> Type {
476
491
struct State < ' a > {
477
492
variables : HashSet < Ident > ,
478
493
env_variables : & ' a mut HashSet < Ident > ,
494
+ not_env_variables : & ' a mut HashSet < Ident > ,
479
495
env_struct : bool ,
480
496
deref : bool ,
481
497
env_name : & ' a Ident ,
482
498
}
483
499
impl < ' a > State < ' a > {
484
500
fn new (
485
- env_variables : & ' a mut HashSet < Ident > , env_struct : bool , deref : bool , env_name : & ' a Ident ,
501
+ env_variables : & ' a mut HashSet < Ident > , not_env_variables : & ' a mut HashSet < Ident > ,
502
+ env_struct : bool , deref : bool , env_name : & ' a Ident ,
486
503
) -> Self {
487
504
Self {
488
505
variables : HashSet :: new ( ) ,
489
506
env_variables,
507
+ not_env_variables,
490
508
env_struct,
491
509
deref,
492
510
env_name,
@@ -496,6 +514,7 @@ impl<'a> State<'a> {
496
514
State {
497
515
variables : self . variables . clone ( ) ,
498
516
env_variables : self . env_variables ,
517
+ not_env_variables : self . not_env_variables ,
499
518
env_struct : self . env_struct ,
500
519
deref : self . deref ,
501
520
env_name : self . env_name ,
@@ -542,21 +561,31 @@ impl<'a> State<'a> {
542
561
}
543
562
}
544
563
545
- fn block ( & mut self , stmts : & mut [ Stmt ] ) {
546
- for stmt in stmts {
547
- match stmt {
548
- Stmt :: Local ( Local { pat, init, .. } ) => {
549
- if let Some ( ( _, expr) ) = init {
564
+ fn block ( & mut self , stmts : & mut Vec < Stmt > ) {
565
+ * stmts = take ( stmts)
566
+ . into_iter ( )
567
+ . flat_map ( |mut stmt| {
568
+ match & mut stmt {
569
+ Stmt :: Local ( Local { pat, init, .. } ) => {
570
+ if let Some ( ( _, expr) ) = init {
571
+ self . expr ( expr, false ) ;
572
+ }
573
+ self . pat ( pat) ;
574
+ }
575
+ Stmt :: Expr ( expr) | Stmt :: Semi ( expr, _) => {
550
576
self . expr ( expr, false ) ;
551
577
}
552
- self . pat ( pat ) ;
578
+ Stmt :: Item ( _ ) => ( ) ,
553
579
}
554
- Stmt :: Expr ( expr) | Stmt :: Semi ( expr, _) => {
555
- self . expr ( expr, false ) ;
580
+ let not_env_variables = take ( self . not_env_variables ) . into_iter ( ) ;
581
+ let mut vec = Vec :: with_capacity ( 2 ) ;
582
+ if not_env_variables. len ( ) != 0 {
583
+ vec. push ( parse2 ( quote ! { { #( use #not_env_variables; ) * } } ) . unwrap ( ) ) ;
556
584
}
557
- Stmt :: Item ( _) => ( ) ,
558
- }
559
- }
585
+ vec. push ( stmt) ;
586
+ vec
587
+ } )
588
+ . collect ( ) ;
560
589
}
561
590
562
591
fn expr ( & mut self , expr : & mut Expr , is_func : bool ) {
@@ -734,15 +763,7 @@ impl<'a> State<'a> {
734
763
expr : Box :: new ( a) ,
735
764
} ) ;
736
765
} else {
737
- let ident = ( * ident) . clone ( ) ;
738
- * expr = parse2 ( quote_spanned ! { expr. span( ) =>
739
- ( {
740
- use #ident;
741
- fn eq<T >( a: T , b: T ) -> T { a }
742
- eq( #expr, #expr)
743
- } )
744
- } )
745
- . unwrap ( ) ;
766
+ let _ = self . not_env_variables . insert ( ident. clone ( ) ) ;
746
767
}
747
768
}
748
769
}
0 commit comments