@@ -75,6 +75,37 @@ pub fn expand_deriving_clone(
75
75
76
76
let inline = cx. meta_word ( span, sym:: inline) ;
77
77
let attrs = vec ! [ cx. attribute( inline) ] ;
78
+ let mut methods = vec ! [ MethodDef {
79
+ name: sym:: clone,
80
+ generics: Bounds :: empty( ) ,
81
+ explicit_self: borrowed_explicit_self( ) ,
82
+ args: Vec :: new( ) ,
83
+ ret_ty: Self_ ,
84
+ attributes: attrs,
85
+ is_unsafe: false ,
86
+ unify_fieldless_variants: false ,
87
+ combine_substructure: substructure,
88
+ } ] ;
89
+
90
+ if !is_shallow {
91
+ let substructure =
92
+ combine_substructure ( Box :: new ( |c, s, sub| cs_clone_from ( "Clone" , c, s, sub) ) ) ;
93
+
94
+ let inline = cx. meta_word ( span, sym:: inline) ;
95
+ let attrs = vec ! [ cx. attribute( inline) ] ;
96
+ methods. push ( MethodDef {
97
+ name : sym:: clone_from,
98
+ generics : Bounds :: empty ( ) ,
99
+ explicit_self : borrowed_explicit_mut_self ( ) ,
100
+ args : vec ! [ ( borrowed_self( ) , sym:: other) ] ,
101
+ ret_ty : nil_ty ( ) ,
102
+ attributes : attrs,
103
+ is_unsafe : false ,
104
+ unify_fieldless_variants : true ,
105
+ combine_substructure : substructure,
106
+ } ) ;
107
+ }
108
+
78
109
let trait_def = TraitDef {
79
110
span,
80
111
attributes : Vec :: new ( ) ,
@@ -83,17 +114,7 @@ pub fn expand_deriving_clone(
83
114
generics : Bounds :: empty ( ) ,
84
115
is_unsafe : false ,
85
116
supports_unions : true ,
86
- methods : vec ! [ MethodDef {
87
- name: sym:: clone,
88
- generics: Bounds :: empty( ) ,
89
- explicit_self: borrowed_explicit_self( ) ,
90
- args: Vec :: new( ) ,
91
- ret_ty: Self_ ,
92
- attributes: attrs,
93
- is_unsafe: false ,
94
- unify_fieldless_variants: false ,
95
- combine_substructure: substructure,
96
- } ] ,
117
+ methods,
97
118
associated_types : Vec :: new ( ) ,
98
119
} ;
99
120
@@ -217,3 +238,41 @@ fn cs_clone(
217
238
VariantData :: Unit ( ..) => cx. expr_path ( ctor_path) ,
218
239
}
219
240
}
241
+
242
+ fn cs_clone_from (
243
+ _name : & str ,
244
+ cx : & mut ExtCtxt < ' _ > ,
245
+ trait_span : Span ,
246
+ substr : & Substructure < ' _ > ,
247
+ ) -> P < Expr > {
248
+ let block = cs_fold (
249
+ true ,
250
+ |cx, span, mut block, self_f, other_fs| {
251
+ let [ other_f] = other_fs else {
252
+ cx. span_bug ( span, "not exactly 2 arguments in `derive(Clone)`" ) ;
253
+ } ;
254
+
255
+ let fn_path = cx. std_path ( & [ sym:: clone, sym:: Clone , sym:: clone_from] ) ;
256
+ let args =
257
+ vec ! [ cx. expr_addr_of_mut( span, self_f) , cx. expr_addr_of( span, other_f. clone( ) ) ] ;
258
+ let new = cx. expr_call_global ( span, fn_path, args) ;
259
+ block. stmts . push ( cx. stmt_expr ( new) ) ;
260
+ block
261
+ } ,
262
+ cx. block ( trait_span, vec ! [ ] ) ,
263
+ Box :: new ( |cx, span, _, _| {
264
+ let self_ = substr. self_args [ 0 ] . expr ( cx) ;
265
+ let other = substr. self_args [ 1 ] . expr ( cx) ;
266
+
267
+ let clone_path = cx. std_path ( & [ sym:: clone, sym:: Clone , sym:: clone] ) ;
268
+ let cloned = cx. expr_call_global ( span, clone_path, vec ! [ cx. expr_addr_of( span, other) ] ) ;
269
+
270
+ let assign = cx. expr_assign ( span, self_, cloned) ;
271
+ cx. block ( trait_span, vec ! [ cx. stmt_expr( assign) ] )
272
+ } ) ,
273
+ cx,
274
+ trait_span,
275
+ substr,
276
+ ) ;
277
+ cx. expr_block ( block)
278
+ }
0 commit comments