#![allow(dead_code)] #[test] fn it_works() { use dynamize::dynamize; mod some { pub mod module { pub type Result<T> = std::io::Result<T>; } } #[dynamize] /// This is a great trait! pub trait MyTrait { type A: Into<String>; // if there are multiple Into bounds the first one is used type B: Into<i32> + Into<u64>; fn test1(&self) -> Self::A; fn test2(&self) -> Self::B; fn test3(&self) -> Option<Self::B>; fn test4(&self) -> Result<(), Self::A>; fn test5(&self) -> Result<Self::A, ()>; /// some method documentation fn test6(&self) -> Result<Self::A, Self::B>; #[allow(clippy::type_complexity)] fn test7(&self) -> Result<Option<Option<Self::A>>, Option<Option<Self::B>>>; // also support Result type aliases with a fixed error type fn test8(&self) -> some::module::Result<Self::A>; // fn test9(&self) -> &dyn Iterator<Item = Self::A>; fn mut1(&mut self) -> Self::A; fn safe1(&self); fn safe2(&self, num: i32) -> i32; fn safe3<'a>(&self, text: &'a str) -> &'a str; fn safe4(&self) -> Option<i32>; // non-dispatchable functions are skipped fn non_dispatch1(); fn non_dispatch2(num: i32); fn non_dispatch3(self) -> Self::A; fn non_dispatch4(&self) where Self: Sized; } fn test<T: MyTrait>(mut some: T) { let dyn_trait: &dyn DynMyTrait = &some; let _: String = dyn_trait.test1(); let _: i32 = dyn_trait.test2(); let _: Option<i32> = dyn_trait.test3(); let _: Result<(), String> = dyn_trait.test4(); let _: Result<String, ()> = dyn_trait.test5(); let _: Result<String, i32> = dyn_trait.test6(); let _: Result<Option<Option<String>>, Option<Option<i32>>> = dyn_trait.test7(); let dyn_trait: &mut dyn DynMyTrait = &mut some; dyn_trait.mut1(); let _: () = dyn_trait.safe1(); let _: i32 = dyn_trait.safe2(0); let _: &str = dyn_trait.safe3("test"); let _: Option<i32> = dyn_trait.safe4(); } } #[dynamize::dynamize] trait Foo<X> { type A: Into<String>; fn foobar(&self, x: X) -> Self::A; } #[dynamize::dynamize] trait Bar<X> { fn foobar<A>(&self, x: X) -> A; } fn test<T: Bar<X>, X, A>(some: T) { let _dyn_trait: &dyn DynBar<X, A> = &some; } #[dynamize::dynamize] trait Bar1<X> { fn foobar<A>(&self, x: X) -> A; fn foobar1<B>(&self, x: X) -> B; fn foobar2<C>(&self, x: X) -> C; } fn test1<T: Bar1<X>, X, A, B, C>(some: T) { let _dyn_trait: &dyn DynBar1<X, A, B, C> = &some; } #[dynamize::dynamize] trait Buz<X> { type C: Into<String>; fn foobar1<A>(&self, x: X) -> Result<A, Self::C>; fn foobar2<A>(&self) -> Result<A, Self::C>; } fn test2<T: Buz<X>, X, A>(some: T, x: X) { let dyn_trait: &dyn DynBuz<X, A> = &some; let _: Result<A, String> = dyn_trait.foobar1(x); let _: Result<A, String> = dyn_trait.foobar2(); } #[dynamize::dynamize] trait Gen { fn foobar<A>(&self, a: A) -> A; } use async_trait::async_trait; #[dynamize::dynamize] #[dyn_trait_attr(async_trait)] #[blanket_impl_attr(async_trait)] #[async_trait] trait SomeTraitWithAsync: Sync { type A: Into<String>; async fn test1(&self) -> Self::A; } async fn async_test<T: SomeTraitWithAsync>(some: T) { let dyn_trait: &dyn DynSomeTraitWithAsync = &some; let _: String = dyn_trait.test1().await; } #[dynamize::dynamize] trait TraitWithCallback { type A: Into<String>; fn fun_with_callback<F: Fn(Self::A)>(&self, a: F); fn fun_with_callback1<X: Fn(Option<Self::A>)>(&self, a: X); fn fun_with_callback2<Y: Fn(i32, Option<Self::A>, String) -> bool>(&self, a: Y); fn fun_with_callback3<Z: Fn(i32)>(&self, a: Z); } #[dynamize::dynamize] #[dyn_trait_attr(async_trait)] #[blanket_impl_attr(async_trait)] #[async_trait] trait AsyncWithCallback: Sync { type A: Into<String>; async fn test1(&self) -> Self::A; async fn fun_with_callback<F: Fn(Self::A) + Sync + Send + 'static>(&self, a: F); }