Skip to content

Commit

Permalink
clone: Distinguish field name from our local variable name
Browse files Browse the repository at this point in the history
This prevents name clashes with `source`.  Because of the way
clone_from works, we need to be able to bind both source and
destination field names at once.

I chose to rename some variables to reflect their purpose, rather than
relying on `2` suffixes.
  • Loading branch information
ijackson committed Jan 8, 2024
1 parent dcad41f commit 177d351
Showing 1 changed file with 22 additions and 24 deletions.
46 changes: 22 additions & 24 deletions src/trait_handlers/clone/clone_enum.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use quote::quote;
use quote::{format_ident, quote};
use syn::{punctuated::Punctuated, Data, DeriveInput, Field, Fields, Ident, Meta, Type, Variant};

use super::models::{FieldAttribute, FieldAttributeBuilder, TypeAttributeBuilder};
Expand Down Expand Up @@ -99,47 +99,45 @@ impl TraitHandler for CloneEnumHandler {
});
},
Fields::Named(_) => {
let mut pattern_token_stream = proc_macro2::TokenStream::new();
let mut pattern2_token_stream = proc_macro2::TokenStream::new();
let mut fields_token_stream = proc_macro2::TokenStream::new();
let mut body_token_stream = proc_macro2::TokenStream::new();
let mut pattern_src_token_stream = proc_macro2::TokenStream::new();
let mut pattern_dst_token_stream = proc_macro2::TokenStream::new();
let mut cl_fields_token_stream = proc_macro2::TokenStream::new();
let mut cf_body_token_stream = proc_macro2::TokenStream::new();

for (field, field_attribute) in variant_fields {
let field_name = field.ident.as_ref().unwrap();

pattern_token_stream.extend(quote!(#field_name,));

let field_name2: Ident =
syn::parse_str(&format!("_{}", field_name)).unwrap();
let field_name_real = field.ident.as_ref().unwrap();
let field_name_src = format_ident!("_s_{}", field_name_real);
let field_name_dst = format_ident!("_d_{}", field_name_real);

pattern2_token_stream.extend(quote!(#field_name: #field_name2,));
pattern_src_token_stream.extend(quote!(#field_name_real: #field_name_src,));
pattern_dst_token_stream.extend(quote!(#field_name_real: #field_name_dst,));

if let Some(clone) = field_attribute.method.as_ref() {
fields_token_stream.extend(quote! {
#field_name: #clone(#field_name),
cl_fields_token_stream.extend(quote! {
#field_name_real: #clone(#field_name_src),
});
body_token_stream
.extend(quote!(*#field_name = #clone(#field_name2);));
cf_body_token_stream
.extend(quote!(*#field_name_dst = #clone(#field_name_src);));
} else {
clone_types.push(&field.ty);

fields_token_stream.extend(quote! {
#field_name: ::core::clone::Clone::clone(#field_name),
cl_fields_token_stream.extend(quote! {
#field_name_real: ::core::clone::Clone::clone(#field_name_src),
});
body_token_stream.extend(
quote!( ::core::clone::Clone::clone_from(#field_name, #field_name2); ),
cf_body_token_stream.extend(
quote!( ::core::clone::Clone::clone_from(#field_name_dst, #field_name_src); ),
);
}
}

clone_variants_token_stream.extend(quote! {
Self::#variant_ident { #pattern_token_stream } => Self::#variant_ident { #fields_token_stream },
Self::#variant_ident { #pattern_src_token_stream } => Self::#variant_ident { #cl_fields_token_stream },
});

clone_from_variants_token_stream.extend(quote! {
Self::#variant_ident { #pattern_token_stream } => {
if let Self::#variant_ident { #pattern2_token_stream } = source {
#body_token_stream
Self::#variant_ident { #pattern_dst_token_stream } => {
if let Self::#variant_ident { #pattern_src_token_stream } = source {
#cf_body_token_stream
} else {
*self = ::core::clone::Clone::clone(source);
}
Expand Down

0 comments on commit 177d351

Please sign in to comment.