Skip to content

Commit

Permalink
Implement associated function for all remaining derives and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
althonos committed Mar 3, 2024
1 parent ae73aa6 commit 1851c1f
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 24 deletions.
18 changes: 14 additions & 4 deletions src/derive/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -32,7 +33,7 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result<syn::ItemImpl> {
let mut assoc_types: Vec<syn::ImplItemType> = 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() {
Expand All @@ -45,10 +46,19 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result<syn::ItemImpl> {
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 });
Expand Down
23 changes: 15 additions & 8 deletions src/derive/box.rs
Original file line number Diff line number Diff line change
@@ -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<syn::ItemImpl> {
Expand Down Expand Up @@ -30,10 +31,8 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result<syn::ItemImpl> {
let mut assoc_types: Vec<syn::ImplItemType> = 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() {
Expand All @@ -46,12 +45,20 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result<syn::ItemImpl> {
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 {
Expand Down
20 changes: 15 additions & 5 deletions src/derive/mut.rs
Original file line number Diff line number Diff line change
@@ -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<syn::ItemImpl> {
Expand Down Expand Up @@ -30,7 +31,7 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result<syn::ItemImpl> {
let mut assoc_types: Vec<syn::ImplItemType> = 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() {
Expand All @@ -41,10 +42,19 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result<syn::ItemImpl> {
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 });
Expand Down
21 changes: 15 additions & 6 deletions src/derive/rc.rs
Original file line number Diff line number Diff line change
@@ -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<syn::ItemImpl> {
Expand Down Expand Up @@ -30,7 +31,7 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result<syn::ItemImpl> {
let mut assoc_types: Vec<syn::ImplItemType> = 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() {
Expand All @@ -43,10 +44,18 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result<syn::ItemImpl> {
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 });
Expand Down
21 changes: 21 additions & 0 deletions tests/derive_arc/successes/assoc_function.rs
Original file line number Diff line number Diff line change
@@ -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<NoOpChecker>: StaticChecker));
}
19 changes: 19 additions & 0 deletions tests/derive_box/successes/assoc_function.rs
Original file line number Diff line number Diff line change
@@ -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<NoOpChecker>: StaticChecker));
}
19 changes: 19 additions & 0 deletions tests/derive_mut/successes/assoc_function.rs
Original file line number Diff line number Diff line change
@@ -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));
}
21 changes: 21 additions & 0 deletions tests/derive_rc/successes/assoc_function.rs
Original file line number Diff line number Diff line change
@@ -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<NoOpChecker>: StaticChecker));
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ impl StaticChecker for NoOpChecker {
}

fn main() {
assert!(impls!(NoOpChecker: StaticChecker));
assert!(impls!( NoOpChecker: StaticChecker));
assert!(impls!(&NoOpChecker: StaticChecker));
}

0 comments on commit 1851c1f

Please sign in to comment.