diff options
Diffstat (limited to 'third_party/rust/derive_more-impl/src/as_mut.rs')
-rw-r--r-- | third_party/rust/derive_more-impl/src/as_mut.rs | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/third_party/rust/derive_more-impl/src/as_mut.rs b/third_party/rust/derive_more-impl/src/as_mut.rs new file mode 100644 index 0000000000..1d05adc505 --- /dev/null +++ b/third_party/rust/derive_more-impl/src/as_mut.rs @@ -0,0 +1,81 @@ +use crate::utils::{ + add_where_clauses_for_new_ident, AttrParams, MultiFieldData, State, +}; +use proc_macro2::TokenStream; +use quote::{format_ident, quote}; +use syn::{parse::Result, DeriveInput}; + +pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> { + let as_mut_type = format_ident!("__AsMutT"); + let state = State::with_type_bound( + input, + trait_name, + "as_mut".into(), + AttrParams::ignore_and_forward(), + false, + )?; + let MultiFieldData { + fields, + input_type, + members, + infos, + trait_path, + impl_generics, + ty_generics, + where_clause, + .. + } = state.enabled_fields_data(); + let sub_items: Vec<_> = infos + .iter() + .zip(members.iter()) + .zip(fields) + .map(|((info, member), field)| { + let field_type = &field.ty; + if info.forward { + let trait_path = quote! { #trait_path<#as_mut_type> }; + let type_where_clauses = quote! { + where #field_type: #trait_path + }; + let new_generics = add_where_clauses_for_new_ident( + &input.generics, + &[field], + &as_mut_type, + type_where_clauses, + false, + ); + let (impl_generics, _, where_clause) = new_generics.split_for_impl(); + let casted_trait = quote! { <#field_type as #trait_path> }; + ( + quote! { #casted_trait::as_mut(&mut #member) }, + quote! { #impl_generics }, + quote! { #where_clause }, + quote! { #trait_path }, + quote! { #as_mut_type }, + ) + } else { + ( + quote! { &mut #member }, + quote! { #impl_generics }, + quote! { #where_clause }, + quote! { #trait_path<#field_type> }, + quote! { #field_type }, + ) + } + }) + .collect(); + let bodies = sub_items.iter().map(|i| &i.0); + let impl_genericses = sub_items.iter().map(|i| &i.1); + let where_clauses = sub_items.iter().map(|i| &i.2); + let trait_paths = sub_items.iter().map(|i| &i.3); + let return_types = sub_items.iter().map(|i| &i.4); + + Ok(quote! {#( + #[automatically_derived] + impl #impl_genericses #trait_paths for #input_type #ty_generics #where_clauses { + #[inline] + fn as_mut(&mut self) -> &mut #return_types { + #bodies + } + } + )*}) +} |