@@ -19,6 +19,8 @@ use syntax::ext::build::AstBuilder;
1919use syntax:: parse:: token:: InternedString ;
2020use syntax:: ptr:: P ;
2121
22+ enum Mode { Assert , Clone }
23+
2224pub fn expand_deriving_clone ( cx : & mut ExtCtxt ,
2325 span : Span ,
2426 mitem : & MetaItem ,
@@ -39,25 +41,30 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
3941 let substructure;
4042 let nested_match;
4143 match * item {
42- Annotatable :: Item ( ref item ) => {
43- match item . node {
44+ Annotatable :: Item ( ref annitem ) => {
45+ match annitem . node {
4446 ItemKind :: Struct ( _, Generics { ref ty_params, .. } ) |
4547 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" ) => {
4750
4851 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 )
5154 } ) ) ;
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+ } ) ;
5360 }
5461
5562 _ => {
5663 bounds = vec ! [ ] ;
5764 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 )
5966 } ) ) ;
60- nested_match = true ;
67+ nested_match = None ;
6168 }
6269 }
6370 }
@@ -101,10 +108,14 @@ fn cs_shallow_clone(cx: &mut ExtCtxt, trait_span: Span) -> P<Expr> {
101108fn cs_deep_clone (
102109 name : & str ,
103110 cx : & mut ExtCtxt , trait_span : Span ,
104- substr : & Substructure ) -> P < Expr > {
111+ substr : & Substructure ,
112+ mode : Mode ) -> P < Expr > {
105113 let ctor_path;
106114 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+ } ;
108119 let subcall = |field : & FieldInfo | {
109120 let args = vec ! [ cx. expr_addr_of( field. span, field. self_. clone( ) ) ] ;
110121
@@ -134,29 +145,41 @@ fn cs_deep_clone(
134145 }
135146 }
136147
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 ) )
152156 }
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+ }
160183 }
161184 }
162185}
0 commit comments