@@ -19,6 +19,8 @@ use syntax::ext::build::AstBuilder;
19
19
use syntax:: parse:: token:: InternedString ;
20
20
use syntax:: ptr:: P ;
21
21
22
+ enum Mode { Assert , Clone }
23
+
22
24
pub fn expand_deriving_clone ( cx : & mut ExtCtxt ,
23
25
span : Span ,
24
26
mitem : & MetaItem ,
@@ -39,25 +41,30 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
39
41
let substructure;
40
42
let nested_match;
41
43
match * item {
42
- Annotatable :: Item ( ref item ) => {
43
- match item . node {
44
+ Annotatable :: Item ( ref annitem ) => {
45
+ match annitem . node {
44
46
ItemKind :: Struct ( _, Generics { ref ty_params, .. } ) |
45
47
ItemKind :: Enum ( _, Generics { ref ty_params, .. } )
46
- if ty_params. is_empty ( ) && attr:: contains_name ( & item. attrs , "derive_Copy" ) => {
48
+ if ty_params. is_empty ( )
49
+ && attr:: contains_name ( & annitem. attrs , "derive_Copy" ) => {
47
50
48
51
bounds = vec ! [ Literal ( path_std!( cx, core:: marker:: Copy ) ) ] ;
49
- substructure = combine_substructure ( Box :: new ( |c, s, _ | {
50
- cs_shallow_clone ( c, s)
52
+ substructure = combine_substructure ( Box :: new ( |c, s, sub | {
53
+ cs_deep_clone ( "Clone" , c, s, sub , Mode :: Assert )
51
54
} ) ) ;
52
- nested_match = false ;
55
+ nested_match = enclose ( |c, s, sub| {
56
+ let inner = cs_shallow_clone ( c, s) ;
57
+ c. expr_block ( c. block_all ( s, vec ! [ c. stmt_expr( sub) ] , Some ( inner) ) )
58
+ //^ FIXME(aburka): this generates an extra set of {} braces
59
+ } ) ;
53
60
}
54
61
55
62
_ => {
56
63
bounds = vec ! [ ] ;
57
64
substructure = combine_substructure ( Box :: new ( |c, s, sub| {
58
- cs_deep_clone ( "Clone" , c, s, sub)
65
+ cs_deep_clone ( "Clone" , c, s, sub, Mode :: Clone )
59
66
} ) ) ;
60
- nested_match = true ;
67
+ nested_match = None ;
61
68
}
62
69
}
63
70
}
@@ -101,10 +108,14 @@ fn cs_shallow_clone(cx: &mut ExtCtxt, trait_span: Span) -> P<Expr> {
101
108
fn cs_deep_clone (
102
109
name : & str ,
103
110
cx : & mut ExtCtxt , trait_span : Span ,
104
- substr : & Substructure ) -> P < Expr > {
111
+ substr : & Substructure ,
112
+ mode : Mode ) -> P < Expr > {
105
113
let ctor_path;
106
114
let all_fields;
107
- let fn_path = cx. std_path ( & [ "clone" , "Clone" , "clone" ] ) ;
115
+ let fn_path = match mode {
116
+ Mode :: Assert => cx. std_path ( & [ "clone" , "assert_receiver_is_clone" ] ) ,
117
+ Mode :: Clone => cx. std_path ( & [ "clone" , "Clone" , "clone" ] ) ,
118
+ } ;
108
119
let subcall = |field : & FieldInfo | {
109
120
let args = vec ! [ cx. expr_addr_of( field. span, field. self_. clone( ) ) ] ;
110
121
@@ -134,29 +145,41 @@ fn cs_deep_clone(
134
145
}
135
146
}
136
147
137
- match * vdata {
138
- VariantData :: Struct ( ..) => {
139
- let fields = all_fields. iter ( ) . map ( |field| {
140
- let ident = match field. name {
141
- Some ( i) => i,
142
- None => {
143
- cx. span_bug ( trait_span,
144
- & format ! ( "unnamed field in normal struct in \
145
- `derive({})`", name) )
146
- }
147
- } ;
148
- cx. field_imm ( field. span , ident, subcall ( field) )
149
- } ) . collect :: < Vec < _ > > ( ) ;
150
-
151
- cx. expr_struct ( trait_span, ctor_path, fields)
148
+ match mode {
149
+ Mode :: Assert => {
150
+ cx. expr_block ( cx. block ( trait_span,
151
+ all_fields. iter ( )
152
+ . map ( subcall)
153
+ . map ( |e| cx. stmt_expr ( e) )
154
+ . collect ( ) ,
155
+ None ) )
152
156
}
153
- VariantData :: Tuple ( ..) => {
154
- let subcalls = all_fields. iter ( ) . map ( subcall) . collect ( ) ;
155
- let path = cx. expr_path ( ctor_path) ;
156
- cx. expr_call ( trait_span, path, subcalls)
157
- }
158
- VariantData :: Unit ( ..) => {
159
- cx. expr_path ( ctor_path)
157
+ Mode :: Clone => {
158
+ match * vdata {
159
+ VariantData :: Struct ( ..) => {
160
+ let fields = all_fields. iter ( ) . map ( |field| {
161
+ let ident = match field. name {
162
+ Some ( i) => i,
163
+ None => {
164
+ cx. span_bug ( trait_span,
165
+ & format ! ( "unnamed field in normal struct in \
166
+ `derive({})`", name) )
167
+ }
168
+ } ;
169
+ cx. field_imm ( field. span , ident, subcall ( field) )
170
+ } ) . collect :: < Vec < _ > > ( ) ;
171
+
172
+ cx. expr_struct ( trait_span, ctor_path, fields)
173
+ }
174
+ VariantData :: Tuple ( ..) => {
175
+ let subcalls = all_fields. iter ( ) . map ( subcall) . collect ( ) ;
176
+ let path = cx. expr_path ( ctor_path) ;
177
+ cx. expr_call ( trait_span, path, subcalls)
178
+ }
179
+ VariantData :: Unit ( ..) => {
180
+ cx. expr_path ( ctor_path)
181
+ }
182
+ }
160
183
}
161
184
}
162
185
}
0 commit comments