@@ -75,6 +75,37 @@ pub fn expand_deriving_clone(
7575
7676 let inline = cx. meta_word ( span, sym:: inline) ;
7777 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+
78109 let trait_def = TraitDef {
79110 span,
80111 attributes : Vec :: new ( ) ,
@@ -83,17 +114,7 @@ pub fn expand_deriving_clone(
83114 generics : Bounds :: empty ( ) ,
84115 is_unsafe : false ,
85116 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,
97118 associated_types : Vec :: new ( ) ,
98119 } ;
99120
@@ -217,3 +238,41 @@ fn cs_clone(
217238 VariantData :: Unit ( ..) => cx. expr_path ( ctor_path) ,
218239 }
219240}
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