From 177d351e7acc4a5adb473f92c4c469378deddca3 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 8 Jan 2024 13:13:00 +0000 Subject: [PATCH] clone: Distinguish field name from our local variable name 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. --- src/trait_handlers/clone/clone_enum.rs | 46 ++++++++++++-------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/src/trait_handlers/clone/clone_enum.rs b/src/trait_handlers/clone/clone_enum.rs index ad89ff1..437d430 100644 --- a/src/trait_handlers/clone/clone_enum.rs +++ b/src/trait_handlers/clone/clone_enum.rs @@ -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}; @@ -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); }