diff --git a/spec-trait-impl/crates/spec-trait-bin/src/all.rs b/spec-trait-impl/crates/spec-trait-bin/src/all.rs new file mode 100644 index 0000000..932cc00 --- /dev/null +++ b/spec-trait-impl/crates/spec-trait-bin/src/all.rs @@ -0,0 +1,364 @@ +use spec_trait_macro::{spec, when}; +use std::fmt::Debug; + +#[allow(clippy::upper_case_acronyms)] +struct ZST; +struct ZST2; +struct S(T); + +trait Foo { + fn foo(&self, x: T); +} + +trait Foo2 { + fn foo(&self, x: T, y: U); +} + +#[allow(dead_code)] +trait Foo3 { + fn foo(&self, x: T, y: String); +} + +trait Foo4 { + fn foo(&self); +} + +type MyType = u8; +type MyVecAlias = Vec; + +trait Bar {} +trait FooBar {} + +impl Bar for i32 {} +impl Bar for i64 {} +impl FooBar for i64 {} + +// ZST - Foo + +impl Foo for ZST { + fn foo(&self, _x: T) { + println!("Default Foo for ZST"); + } +} + +#[when(T = MyType)] +impl Foo for ZST { + fn foo(&self, _x: T) { + println!("Foo impl ZST where T is MyType"); + } +} + +#[when(T: Bar)] +impl Foo for ZST { + fn foo(&self, _x: T) { + println!("Foo impl ZST where T implements Bar"); + } +} + +#[when(T: Bar + FooBar)] +impl Foo for ZST { + fn foo(&self, _x: T) { + println!("Foo impl ZST where T implements Bar and FooBar"); + } +} + +#[when(T = Vec)] +impl Foo for ZST { + fn foo(&self, _x: T) { + println!("Foo impl ZST where T is Vec"); + } +} + +#[when(T = Vec<_>)] +impl Foo for ZST { + fn foo(&self, _x: T) { + println!("Foo impl ZST where T is Vec<_>"); + } +} + +#[when(T = MyVecAlias)] +impl Foo for ZST { + fn foo(&self, _x: T) { + println!("Foo impl ZST where T is MyVecAlias"); + } +} + +#[when(T = (i32, _))] +impl Foo for ZST { + fn foo(&self, _x: T) { + println!("Foo impl ZST where T is (i32, _)"); + } +} + +#[when(T = &[i32])] +impl Foo for ZST { + fn foo(&self, _x: T) { + println!("Foo impl ZST where T is &[i32]"); + } +} + +#[when(all(T = &_, T: 'a))] +impl<'a, T> Foo for ZST { + fn foo(&self, _x: T) { + println!("Foo impl ZST where T is &'a _"); + } +} + +#[when(T = &'static _)] +impl Foo for ZST { + fn foo(&self, _x: T) { + println!("Foo impl ZST where T is &'static _"); + } +} + +#[when(T = fn(&u8) -> &u8)] +impl Foo for ZST { + fn foo(&self, _x: T) { + println!("Foo impl ZST where T is a function pointer from &u8 to &u8"); + } +} + +#[when(T: Fn(i32) -> i32)] +impl Foo for ZST { + fn foo(&self, _x: T) { + println!("Foo impl ZST where T implements Fn(i32) -> i32"); + } +} + +#[when(T: for<'a> Fn(&'a i32) -> i32)] +impl Foo for ZST { + fn foo(&self, _x: T) { + println!("Foo impl ZST where T implements for<'a> Fn(&'a i32) -> i32"); + } +} + +// ZST - Foo2 + +impl Foo2 for ZST { + fn foo(&self, _x: T, _y: U) { + println!("Default Foo2 for ZST"); + } +} + +#[when(T = MyType)] +impl Foo2 for ZST { + fn foo(&self, _x: T, _y: U) { + println!("Foo2 for ZST where T is MyType"); + } +} + +#[when(U = Vec)] +impl Foo2 for ZST { + fn foo(&self, _x: T, _y: U) { + println!("Foo2 for ZST where U is Vec"); + } +} + +// ZST - Foo3 + +#[when(T = String)] +impl Foo3 for ZST { + fn foo(&self, _x: T, _y: String) { + println!("Foo3 for ZST where T is String"); + } +} + +#[when(all(T = Vec, U = String))] +impl Foo3 for ZST { + fn foo(&self, _x: T, _y: String) { + println!("Foo3 impl ZST where T is Vec"); + } +} + +#[when(T = Vec)] +impl Foo3 for ZST { + fn foo(&self, _x: T, _y: String) { + println!("Foo3 impl ZST where T is Vec"); + } +} + +#[when(all(T = Vec, U: Debug))] +impl Foo3 for ZST { + fn foo(&self, _x: T, _y: String) { + println!("Foo3 impl ZST where T is Vec and U implements Debug"); + } +} + +// ZST2 - Foo + +impl Foo for ZST2 { + fn foo(&self, _x: T) { + println!("Default Foo for ZST2"); + } +} + +#[when(T = MyType)] +impl Foo for ZST2 { + fn foo(&self, _x: T) { + println!("Foo impl ZST2 where T is MyType"); + } +} + +#[when(all(T = Vec, T = Vec<_>))] +impl Foo for ZST2 { + fn foo(&self, _x: T) { + println!("Foo impl ZST2 where T is Vec"); + } +} + +#[when(any(T: Copy, T: Clone))] +impl Foo for ZST2 { + fn foo(&self, _x: T) { + println!("Foo impl ZST2 where T implements Copy or Clone"); + } +} + +// ZST2 - Foo2 + +impl Foo2 for ZST2 { + fn foo(&self, _x: T, _y: U) { + println!("Default Foo2 for ZST2"); + } +} + +#[when(T = MyType)] +impl Foo2 for ZST2 { + fn foo(&self, _x: T, _y: U) { + println!("Foo2 for ZST2 where T is MyType"); + } +} + +#[when(not(T = MyType))] +impl Foo2 for ZST2 { + fn foo(&self, _x: T, _y: U) { + println!("Foo2 for ZST2 where T is not MyType"); + } +} + +// T - Foo + +#[when(all(U = MyType, T = i32))] +impl Foo for T { + fn foo(&self, _x: U) { + println!("Foo impl T where T is i32 and U is MyType"); + } +} + +#[when(all(U = MyType, T = Vec<_>))] +impl Foo for T { + fn foo(&self, _x: U) { + println!("Foo impl T where T is Vec<_> and U is MyType"); + } +} + +#[when(all(U = &str))] +impl Foo for T { + fn foo(&self, _x: U) { + println!("Foo impl T where U is &str"); + } +} + +#[when(T: Bar)] +impl Foo for T { + fn foo(&self, _x: U) { + println!("Foo impl T where T implements Bar"); + } +} + +#[when(all(not(T = i32), not(T = ZST), not(U = i32)))] +impl Foo for T { + fn foo(&self, _x: U) { + println!("Foo impl T where T is not i32 or ZST and U is not i32"); + } +} + +// T - Foo4 +impl Foo4 for T { + fn foo(&self) { + println!("Default Foo4 for T"); + } +} + +#[when(T = i32)] +impl Foo4 for S { + fn foo(&self) { + println!("Foo4 impl S where T is i32"); + } +} + +#[when(T = i32)] +impl Foo4 for Vec { + fn foo(&self) { + println!("Foo4 impl Vec where T is i32"); + } +} + +pub fn run() { + println!("\n- All Cases:"); + + let zst = ZST; + let zst2 = ZST2; + let x = vec![1i32]; + let s1 = S(1i32); + let s2 = S(1u8); + + // ZST - Foo + spec! { zst.foo(1u8); ZST; [MyType] } // -> "Foo impl ZST where T is MyType" + spec! { zst.foo(1u8); ZST; [u8]; u8 = MyType } // -> "Foo impl ZST where T is MyType" + spec! { zst.foo(vec![1i32]); ZST; [Vec]; Vec = MyVecAlias } // -> "Foo impl ZST where T is MyVecAlias" + spec! { zst.foo(vec![1u8]); ZST; [Vec]; u8 = MyType } // -> "Foo impl ZST where T is Vec" + spec! { zst.foo(vec![1i32]); ZST; [Vec] } // -> "Foo impl ZST where T is Vec<_>" + spec! { zst.foo((1, 2)); ZST; [(i32, i32)] } // -> "Foo impl ZST where T is (i32, _)" + spec! { zst.foo(&[1i32]); ZST; [&[i32]] } // -> "Foo impl ZST where T is &[i32]" + spec! { zst.foo(&1i32); ZST; [&'static i32] } // -> "Foo impl ZST where T is &'static _" + spec! { zst.foo(&1i32); ZST; [&i32]; &i32: 'static } // -> "Foo impl ZST where T is &'static _" + spec! { zst.foo(&1i32); ZST; [&'a i32] } // -> "Foo impl ZST where T is &'a _" + spec! { zst.foo(&1i32); ZST; [&i32]; &i32: 'a } // -> "Foo impl ZST where T is &'a _" + spec! { zst.foo(&1i32); ZST; [&i32] } // -> "Foo impl ZST where T is &'a _" + spec! { zst.foo(1i32); ZST; [i32]; i32: Bar } // -> "Foo impl ZST where T implements Bar" + spec! { zst.foo(1i64); ZST; [i64]; i64: Bar + FooBar } // -> "Foo impl ZST where T implements Bar and FooBar" + spec! { zst.foo(|x: &u8| x); ZST; [fn(&u8) -> &u8] } // -> "Foo impl ZST where T is a function pointer from &u8 to &u8" + spec! { zst.foo(|x: i32| x); ZST; [T]; T: Fn(i32) -> i32 } // -> "Foo impl ZST where T implements Fn(i32) -> i32" + spec! { zst.foo(|x: &i32| *x); ZST; [T]; T: for<'a> Fn(&'a i32) -> i32 } // -> "Foo impl ZST where T implements for<'a> Fn(&'a i32) -> i32" + spec! { zst.foo(1i8); ZST; [i8] } // -> "Default Foo for ZST" + println!(); + + // ZST - Foo2 + spec! { zst.foo(1u8, 2u8); ZST; [u8, u8]; u8 = MyType } // -> "Foo2 for ZST where T is MyType" + spec! { zst.foo(2u8, vec![2u8]); ZST; [u8, Vec] } // "Foo2 for ZST where U is Vec" + spec! { zst.foo(1i32, 1i32); ZST; [i32, i32] } // -> "Default Foo2 for ZST" + println!(); + + // ZST - Foo3 + spec! { zst.foo("a".to_string(), "b".to_string()); ZST; [String, String] } // -> "Foo3 impl ZST where T is String" + spec! { zst.foo(vec!["a".to_string()], "b".to_string()); ZST; [Vec, String] } // -> "Foo3 impl ZST where T is Vec" + spec! { zst.foo(vec!["a".to_string()], "b".to_string()); ZST; [Vec, String]; String: Debug } // -> "Foo3 impl ZST where T is Vec and U implements Debug" + println!(); + + // ZST2 - Foo + spec! { zst2.foo(1u8); ZST2; [u8]; u8 = MyType } // -> "Foo impl ZST2 where T is MyType" + spec! { zst2.foo(vec![1i32]); ZST2; [Vec] } // -> "Foo impl ZST2 where T is Vec" + spec! { zst2.foo(1i32); ZST2; [i32]; i32: Copy } // -> "Foo impl ZST2 where T implements Copy or Clone" + spec! { zst2.foo(1i32); ZST2; [i32] } // -> "Default Foo for ZST2" + println!(); + + // ZST2 - Foo2 + spec! { zst2.foo(1u8, 2u8); ZST2; [u8, u8]; u8 = MyType } // -> "Foo2 for ZST2 where T is MyType" + spec! { zst2.foo(1i8, 1i8); ZST2; [i8, i8] } // -> "Foo2 for ZST2 where T is not MyType" + println!(); + + // T - Foo + spec! { 1i32.foo(1u8); i32; [u8]; u8 = MyType } // -> "Foo impl T where T is i32 and U is MyType" + spec! { 1i32.foo(1i8); i32; [i8]; i32: Bar } // -> "Foo impl T where T implements Bar" + spec! { x.foo(1u8); Vec; [u8]; u8 = MyType } // -> "Foo impl T where T is Vec<_> and U is MyType" + spec! { 1i32.foo("str"); i32; [&str] } // -> "Foo impl T where U is &str" + spec! { zst.foo("str"); ZST; [&str] } // -> "Foo impl T where U is &str" + spec! { 1u8.foo(1u8); u8; [u8] } // -> "Foo impl T where T is not i32 or ZST and U is not i32" + println!(); + + // T - Foo4 + spec! { s1.foo(); S; [] } // -> "Foo4 impl S where T is i32" + spec! { x.foo(); Vec; [] } // -> "Foo4 impl Vec where T is i32" + spec! { s2.foo(); S; [] } // -> "Default Foo4 for T" + println!(); +} diff --git a/spec-trait-impl/crates/spec-trait-bin/src/base.rs b/spec-trait-impl/crates/spec-trait-bin/src/base.rs new file mode 100644 index 0000000..613ebff --- /dev/null +++ b/spec-trait-impl/crates/spec-trait-bin/src/base.rs @@ -0,0 +1,53 @@ +use spec_trait_macro::{spec, when}; + +struct BaseType; + +trait BaseTrait { + fn base_method(&self, _x: T); +} + +impl BaseTrait for BaseType { + fn base_method(&self, _x: T) { + println!("Default"); + } +} + +#[when(T = u8)] +impl BaseTrait for BaseType { + fn base_method(&self, _x: T) { + println!("T is u8"); + } +} + +#[when(T: Copy)] +impl BaseTrait for BaseType { + fn base_method(&self, _x: T) { + println!("T implements Copy"); + } +} + +#[when(any(T = String, T = i32))] +impl BaseTrait for BaseType { + fn base_method(&self, _x: T) { + println!("T is String or i32"); + } +} + +#[when(all(T = Vec, U: Copy))] +impl BaseTrait for BaseType { + fn base_method(&self, _x: T) { + println!("T is a Vec of Copy"); + } +} + +pub fn run() { + println!("\n- Base Cases:"); + + let x = BaseType; + + spec! { x.base_method(42u8); BaseType; [u8] } // T is u8 + spec! { x.base_method(1.2f32); BaseType; [f32]; f32: Copy } // T implements Copy + spec! { x.base_method(1i32); BaseType; [i32] } // T is String or i32 + spec! { x.base_method(vec![1, 2, 3]); BaseType; [Vec]; i32: Copy } // T is a Vec of Copy + spec! { x.base_method(&x); BaseType; [&BaseType] } // Default +} diff --git a/spec-trait-impl/crates/spec-trait-bin/src/lifetimes.rs b/spec-trait-impl/crates/spec-trait-bin/src/lifetimes.rs new file mode 100644 index 0000000..30143da --- /dev/null +++ b/spec-trait-impl/crates/spec-trait-bin/src/lifetimes.rs @@ -0,0 +1,40 @@ +use spec_trait_macro::{spec, when}; + +struct BaseType; + +trait LifetimesTrait { + fn lifetimes_method(&self, _x: T); +} + +impl LifetimesTrait for BaseType { + fn lifetimes_method(&self, _x: T) { + println!("Default"); + } +} + +#[when(all(T = &_, T: 'a))] +impl<'a, T> LifetimesTrait for BaseType { + fn lifetimes_method(&self, _x: T) { + println!("T is &'a _"); + } +} + +#[when(T = &'static _)] +impl LifetimesTrait for BaseType { + fn lifetimes_method(&self, _x: T) { + println!("T is &'static _"); + } +} + +pub fn run() { + println!("\n- Lifetimes Cases:"); + + let x = BaseType; + + spec! { x.lifetimes_method(&1i32); BaseType; [&'static i32] } // -> "T is &'static _" + spec! { x.lifetimes_method(&1i32); BaseType; [&i32]; &i32: 'static } // -> "T is &'static _" + spec! { x.lifetimes_method(&1i32); BaseType; [&'a i32] } // -> "T is &'a _" + spec! { x.lifetimes_method(&1i32); BaseType; [&i32]; &i32: 'a } // -> "T is &'a _" + spec! { x.lifetimes_method(&1i32); BaseType; [&i32] } // -> "T is &'a _" + spec! { x.lifetimes_method(1i32); BaseType; [i32] } // -> "Default" +} diff --git a/spec-trait-impl/crates/spec-trait-bin/src/main.rs b/spec-trait-impl/crates/spec-trait-bin/src/main.rs index 7b85874..822490c 100644 --- a/spec-trait-impl/crates/spec-trait-bin/src/main.rs +++ b/spec-trait-impl/crates/spec-trait-bin/src/main.rs @@ -1,362 +1,17 @@ -use spec_trait_macro::{spec, when}; -use std::fmt::Debug; - -#[allow(clippy::upper_case_acronyms)] -struct ZST; -struct ZST2; -struct S(T); - -trait Foo { - fn foo(&self, x: T); -} - -trait Foo2 { - fn foo(&self, x: T, y: U); -} - -#[allow(dead_code)] -trait Foo3 { - fn foo(&self, x: T, y: String); -} - -trait Foo4 { - fn foo(&self); -} - -type MyType = u8; -type MyVecAlias = Vec; - -trait Bar {} -trait FooBar {} - -impl Bar for i32 {} -impl Bar for i64 {} -impl FooBar for i64 {} - -// ZST - Foo - -impl Foo for ZST { - fn foo(&self, _x: T) { - println!("Default Foo for ZST"); - } -} - -#[when(T = MyType)] -impl Foo for ZST { - fn foo(&self, _x: T) { - println!("Foo impl ZST where T is MyType"); - } -} - -#[when(T: Bar)] -impl Foo for ZST { - fn foo(&self, _x: T) { - println!("Foo impl ZST where T implements Bar"); - } -} - -#[when(T: Bar + FooBar)] -impl Foo for ZST { - fn foo(&self, _x: T) { - println!("Foo impl ZST where T implements Bar and FooBar"); - } -} - -#[when(T = Vec)] -impl Foo for ZST { - fn foo(&self, _x: T) { - println!("Foo impl ZST where T is Vec"); - } -} - -#[when(T = Vec<_>)] -impl Foo for ZST { - fn foo(&self, _x: T) { - println!("Foo impl ZST where T is Vec<_>"); - } -} - -#[when(T = MyVecAlias)] -impl Foo for ZST { - fn foo(&self, _x: T) { - println!("Foo impl ZST where T is MyVecAlias"); - } -} - -#[when(T = (i32, _))] -impl Foo for ZST { - fn foo(&self, _x: T) { - println!("Foo impl ZST where T is (i32, _)"); - } -} - -#[when(T = &[i32])] -impl Foo for ZST { - fn foo(&self, _x: T) { - println!("Foo impl ZST where T is &[i32]"); - } -} - -#[when(all(T = &_, T: 'a))] -impl<'a, T> Foo for ZST { - fn foo(&self, _x: T) { - println!("Foo impl ZST where T is &'a _"); - } -} - -#[when(T = &'static _)] -impl Foo for ZST { - fn foo(&self, _x: T) { - println!("Foo impl ZST where T is &'static _"); - } -} - -#[when(T = fn(&u8) -> &u8)] -impl Foo for ZST { - fn foo(&self, _x: T) { - println!("Foo impl ZST where T is a function pointer from &u8 to &u8"); - } -} - -#[when(T: Fn(i32) -> i32)] -impl Foo for ZST { - fn foo(&self, _x: T) { - println!("Foo impl ZST where T implements Fn(i32) -> i32"); - } -} - -#[when(T: for<'a> Fn(&'a i32) -> i32)] -impl Foo for ZST { - fn foo(&self, _x: T) { - println!("Foo impl ZST where T implements for<'a> Fn(&'a i32) -> i32"); - } -} - -// ZST - Foo2 - -impl Foo2 for ZST { - fn foo(&self, _x: T, _y: U) { - println!("Default Foo2 for ZST"); - } -} - -#[when(T = MyType)] -impl Foo2 for ZST { - fn foo(&self, _x: T, _y: U) { - println!("Foo2 for ZST where T is MyType"); - } -} - -#[when(U = Vec)] -impl Foo2 for ZST { - fn foo(&self, _x: T, _y: U) { - println!("Foo2 for ZST where U is Vec"); - } -} - -// ZST - Foo3 - -#[when(T = String)] -impl Foo3 for ZST { - fn foo(&self, _x: T, _y: String) { - println!("Foo3 for ZST where T is String"); - } -} - -#[when(all(T = Vec, U = String))] -impl Foo3 for ZST { - fn foo(&self, _x: T, _y: String) { - println!("Foo3 impl ZST where T is Vec"); - } -} - -#[when(T = Vec)] -impl Foo3 for ZST { - fn foo(&self, _x: T, _y: String) { - println!("Foo3 impl ZST where T is Vec"); - } -} - -#[when(all(T = Vec, U: Debug))] -impl Foo3 for ZST { - fn foo(&self, _x: T, _y: String) { - println!("Foo3 impl ZST where T is Vec and U implements Debug"); - } -} - -// ZST2 - Foo - -impl Foo for ZST2 { - fn foo(&self, _x: T) { - println!("Default Foo for ZST2"); - } -} - -#[when(T = MyType)] -impl Foo for ZST2 { - fn foo(&self, _x: T) { - println!("Foo impl ZST2 where T is MyType"); - } -} - -#[when(all(T = Vec, T = Vec<_>))] -impl Foo for ZST2 { - fn foo(&self, _x: T) { - println!("Foo impl ZST2 where T is Vec"); - } -} - -#[when(any(T: Copy, T: Clone))] -impl Foo for ZST2 { - fn foo(&self, _x: T) { - println!("Foo impl ZST2 where T implements Copy or Clone"); - } -} - -// ZST2 - Foo2 - -impl Foo2 for ZST2 { - fn foo(&self, _x: T, _y: U) { - println!("Default Foo2 for ZST2"); - } -} - -#[when(T = MyType)] -impl Foo2 for ZST2 { - fn foo(&self, _x: T, _y: U) { - println!("Foo2 for ZST2 where T is MyType"); - } -} - -#[when(not(T = MyType))] -impl Foo2 for ZST2 { - fn foo(&self, _x: T, _y: U) { - println!("Foo2 for ZST2 where T is not MyType"); - } -} - -// T - Foo - -#[when(all(U = MyType, T = i32))] -impl Foo for T { - fn foo(&self, _x: U) { - println!("Foo impl T where T is i32 and U is MyType"); - } -} - -#[when(all(U = MyType, T = Vec<_>))] -impl Foo for T { - fn foo(&self, _x: U) { - println!("Foo impl T where T is Vec<_> and U is MyType"); - } -} - -#[when(all(U = &str))] -impl Foo for T { - fn foo(&self, _x: U) { - println!("Foo impl T where U is &str"); - } -} - -#[when(T: Bar)] -impl Foo for T { - fn foo(&self, _x: U) { - println!("Foo impl T where T implements Bar"); - } -} - -#[when(all(not(T = i32), not(T = ZST), not(U = i32)))] -impl Foo for T { - fn foo(&self, _x: U) { - println!("Foo impl T where T is not i32 or ZST and U is not i32"); - } -} - -// T - Foo4 -impl Foo4 for T { - fn foo(&self) { - println!("Default Foo4 for T"); - } -} - -#[when(T = i32)] -impl Foo4 for S { - fn foo(&self) { - println!("Foo4 impl S where T is i32"); - } -} - -#[when(T = i32)] -impl Foo4 for Vec { - fn foo(&self) { - println!("Foo4 impl Vec where T is i32"); - } -} +mod all; +mod base; +mod lifetimes; +mod nested; +mod sself; +mod traits; +mod types; fn main() { - let zst = ZST; - let zst2 = ZST2; - let x = vec![1i32]; - let s1 = S(1i32); - let s2 = S(1u8); - - // ZST - Foo - spec! { zst.foo(1u8); ZST; [MyType] } // -> "Foo impl ZST where T is MyType" - spec! { zst.foo(1u8); ZST; [u8]; u8 = MyType } // -> "Foo impl ZST where T is MyType" - spec! { zst.foo(vec![1i32]); ZST; [Vec]; Vec = MyVecAlias } // -> "Foo impl ZST where T is MyVecAlias" - spec! { zst.foo(vec![1u8]); ZST; [Vec]; u8 = MyType } // -> "Foo impl ZST where T is Vec" - spec! { zst.foo(vec![1i32]); ZST; [Vec] } // -> "Foo impl ZST where T is Vec<_>" - spec! { zst.foo((1, 2)); ZST; [(i32, i32)] } // -> "Foo impl ZST where T is (i32, _)" - spec! { zst.foo(&[1i32]); ZST; [&[i32]] } // -> "Foo impl ZST where T is &[i32]" - spec! { zst.foo(&1i32); ZST; [&'static i32] } // -> "Foo impl ZST where T is &'static _" - spec! { zst.foo(&1i32); ZST; [&i32]; &i32: 'static } // -> "Foo impl ZST where T is &'static _" - spec! { zst.foo(&1i32); ZST; [&'a i32] } // -> "Foo impl ZST where T is &'a _" - spec! { zst.foo(&1i32); ZST; [&i32]; &i32: 'a } // -> "Foo impl ZST where T is &'a _" - spec! { zst.foo(&1i32); ZST; [&i32] } // -> "Foo impl ZST where T is &'a _" - spec! { zst.foo(1i32); ZST; [i32]; i32: Bar } // -> "Foo impl ZST where T implements Bar" - spec! { zst.foo(1i64); ZST; [i64]; i64: Bar + FooBar } // -> "Foo impl ZST where T implements Bar and FooBar" - spec! { zst.foo(|x: &u8| x); ZST; [fn(&u8) -> &u8] } // -> "Foo impl ZST where T is a function pointer from &u8 to &u8" - spec! { zst.foo(|x: i32| x); ZST; [T]; T: Fn(i32) -> i32 } // -> "Foo impl ZST where T implements Fn(i32) -> i32" - spec! { zst.foo(|x: &i32| *x); ZST; [T]; T: for<'a> Fn(&'a i32) -> i32 } // -> "Foo impl ZST where T implements for<'a> Fn(&'a i32) -> i32" - spec! { zst.foo(1i8); ZST; [i8] } // -> "Default Foo for ZST" - println!(); - - // ZST - Foo2 - spec! { zst.foo(1u8, 2u8); ZST; [u8, u8]; u8 = MyType } // -> "Foo2 for ZST where T is MyType" - spec! { zst.foo(2u8, vec![2u8]); ZST; [u8, Vec] } // "Foo2 for ZST where U is Vec" - spec! { zst.foo(1i32, 1i32); ZST; [i32, i32] } // -> "Default Foo2 for ZST" - println!(); - - // ZST - Foo3 - spec! { zst.foo("a".to_string(), "b".to_string()); ZST; [String, String] } // -> "Foo3 impl ZST where T is String" - spec! { zst.foo(vec!["a".to_string()], "b".to_string()); ZST; [Vec, String] } // -> "Foo3 impl ZST where T is Vec" - spec! { zst.foo(vec!["a".to_string()], "b".to_string()); ZST; [Vec, String]; String: Debug } // -> "Foo3 impl ZST where T is Vec and U implements Debug" - println!(); - - // ZST2 - Foo - spec! { zst2.foo(1u8); ZST2; [u8]; u8 = MyType } // -> "Foo impl ZST2 where T is MyType" - spec! { zst2.foo(vec![1i32]); ZST2; [Vec] } // -> "Foo impl ZST2 where T is Vec" - spec! { zst2.foo(1i32); ZST2; [i32]; i32: Copy } // -> "Foo impl ZST2 where T implements Copy or Clone" - spec! { zst2.foo(1i32); ZST2; [i32] } // -> "Default Foo for ZST2" - println!(); - - // ZST2 - Foo2 - spec! { zst2.foo(1u8, 2u8); ZST2; [u8, u8]; u8 = MyType } // -> "Foo2 for ZST2 where T is MyType" - spec! { zst2.foo(1i8, 1i8); ZST2; [i8, i8] } // -> "Foo2 for ZST2 where T is not MyType" - println!(); - - // T - Foo - spec! { 1i32.foo(1u8); i32; [u8]; u8 = MyType } // -> "Foo impl T where T is i32 and U is MyType" - spec! { 1i32.foo(1i8); i32; [i8]; i32: Bar } // -> "Foo impl T where T implements Bar" - spec! { x.foo(1u8); Vec; [u8]; u8 = MyType } // -> "Foo impl T where T is Vec<_> and U is MyType" - spec! { 1i32.foo("str"); i32; [&str] } // -> "Foo impl T where U is &str" - spec! { zst.foo("str"); ZST; [&str] } // -> "Foo impl T where U is &str" - spec! { 1u8.foo(1u8); u8; [u8] } // -> "Foo impl T where T is not i32 or ZST and U is not i32" - println!(); - - // T - Foo4 - spec! { s1.foo(); S; [] } // -> "Foo4 impl S where T is i32" - spec! { x.foo(); Vec; [] } // -> "Foo4 impl Vec where T is i32" - spec! { s2.foo(); S; [] } // -> "Default Foo4 for T" - println!(); + base::run(); + types::run(); + traits::run(); + lifetimes::run(); + nested::run(); + sself::run(); + all::run(); } diff --git a/spec-trait-impl/crates/spec-trait-bin/src/nested.rs b/spec-trait-impl/crates/spec-trait-bin/src/nested.rs new file mode 100644 index 0000000..f71b641 --- /dev/null +++ b/spec-trait-impl/crates/spec-trait-bin/src/nested.rs @@ -0,0 +1,37 @@ +use spec_trait_macro::{spec, when}; + +struct BaseType; + +trait NestedTrait { + fn nested_method(&self, _x: T, _y: U); +} + +impl NestedTrait for BaseType { + fn nested_method(&self, _x: T, _y: U) { + println!("Default"); + } +} + +#[when(all(U = Vec, T = u8))] +impl NestedTrait for BaseType { + fn nested_method(&self, _x: T, _y: U) { + println!("T is u8 and U is Vec"); + } +} + +#[when(U = Vec)] +impl NestedTrait for BaseType { + fn nested_method(&self, _x: T, _y: U) { + println!("U is Vec"); + } +} + +pub fn run() { + println!("\n- Nested Cases:"); + + let x = BaseType; + + spec! { x.nested_method(1u8, vec![2u8]); BaseType; [u8, Vec] } // "T is u8 and U is Vec" + spec! { x.nested_method(1i32, vec![2i32]); BaseType; [i32, Vec] } // "U is Vec" + spec! { x.nested_method(1i32, 2i32); BaseType; [i32, i32] } // -> "Default" +} diff --git a/spec-trait-impl/crates/spec-trait-bin/src/sself.rs b/spec-trait-impl/crates/spec-trait-bin/src/sself.rs new file mode 100644 index 0000000..8ac8484 --- /dev/null +++ b/spec-trait-impl/crates/spec-trait-bin/src/sself.rs @@ -0,0 +1,82 @@ +use spec_trait_macro::{spec, when}; + +struct BaseType1; +struct BaseType2; + +trait SelfTrait { + fn self_method(&self, _x: T); +} + +impl SelfTrait for BaseType1 { + fn self_method(&self, _x: T) { + println!("BaseType1: Default"); + } +} + +impl SelfTrait for BaseType2 { + fn self_method(&self, _x: T) { + println!("BaseType2: Default"); + } +} + +impl SelfTrait for Vec { + fn self_method(&self, _x: T) { + println!("Vec: Default"); + } +} + +impl SelfTrait for (U, V) { + fn self_method(&self, _x: T) { + println!("(U, V): Default"); + } +} + +#[when(T = u8)] +impl SelfTrait for BaseType1 { + fn self_method(&self, _x: T) { + println!("BaseType1: T is u8"); + } +} + +#[when(T = u8)] +impl SelfTrait for BaseType2 { + fn self_method(&self, _x: T) { + println!("BaseType2: T is u8"); + } +} + +#[when(T = u8)] +impl SelfTrait for Vec { + fn self_method(&self, _x: T) { + println!("Vec: T is u8"); + } +} + +#[when(T = u8)] +impl SelfTrait for (U, V) { + fn self_method(&self, _x: T) { + println!("(U, V): T is u8"); + } +} + +pub fn run() { + println!("\n- Self Cases:"); + + let x = BaseType1; + spec! { x.self_method(42u8); BaseType1; [u8] } // -> "BaseType1: T is u8" + spec! { x.self_method(1i32); BaseType1; [i32] } // -> "BaseType1: Default" + + let y = BaseType2; + spec! { y.self_method(42u8); BaseType2; [u8] } // -> "BaseType2: T is u8" + spec! { y.self_method(1i32); BaseType2; [i32] } // -> "BaseType2: Default" + + let v1 = vec![1u8]; + let v2 = vec![1i32]; + spec! { v1.self_method(42u8); Vec; [u8] } // -> "Vec: T is u8" + spec! { v2.self_method(1i32); Vec; [i32] } // -> "Vec: Default" + + let t1 = (1u8, 2u8); + let t2 = (1i32, 2i32); + spec! { t1.self_method(42u8); (u8, u8); [u8] } // -> "(U, V): T is u8" + spec! { t2.self_method(1i32); (i32, i32); [i32] } // -> "(U, V): Default" +} diff --git a/spec-trait-impl/crates/spec-trait-bin/src/traits.rs b/spec-trait-impl/crates/spec-trait-bin/src/traits.rs new file mode 100644 index 0000000..2495249 --- /dev/null +++ b/spec-trait-impl/crates/spec-trait-bin/src/traits.rs @@ -0,0 +1,60 @@ +use spec_trait_macro::{spec, when}; + +trait Bar {} +trait FooBar {} + +impl Bar for i32 {} +impl Bar for i64 {} +impl FooBar for i64 {} + +struct BaseType; + +trait TraitsTrait { + fn traits_method(&self, _x: T); +} + +impl TraitsTrait for BaseType { + fn traits_method(&self, _x: T) { + println!("Default"); + } +} + +#[when(T: Bar)] +impl TraitsTrait for BaseType { + fn traits_method(&self, _x: T) { + println!("T implements Bar"); + } +} + +#[when(T: Bar + FooBar)] +impl TraitsTrait for BaseType { + fn traits_method(&self, _x: T) { + println!("T implements Bar and FooBar"); + } +} + +#[when(T: Fn(i32) -> i32)] +impl TraitsTrait for BaseType { + fn traits_method(&self, _x: T) { + println!("T implements Fn(i32) -> i32"); + } +} + +#[when(T: for<'a> Fn(&'a i32) -> i32)] +impl TraitsTrait for BaseType { + fn traits_method(&self, _x: T) { + println!("T implements for<'a> Fn(&'a i32) -> i32"); + } +} + +pub fn run() { + println!("\n- Traits Cases:"); + + let x = BaseType; + + spec! { x.traits_method(1i32); BaseType; [i32]; i32: Bar } // -> "T implements Bar" + spec! { x.traits_method(1i64); BaseType; [i64]; i64: Bar + FooBar } // -> "T implements Bar and FooBar" + spec! { x.traits_method(|x: i32| x); BaseType; [T]; T: Fn(i32) -> i32 } // -> "T implements Fn(i32) -> i32" + spec! { x.traits_method(|x: &i32| *x); BaseType; [T]; T: for<'a> Fn(&'a i32) -> i32 } // -> "T implements for<'a> Fn(&'a i32) -> i32" + spec! { x.traits_method(1i8); BaseType; [i8] } // -> "Default" +} diff --git a/spec-trait-impl/crates/spec-trait-bin/src/types.rs b/spec-trait-impl/crates/spec-trait-bin/src/types.rs new file mode 100644 index 0000000..ed1ec75 --- /dev/null +++ b/spec-trait-impl/crates/spec-trait-bin/src/types.rs @@ -0,0 +1,81 @@ +use spec_trait_macro::{spec, when}; + +type MyAlias = u8; +type MyVecAlias = Vec; + +struct BaseType; + +trait TypesTrait { + fn types_method(&self, _x: T); +} + +impl TypesTrait for BaseType { + fn types_method(&self, _x: T) { + println!("Default"); + } +} + +#[when(T = MyAlias)] +impl TypesTrait for BaseType { + fn types_method(&self, _x: T) { + println!("T is MyAlias"); + } +} + +#[when(T = Vec)] +impl TypesTrait for BaseType { + fn types_method(&self, _x: T) { + println!("T is Vec"); + } +} + +#[when(T = Vec<_>)] +impl TypesTrait for BaseType { + fn types_method(&self, _x: T) { + println!("T is Vec<_>"); + } +} + +#[when(T = MyVecAlias)] +impl TypesTrait for BaseType { + fn types_method(&self, _x: T) { + println!("T is MyVecAlias"); + } +} + +#[when(T = (i32, _))] +impl TypesTrait for BaseType { + fn types_method(&self, _x: T) { + println!("T is (i32, _)"); + } +} + +#[when(T = &[i32])] +impl TypesTrait for BaseType { + fn types_method(&self, _x: T) { + println!("T is &[i32]"); + } +} + +#[when(T = fn(&u8) -> &u8)] +impl TypesTrait for BaseType { + fn types_method(&self, _x: T) { + println!("T is a function pointer from &u8 to &u8"); + } +} + +pub fn run() { + println!("\n- Types Cases:"); + + let x = BaseType; + + spec! { x.types_method(1u8); BaseType; [MyAlias] } // -> "T is MyAlias" + spec! { x.types_method(1u8); BaseType; [u8]; u8 = MyAlias } // -> "T is MyAlias" + spec! { x.types_method(vec![1i32]); BaseType; [Vec]; Vec = MyVecAlias } // -> "T is MyVecAlias" + spec! { x.types_method(vec![1u8]); BaseType; [Vec]; u8 = MyAlias } // -> "T is Vec" + spec! { x.types_method(vec![1i32]); BaseType; [Vec] } // -> "T is Vec<_>" + spec! { x.types_method((1, 2)); BaseType; [(i32, i32)] } // -> "T is (i32, _)" + spec! { x.types_method(&[1i32]); BaseType; [&[i32]] } // -> "T is &[i32]" + spec! { x.types_method(|x: &u8| x); BaseType; [fn(&u8) -> &u8] } // -> "T is a function pointer from &u8 to &u8" + spec! { x.types_method(1i8); BaseType; [i8] } // -> "Default" +}