diff --git a/src/data.rs b/src/data.rs index 000ea0db2..9e73f02d3 100644 --- a/src/data.rs +++ b/src/data.rs @@ -105,42 +105,44 @@ impl Fields { } } - /// Get an iterator over the fields of a struct or variant as [`Member`]s. - /// This iterator can be used to iterate over a named or unnamed struct or - /// variant's fields uniformly. - /// - /// # Example - /// - /// The following is a simplistic [`Clone`] derive for structs. (A more - /// complete implementation would additionally want to infer trait bounds on - /// the generic type parameters.) - /// - /// ``` - /// # use quote::quote; - /// # - /// fn derive_clone(input: &syn::ItemStruct) -> proc_macro2::TokenStream { - /// let ident = &input.ident; - /// let members = input.fields.members(); - /// let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); - /// quote! { - /// impl #impl_generics Clone for #ident #ty_generics #where_clause { - /// fn clone(&self) -> Self { - /// Self { - /// #(#members: self.#members.clone()),* - /// } - /// } - /// } - /// } - /// } - /// ``` - /// - /// For structs with named fields, it produces an expression like `Self { a: - /// self.a.clone() }`. For structs with unnamed fields, `Self { 0: - /// self.0.clone() }`. And for unit structs, `Self {}`. - pub fn members(&self) -> impl Iterator + Clone + '_ { - Members { - fields: self.iter(), - index: 0, + return_impl_trait! { + /// Get an iterator over the fields of a struct or variant as [`Member`]s. + /// This iterator can be used to iterate over a named or unnamed struct or + /// variant's fields uniformly. + /// + /// # Example + /// + /// The following is a simplistic [`Clone`] derive for structs. (A more + /// complete implementation would additionally want to infer trait bounds on + /// the generic type parameters.) + /// + /// ``` + /// # use quote::quote; + /// # + /// fn derive_clone(input: &syn::ItemStruct) -> proc_macro2::TokenStream { + /// let ident = &input.ident; + /// let members = input.fields.members(); + /// let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + /// quote! { + /// impl #impl_generics Clone for #ident #ty_generics #where_clause { + /// fn clone(&self) -> Self { + /// Self { + /// #(#members: self.#members.clone()),* + /// } + /// } + /// } + /// } + /// } + /// ``` + /// + /// For structs with named fields, it produces an expression like `Self { a: + /// self.a.clone() }`. For structs with unnamed fields, `Self { 0: + /// self.0.clone() }`. And for unit structs, `Self {}`. + pub fn members(&self) -> impl Iterator + Clone + '_ [Members] { + Members { + fields: self.iter(), + index: 0, + } } } } diff --git a/src/generics.rs b/src/generics.rs index 0aff7cecd..692ad5300 100644 --- a/src/generics.rs +++ b/src/generics.rs @@ -103,34 +103,46 @@ impl Default for Generics { } impl Generics { - /// Iterator over the lifetime parameters in `self.params`. - pub fn lifetimes(&self) -> impl Iterator { - Lifetimes(self.params.iter()) + return_impl_trait! { + /// Iterator over the lifetime parameters in `self.params`. + pub fn lifetimes(&self) -> impl Iterator [Lifetimes] { + Lifetimes(self.params.iter()) + } } - /// Iterator over the lifetime parameters in `self.params`. - pub fn lifetimes_mut(&mut self) -> impl Iterator { - LifetimesMut(self.params.iter_mut()) + return_impl_trait! { + /// Iterator over the lifetime parameters in `self.params`. + pub fn lifetimes_mut(&mut self) -> impl Iterator [LifetimesMut] { + LifetimesMut(self.params.iter_mut()) + } } - /// Iterator over the type parameters in `self.params`. - pub fn type_params(&self) -> impl Iterator { - TypeParams(self.params.iter()) + return_impl_trait! { + /// Iterator over the type parameters in `self.params`. + pub fn type_params(&self) -> impl Iterator [TypeParams] { + TypeParams(self.params.iter()) + } } - /// Iterator over the type parameters in `self.params`. - pub fn type_params_mut(&mut self) -> impl Iterator { - TypeParamsMut(self.params.iter_mut()) + return_impl_trait! { + /// Iterator over the type parameters in `self.params`. + pub fn type_params_mut(&mut self) -> impl Iterator [TypeParamsMut] { + TypeParamsMut(self.params.iter_mut()) + } } - /// Iterator over the constant parameters in `self.params`. - pub fn const_params(&self) -> impl Iterator { - ConstParams(self.params.iter()) + return_impl_trait! { + /// Iterator over the constant parameters in `self.params`. + pub fn const_params(&self) -> impl Iterator [ConstParams] { + ConstParams(self.params.iter()) + } } - /// Iterator over the constant parameters in `self.params`. - pub fn const_params_mut(&mut self) -> impl Iterator { - ConstParamsMut(self.params.iter_mut()) + return_impl_trait! { + /// Iterator over the constant parameters in `self.params`. + pub fn const_params_mut(&mut self) -> impl Iterator [ConstParamsMut] { + ConstParamsMut(self.params.iter_mut()) + } } /// Initializes an empty `where`-clause if there is not one present already. diff --git a/src/macros.rs b/src/macros.rs index 2b6708d49..167f2cf26 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -164,3 +164,19 @@ macro_rules! check_keyword_matches { (pub pub) => {}; (struct struct) => {}; } + +#[cfg(any(feature = "full", feature = "derive"))] +macro_rules! return_impl_trait { + ( + $(#[$attr:meta])* + $vis:vis fn $name:ident $args:tt -> $impl_trait:ty [$concrete:ty] $body:block + ) => { + #[cfg(not(docsrs))] + $(#[$attr])* + $vis fn $name $args -> $concrete $body + + #[cfg(docsrs)] + $(#[$attr])* + $vis fn $name $args -> $impl_trait $body + }; +}