#![allow(dead_code)] #[test] fn it_works() { use dynamize::dynamize; mod some { pub mod module { pub type Result = std::io::Result; } } #[dynamize] /// This is a great trait! pub trait MyTrait { type A: Into; // if there are multiple Into bounds the first one is used type B: Into + Into; fn test1(&self) -> Self::A; fn test2(&self) -> Self::B; fn test3(&self) -> Option; fn test4(&self) -> Result<(), Self::A>; fn test5(&self) -> Result; /// some method documentation fn test6(&self) -> Result; #[allow(clippy::type_complexity)] fn test7(&self) -> Result>, Option>>; // also support Result type aliases with a fixed error type fn test8(&self) -> some::module::Result; fn test9(&self) -> (Self::A, Self::B); #[allow(clippy::type_complexity)] fn test10(&self) -> (Self::A, (Self::A, Self::B), Self::B); fn test11(&self) -> ::A; // fn test9(&self) -> &dyn Iterator; 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; // 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(mut some: T) { let dyn_trait: &dyn DynMyTrait = &some; let _: String = dyn_trait.test1(); let _: i32 = dyn_trait.test2(); let _: Option = dyn_trait.test3(); let _: Result<(), String> = dyn_trait.test4(); let _: Result = dyn_trait.test5(); let _: Result = dyn_trait.test6(); let _: Result>, Option>> = 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 = dyn_trait.safe4(); } } #[dynamize::dynamize] trait Foo { type A: Into; fn foobar(&self, x: X) -> Self::A; } #[dynamize::dynamize] trait FooWithWhere where X: std::fmt::Display, { type A: Into; fn foobar(&self, x: X) -> Self::A; } #[dynamize::dynamize] trait Bar { fn foobar(&self, x: X) -> A; } fn test, X, A>(some: T) { let _dyn_trait: &dyn DynBar = &some; } #[dynamize::dynamize] trait Bar1 { fn foobar(&self, x: X) -> A; fn foobar1(&self, x: X) -> B; fn foobar2(&self, x: X) -> C; } fn test1, X, A, B, C>(some: T) { let _dyn_trait: &dyn DynBar1 = &some; } #[dynamize::dynamize] trait Buz { type C: Into; fn foobar1(&self, x: X) -> Result; fn foobar2(&self) -> Result; } fn test2, X, A>(some: T, x: X) { let dyn_trait: &dyn DynBuz = &some; let _: Result = dyn_trait.foobar1(x); let _: Result = dyn_trait.foobar2(); } #[dynamize::dynamize] trait Gen { fn foobar(&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; async fn test1(&self) -> Self::A; } async fn async_test(some: T) { let dyn_trait: &dyn DynSomeTraitWithAsync = &some; let _: String = dyn_trait.test1().await; } #[dynamize::dynamize] trait TraitWithCallback { type A: Into; fn fun_with_callback(&self, a: F); fn fun_with_callback0(&self, a: G) where G: Fn(Self::A); fn fun_with_callback1)>(&self, a: X); fn fun_with_callback2, String) -> bool>(&self, a: Y); fn fun_with_callback3(&self, a: Z); } #[dynamize::dynamize] #[dyn_trait_attr(async_trait)] #[blanket_impl_attr(async_trait)] #[async_trait] trait AsyncWithCallback: Sync { type A: Into; async fn test1(&self) -> Self::A; async fn fun_with_callback(&self, a: F); } #[dynamize::dynamize] trait TypeTraitBound { type A: std::error::Error; fn foobar(&self, text: &str) -> Result; } fn type_trait_bound_test(t: T) { let dyn_trait: &dyn DynTypeTraitBound = &t; let _: Result> = dyn_trait.foobar("test"); } #[dynamize::dynamize] trait TypeTraitBoundStatic { type A: std::error::Error + 'static; fn foobar(&self, text: &str) -> Result; } fn type_trait_bound_static_test( t: Box, ) -> Option> { t.foobar("test").err() } #[dynamize::dynamize] trait TypeWithSuper: std::fmt::Display + Sized { type A: std::error::Error; fn foobar(&self, text: &str) -> Result; } fn test3(some: T) { let dyn_trait: &dyn DynTypeWithSuper = &some; println!("{}", dyn_trait); } use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; #[dynamize::dynamize] trait Collections { type A: std::error::Error; fn vec(&self) -> Vec; fn vec_deque(&self) -> VecDeque; fn linked_list(&self) -> LinkedList; fn vec_opt(&self) -> Vec>; } #[dynamize::dynamize] trait CollectionsRequiringEq { type A: Into; fn hashset(&self) -> HashSet; fn binary_heap(&self) -> BinaryHeap; fn btree_set(&self) -> BTreeSet; fn hash_map(&self) -> HashMap; fn btree_map(&self) -> BTreeMap; } #[dynamize::dynamize] trait ReturnIter { type A: std::error::Error; fn foobar(&mut self, text: &str) -> &mut dyn Iterator; } #[dynamize::dynamize] trait FunIter { type A: std::error::Error + Send; fn foobar)>(&mut self, f: F); fn foobar1>)>(&mut self, f: G); fn foobar2>)>(&mut self, f: H); } struct MyCollection(A, B, C); impl IntoIterator for MyCollection { type Item = (A, B, C); type IntoIter = Box>; fn into_iter(self) -> Self::IntoIter { todo!() } } impl FromIterator<(A, B, C)> for MyCollection { fn from_iter>(_iter: T) -> Self { todo!() } } #[dynamize::dynamize] #[collection(MyCollection, 3)] trait CustomCollection { type A: Into; fn test(&self) -> MyCollection; } #[dynamize::dynamize] trait SomeTrait { type Y: Into; fn foo(&self) -> Self::Y; } #[dynamize::dynamize] #[dynamized(SomeTrait)] trait OneTrait: SomeTrait { type X: Into; fn test(&self) -> Self::X; } #[dynamize::dynamize] #[dynamized(Foo)] trait OtherTrait: Foo {} struct SuperError; trait Cache {} #[dynamize::dynamize] trait Client { type Error: std::error::Error; fn get(&self, url: String) -> Result, Self::Error>; } #[dynamize::dynamize] #[dynamized(Client)] #[convert = |x: ::Error| -> Box {Box::new(x) as _}] trait ClientWithCache: Client { fn get_with_cache( &self, url: String, cache: C, ) -> Result, ::Error>; }