use crate::add_assign_like; use crate::mul_helpers::generics_and_exprs; use crate::utils::{AttrParams, MultiFieldData, RefType, State}; use proc_macro2::{Span, TokenStream}; use quote::quote; use std::collections::HashSet; use std::iter; use syn::{DeriveInput, Ident, Result}; pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result { let method_name = trait_name .to_lowercase() .trim_end_matches("assign") .to_string() + "_assign"; let mut state = State::with_attr_params( input, trait_name, quote!(::core::ops), method_name, AttrParams::struct_(vec!["forward"]), )?; if state.default_info.forward { return Ok(add_assign_like::expand(input, trait_name)); } let scalar_ident = &Ident::new("__RhsT", Span::call_site()); state.add_trait_path_type_param(quote!(#scalar_ident)); let multi_field_data = state.enabled_fields_data(); let MultiFieldData { input_type, field_types, ty_generics, trait_path, trait_path_with_params, method_ident, .. } = multi_field_data.clone(); let tys = field_types.iter().collect::>(); let tys = tys.iter(); let trait_path_iter = iter::repeat(trait_path_with_params); let type_where_clauses = quote! { where #(#tys: #trait_path_iter),* }; let (generics, exprs) = generics_and_exprs( multi_field_data.clone(), scalar_ident, type_where_clauses, RefType::Mut, ); let (impl_generics, _, where_clause) = generics.split_for_impl(); Ok(quote!( impl#impl_generics #trait_path<#scalar_ident> for #input_type#ty_generics #where_clause{ #[inline] fn #method_ident(&mut self, rhs: #scalar_ident) { #(#exprs; )* } } )) }