diff --git a/src/derive/arc.rs b/src/derive/arc.rs index 7971b53..014db0c 100644 --- a/src/derive/arc.rs +++ b/src/derive/arc.rs @@ -3,6 +3,7 @@ use syn::spanned::Spanned; use crate::utils::deref_expr; use crate::utils::generics_declaration_to_generics; +use crate::utils::signature_to_associated_function_call; use crate::utils::signature_to_method_call; use crate::utils::trait_to_generic_ident; @@ -32,7 +33,7 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result { let mut assoc_types: Vec = Vec::new(); for item in trait_.items.iter() { if let syn::TraitItem::Fn(ref m) = item { - if let Some(r) = m.sig.receiver() { + let call: syn::Expr = if let Some(r) = m.sig.receiver() { let err = if r.colon_token.is_some() { Some("cannot derive `Arc` for a trait declaring methods with arbitrary receiver types") } else if r.mutability.is_some() { @@ -45,10 +46,19 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result { if let Some(msg) = err { return Err(syn::Error::new(r.span(), msg)); } - } - let mut call = signature_to_method_call(&m.sig)?; - call.receiver = Box::new(deref_expr(deref_expr(*call.receiver))); + let mut call = signature_to_method_call(&m.sig)?; + call.receiver = Box::new(deref_expr(deref_expr(*call.receiver))); + call.into() + } else { + let call = signature_to_associated_function_call( + &m.sig, + &trait_ident, + &generic_type, + &trait_generic_names, + )?; + call.into() + }; let signature = &m.sig; let item = parse_quote!(#[inline] #signature { #call }); diff --git a/src/derive/box.rs b/src/derive/box.rs index 7ed5bd5..5401443 100644 --- a/src/derive/box.rs +++ b/src/derive/box.rs @@ -1,7 +1,8 @@ use syn::{parse_quote, spanned::Spanned}; use crate::utils::{ - deref_expr, generics_declaration_to_generics, signature_to_method_call, trait_to_generic_ident, + deref_expr, generics_declaration_to_generics, signature_to_associated_function_call, + signature_to_method_call, trait_to_generic_ident, }; pub fn derive(trait_: &syn::ItemTrait) -> syn::Result { @@ -30,10 +31,8 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result { let mut assoc_types: Vec = Vec::new(); for item in trait_.items.iter() { if let syn::TraitItem::Fn(ref m) = item { - let signature = &m.sig; - let mut call = signature_to_method_call(signature)?; - - if let Some(r) = m.sig.receiver() { + let call: syn::Expr = if let Some(r) = m.sig.receiver() { + let mut call = signature_to_method_call(&m.sig)?; let err = if r.colon_token.is_some() { Some("cannot derive `Box` for a trait declaring methods with arbitrary receiver types") } else if r.reference.is_some() { @@ -46,12 +45,20 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result { if let Some(msg) = err { return Err(syn::Error::new(r.span(), msg)); } + call.into() } else { - unimplemented!() - } + let call = signature_to_associated_function_call( + &m.sig, + &trait_ident, + &generic_type, + &trait_generic_names, + )?; + call.into() + }; + let signature = &m.sig; let item = parse_quote!(#[inline] #signature { #call }); - methods.push(item) + methods.push(item); } if let syn::TraitItem::Type(t) = item { diff --git a/src/derive/mut.rs b/src/derive/mut.rs index 0043806..c8792c6 100644 --- a/src/derive/mut.rs +++ b/src/derive/mut.rs @@ -1,7 +1,8 @@ use syn::{parse_quote, spanned::Spanned}; use crate::utils::{ - deref_expr, generics_declaration_to_generics, signature_to_method_call, trait_to_generic_ident, + deref_expr, generics_declaration_to_generics, signature_to_associated_function_call, + signature_to_method_call, trait_to_generic_ident, }; pub fn derive(trait_: &syn::ItemTrait) -> syn::Result { @@ -30,7 +31,7 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result { let mut assoc_types: Vec = Vec::new(); for item in trait_.items.iter() { if let syn::TraitItem::Fn(ref m) = item { - if let Some(r) = m.sig.receiver() { + let call: syn::Expr = if let Some(r) = m.sig.receiver() { let err = if r.colon_token.is_some() { Some("cannot derive `Mut` for a trait declaring methods with arbitrary receiver types") } else if r.reference.is_none() { @@ -41,10 +42,19 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result { if let Some(msg) = err { return Err(syn::Error::new(r.span(), msg)); } - } - let mut call = signature_to_method_call(&m.sig)?; - call.receiver = Box::new(deref_expr(deref_expr(*call.receiver))); + let mut call = signature_to_method_call(&m.sig)?; + call.receiver = Box::new(deref_expr(deref_expr(*call.receiver))); + call.into() + } else { + let call = signature_to_associated_function_call( + &m.sig, + &trait_ident, + &generic_type, + &trait_generic_names, + )?; + call.into() + }; let signature = &m.sig; let item = parse_quote!(#[inline] #signature { #call }); diff --git a/src/derive/rc.rs b/src/derive/rc.rs index 64197ec..35a8e7e 100644 --- a/src/derive/rc.rs +++ b/src/derive/rc.rs @@ -1,7 +1,8 @@ use syn::{parse_quote, spanned::Spanned}; use crate::utils::{ - deref_expr, generics_declaration_to_generics, signature_to_method_call, trait_to_generic_ident, + deref_expr, generics_declaration_to_generics, signature_to_associated_function_call, + signature_to_method_call, trait_to_generic_ident, }; pub fn derive(trait_: &syn::ItemTrait) -> syn::Result { @@ -30,7 +31,7 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result { let mut assoc_types: Vec = Vec::new(); for item in trait_.items.iter() { if let syn::TraitItem::Fn(ref m) = item { - if let Some(r) = m.sig.receiver() { + let call: syn::Expr = if let Some(r) = m.sig.receiver() { let err = if r.colon_token.is_some() { Some("cannot derive `Rc` for a trait declaring methods with arbitrary receiver types") } else if r.mutability.is_some() { @@ -43,10 +44,18 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result { if let Some(msg) = err { return Err(syn::Error::new(r.span(), msg)); } - } - - let mut call = signature_to_method_call(&m.sig)?; - call.receiver = Box::new(deref_expr(deref_expr(*call.receiver))); + let mut call = signature_to_method_call(&m.sig)?; + call.receiver = Box::new(deref_expr(deref_expr(*call.receiver))); + call.into() + } else { + let call = signature_to_associated_function_call( + &m.sig, + &trait_ident, + &generic_type, + &trait_generic_names, + )?; + call.into() + }; let signature = &m.sig; let item = parse_quote!(#[inline] #signature { #call }); diff --git a/tests/derive_arc/successes/assoc_function.rs b/tests/derive_arc/successes/assoc_function.rs new file mode 100644 index 0000000..76e45ee --- /dev/null +++ b/tests/derive_arc/successes/assoc_function.rs @@ -0,0 +1,21 @@ +use blanket::blanket; +use impls::impls; + +use std::sync::Arc; + +#[blanket(derive(Arc))] +pub trait StaticChecker { + fn check(); +} + +#[derive(Default)] +struct NoOpChecker; + +impl StaticChecker for NoOpChecker { + fn check() {} +} + +fn main() { + assert!(impls!( NoOpChecker: StaticChecker)); + assert!(impls!(Arc: StaticChecker)); +} diff --git a/tests/derive_box/successes/assoc_function.rs b/tests/derive_box/successes/assoc_function.rs new file mode 100644 index 0000000..e28428d --- /dev/null +++ b/tests/derive_box/successes/assoc_function.rs @@ -0,0 +1,19 @@ +use blanket::blanket; +use impls::impls; + +#[blanket(derive(Box))] +pub trait StaticChecker { + fn check(); +} + +#[derive(Default)] +struct NoOpChecker; + +impl StaticChecker for NoOpChecker { + fn check() {} +} + +fn main() { + assert!(impls!( NoOpChecker: StaticChecker)); + assert!(impls!(Box: StaticChecker)); +} diff --git a/tests/derive_mut/successes/assoc_function.rs b/tests/derive_mut/successes/assoc_function.rs new file mode 100644 index 0000000..41a8a78 --- /dev/null +++ b/tests/derive_mut/successes/assoc_function.rs @@ -0,0 +1,19 @@ +use blanket::blanket; +use impls::impls; + +#[blanket(derive(Mut))] +pub trait StaticChecker { + fn check(); +} + +#[derive(Default)] +struct NoOpChecker; + +impl StaticChecker for NoOpChecker { + fn check() {} +} + +fn main() { + assert!(impls!( NoOpChecker: StaticChecker)); + assert!(impls!(&mut NoOpChecker: StaticChecker)); +} diff --git a/tests/derive_rc/successes/assoc_function.rs b/tests/derive_rc/successes/assoc_function.rs new file mode 100644 index 0000000..5ae763a --- /dev/null +++ b/tests/derive_rc/successes/assoc_function.rs @@ -0,0 +1,21 @@ +use blanket::blanket; +use impls::impls; + +use std::rc::Rc; + +#[blanket(derive(Rc))] +pub trait StaticChecker { + fn check(); +} + +#[derive(Default)] +struct NoOpChecker; + +impl StaticChecker for NoOpChecker { + fn check() {} +} + +fn main() { + assert!(impls!( NoOpChecker: StaticChecker)); + assert!(impls!(Rc: StaticChecker)); +} diff --git a/tests/derive_ref/successes/static_method.rs b/tests/derive_ref/successes/assoc_function.rs similarity index 84% rename from tests/derive_ref/successes/static_method.rs rename to tests/derive_ref/successes/assoc_function.rs index 3b5b737..252dd8b 100644 --- a/tests/derive_ref/successes/static_method.rs +++ b/tests/derive_ref/successes/assoc_function.rs @@ -14,6 +14,6 @@ impl StaticChecker for NoOpChecker { } fn main() { - assert!(impls!(NoOpChecker: StaticChecker)); + assert!(impls!( NoOpChecker: StaticChecker)); assert!(impls!(&NoOpChecker: StaticChecker)); }