Skip to content

Commit a401bb0

Browse files
committed
clone_from derive macro impl
1 parent 9d1aeae commit a401bb0

File tree

4 files changed

+198
-71
lines changed

4 files changed

+198
-71
lines changed

compiler/rustc_builtin_macros/src/deriving/clone.rs

+70-11
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)