diff --git a/typed-builder-macro/src/lib.rs b/typed-builder-macro/src/lib.rs index a33292eb..5c15d06c 100644 --- a/typed-builder-macro/src/lib.rs +++ b/typed-builder-macro/src/lib.rs @@ -1,3 +1,5 @@ +#![forbid(rust_2018_idioms)] + use proc_macro2::TokenStream; use quote::quote; use syn::{parse::Error, parse_macro_input, spanned::Spanned, DeriveInput}; diff --git a/typed-builder-macro/src/mutator.rs b/typed-builder-macro/src/mutator.rs index 90bae1fd..bae937f4 100644 --- a/typed-builder-macro/src/mutator.rs +++ b/typed-builder-macro/src/mutator.rs @@ -52,7 +52,7 @@ impl ApplyMeta for MutatorAttribute { } impl Parse for Mutator { - fn parse(input: ParseStream) -> syn::Result { + fn parse(input: ParseStream<'_>) -> syn::Result { let mut fun: ItemFn = input.parse()?; let mut attribute = MutatorAttribute::default(); diff --git a/typed-builder-macro/src/struct_info.rs b/typed-builder-macro/src/struct_info.rs index 077bb812..399570f2 100644 --- a/typed-builder-macro/src/struct_info.rs +++ b/typed-builder-macro/src/struct_info.rs @@ -1,8 +1,10 @@ +use std::cell::OnceCell; +use std::rc::Rc; + use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote, quote_spanned, ToTokens}; -use syn::parse::Error; use syn::punctuated::Punctuated; -use syn::{parse_quote, GenericArgument, ItemFn, Token}; +use syn::{parse_quote, Error, GenericArgument, ItemFn, Token}; use crate::field_info::{FieldBuilderAttr, FieldInfo}; use crate::mutator::Mutator; @@ -16,7 +18,7 @@ pub struct StructInfo<'a> { pub vis: &'a syn::Visibility, pub name: &'a syn::Ident, pub generics: &'a syn::Generics, - pub fields: Vec>, + pub fields: Box<[FieldInfo<'a>]>, pub builder_attr: TypeBuilderAttr<'a>, pub builder_name: syn::Ident, @@ -49,7 +51,7 @@ impl<'a> StructInfo<'a> { .collect() } - pub fn new(ast: &'a syn::DeriveInput, fields: impl Iterator) -> Result, Error> { + pub fn new(ast: &'a syn::DeriveInput, fields: impl Iterator) -> syn::Result { let builder_attr = TypeBuilderAttr::new(&ast.attrs)?; let builder_name = builder_attr .builder_type @@ -70,7 +72,7 @@ impl<'a> StructInfo<'a> { }) } - pub fn builder_creation_impl(&self) -> Result { + pub fn builder_creation_impl(&self) -> syn::Result { let StructInfo { vis, ref name, @@ -85,15 +87,27 @@ impl<'a> StructInfo<'a> { empty_type() } })); - let init_fields_expr = self.included_fields().map(|f| { - f.builder_attr.via_mutators.as_ref().map_or_else( - || quote!(()), - |via_mutators| { - let init = &via_mutators.init; - quote!((#init,)) - }, - ) - }); + let builder_method_const = Rc::new(OnceCell::new()); + let init_fields_expr = self + .included_fields() + .map({ + let builder_method_const = builder_method_const.clone(); + move |f| { + f.builder_attr.via_mutators.as_ref().map_or_else( + || quote!(()), + |via_mutators| { + let init = &via_mutators.init; + if !matches!(init, syn::Expr::Lit(_)) { + _ = builder_method_const.set(quote!()); + } + quote!((#init,)) + }, + ) + } + }) + .collect::>(); + let builder_method_const = Rc::into_inner(builder_method_const).unwrap(); + let builder_method_const = OnceCell::into_inner(builder_method_const).unwrap_or_else(|| quote!(const)); let mut all_fields_param_type: syn::TypeParam = syn::Ident::new("TypedBuilderFields", proc_macro2::Span::call_site()).into(); let all_fields_param = syn::GenericParam::Type(all_fields_param_type.clone()); @@ -177,10 +191,10 @@ impl<'a> StructInfo<'a> { impl #impl_generics #name #ty_generics #where_clause { #builder_method_doc #[allow(dead_code, clippy::default_trait_access)] - #builder_method_visibility fn #builder_method_name() -> #builder_name #generics_with_empty { + #builder_method_visibility #builder_method_const fn #builder_method_name() -> #builder_name #generics_with_empty { #builder_name { fields: (#(#init_fields_expr,)*), - phantom: ::core::default::Default::default(), + phantom: ::core::marker::PhantomData, } } } @@ -206,7 +220,7 @@ impl<'a> StructInfo<'a> { }) } - pub fn field_impl(&self, field: &FieldInfo) -> Result { + pub fn field_impl(&self, field: &FieldInfo<'_>) -> syn::Result { let StructInfo { ref builder_name, .. } = *self; let descructuring = self.included_fields().map(|f| { @@ -324,12 +338,10 @@ impl<'a> StructInfo<'a> { }) } - pub fn required_field_impl(&self, field: &FieldInfo) -> TokenStream { - let StructInfo { ref builder_name, .. } = self; + pub fn required_field_impl(&self, field: &FieldInfo<'_>) -> TokenStream { + let StructInfo { builder_name, .. } = self; - let FieldInfo { - name: ref field_name, .. - } = field; + let FieldInfo { name: field_name, .. } = *field; let mut builder_generics: Vec = self .generics .params @@ -637,7 +649,7 @@ pub struct CommonDeclarationSettings { } impl ApplyMeta for CommonDeclarationSettings { - fn apply_meta(&mut self, expr: AttrArg) -> Result<(), Error> { + fn apply_meta(&mut self, expr: AttrArg) -> syn::Result<()> { match expr.name().to_string().as_str() { "vis" => { let expr_str = expr.key_value()?.parse_value::()?.value(); @@ -701,7 +713,7 @@ pub struct BuildMethodSettings { } impl ApplyMeta for BuildMethodSettings { - fn apply_meta(&mut self, expr: AttrArg) -> Result<(), Error> { + fn apply_meta(&mut self, expr: AttrArg) -> syn::Result<()> { match expr.name().to_string().as_str() { "into" => match expr { AttrArg::Flag(_) => { @@ -756,8 +768,8 @@ impl Default for TypeBuilderAttr<'_> { } } -impl<'a> TypeBuilderAttr<'a> { - pub fn new(attrs: &[syn::Attribute]) -> Result { +impl TypeBuilderAttr<'_> { + pub fn new(attrs: &[syn::Attribute]) -> syn::Result { let mut result = Self::default(); for attr in attrs { @@ -784,7 +796,7 @@ impl<'a> TypeBuilderAttr<'a> { } impl ApplyMeta for TypeBuilderAttr<'_> { - fn apply_meta(&mut self, expr: AttrArg) -> Result<(), Error> { + fn apply_meta(&mut self, expr: AttrArg) -> syn::Result<()> { match expr.name().to_string().as_str() { "crate_module_path" => { let crate_module_path = expr.key_value()?.parse_value::()?; diff --git a/typed-builder-macro/src/util.rs b/typed-builder-macro/src/util.rs index e402d328..158b61dc 100644 --- a/typed-builder-macro/src/util.rs +++ b/typed-builder-macro/src/util.rs @@ -64,7 +64,7 @@ pub fn empty_type_tuple() -> syn::TypeTuple { } } -pub fn modify_types_generics_hack(ty_generics: &syn::TypeGenerics, mut mutator: F) -> syn::AngleBracketedGenericArguments +pub fn modify_types_generics_hack(ty_generics: &syn::TypeGenerics<'_>, mut mutator: F) -> syn::AngleBracketedGenericArguments where F: FnMut(&mut syn::punctuated::Punctuated), { @@ -212,7 +212,7 @@ impl ToTokens for KeyValue { } impl Parse for KeyValue { - fn parse(input: syn::parse::ParseStream) -> syn::Result { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { Ok(Self { name: input.parse()?, eq: input.parse()?, @@ -232,7 +232,8 @@ impl SubAttr { Punctuated::::parse_terminated.parse2(self.args) } pub fn undelimited(self) -> syn::Result> { - (|p: ParseStream| iter::from_fn(|| (!p.is_empty()).then(|| p.parse())).collect::>>()).parse2(self.args) + (|p: ParseStream<'_>| iter::from_fn(|| (!p.is_empty()).then(|| p.parse())).collect::>>()) + .parse2(self.args) } } @@ -243,7 +244,7 @@ impl ToTokens for SubAttr { } } -fn get_cursor_after_parsing(input: syn::parse::ParseBuffer) -> syn::Result { +fn get_cursor_after_parsing(input: syn::parse::ParseBuffer<'_>) -> syn::Result> { let parse_attempt: P = input.parse()?; let cursor = input.cursor(); if cursor.eof() || input.peek(Token![,]) { @@ -256,7 +257,10 @@ fn get_cursor_after_parsing(input: syn::parse::ParseBuffer) } } -fn get_token_stream_up_to_cursor(input: syn::parse::ParseStream, cursor: syn::buffer::Cursor) -> syn::Result { +fn get_token_stream_up_to_cursor( + input: syn::parse::ParseStream<'_>, + cursor: syn::buffer::Cursor<'_>, +) -> syn::Result { Ok(core::iter::from_fn(|| { if input.cursor() < cursor { input.parse::().ok() @@ -268,7 +272,7 @@ fn get_token_stream_up_to_cursor(input: syn::parse::ParseStream, cursor: syn::bu } impl Parse for AttrArg { - fn parse(input: syn::parse::ParseStream) -> syn::Result { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { if input.peek(Token![!]) { Ok(Self::Not { not: input.parse()?,