From d5c2499708d2dd85c3e1fbd75160a3663d91ce36 Mon Sep 17 00:00:00 2001 From: Dmytro Kriuchkov <75734980+BigglesworthCat@users.noreply.github.com> Date: Sat, 22 Jun 2024 13:42:37 +0300 Subject: [PATCH] READY: Extend `phantom` macros (#1381) get completed phantom derive --- module/core/derive_tools/Cargo.toml | 4 +- module/core/derive_tools/build.rs | 6 +- module/core/derive_tools/tests/inc/mod.rs | 32 +++++- .../tests/inc/phantom/bounds_inlined.rs | 8 ++ .../inc/phantom/bounds_inlined_manual.rs | 13 +++ .../tests/inc/phantom/bounds_mixed.rs | 11 ++ .../tests/inc/phantom/bounds_mixed_manual.rs | 15 +++ .../tests/inc/phantom/bounds_where.rs | 12 ++ .../tests/inc/phantom/bounds_where_manual.rs | 16 +++ .../tests/inc/phantom/compiletime/enum.rs | 13 +++ .../tests/inc/phantom/compiletime/enum.stderr | 5 + .../inc/phantom/compiletime/invariant_type.rs | 18 +++ .../phantom/compiletime/invariant_type.stderr | 12 ++ .../tests/inc/phantom/contravariant_type.rs | 10 ++ .../inc/phantom/contravariant_type_manual.rs | 10 ++ .../tests/inc/phantom/covariant_type.rs | 10 ++ .../inc/phantom/covariant_type_manual.rs | 10 ++ .../tests/inc/phantom/name_collisions.rs | 15 +++ .../inc/phantom/only_test/bounds_inlined.rs | 5 + .../inc/phantom/only_test/bounds_mixed.rs | 5 + .../inc/phantom/only_test/bounds_where.rs | 5 + .../phantom/only_test/contravariant_type.rs | 18 +++ .../inc/phantom/only_test/covariant_type.rs | 12 ++ .../inc/phantom/only_test/name_collisions.rs | 5 + .../inc/phantom/only_test/send_sync_type.rs | 9 ++ .../inc/phantom/only_test/struct_named.rs | 2 +- .../phantom/only_test/struct_named_empty.rs | 5 + .../phantom/only_test/struct_tuple_empty.rs | 5 + .../phantom/only_test/struct_unit_to_tuple.rs | 5 + .../tests/inc/phantom/send_sync_type.rs | 10 ++ .../inc/phantom/send_sync_type_manual.rs | 10 ++ .../tests/inc/phantom/struct_named_empty.rs | 7 ++ .../inc/phantom/struct_named_empty_manual.rs | 9 ++ .../tests/inc/phantom/struct_named_manual.rs | 1 - .../tests/inc/phantom/struct_tuple_empty.rs | 7 ++ .../inc/phantom/struct_tuple_empty_manual.rs | 6 + .../tests/inc/phantom/struct_tuple_manual.rs | 1 - .../tests/inc/phantom/struct_unit_to_tuple.rs | 7 ++ .../phantom/struct_unit_to_tuple_manual.rs | 6 + .../derive_tools_meta/src/derive/phantom.rs | 107 ++++++++++++++++-- module/core/derive_tools_meta/src/lib.rs | 2 +- module/core/macro_tools/src/phantom.rs | 15 ++- 42 files changed, 467 insertions(+), 17 deletions(-) create mode 100644 module/core/derive_tools/tests/inc/phantom/bounds_inlined.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/bounds_inlined_manual.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/bounds_mixed.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/bounds_mixed_manual.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/bounds_where.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/bounds_where_manual.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/compiletime/enum.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/compiletime/enum.stderr create mode 100644 module/core/derive_tools/tests/inc/phantom/compiletime/invariant_type.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/compiletime/invariant_type.stderr create mode 100644 module/core/derive_tools/tests/inc/phantom/contravariant_type.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/contravariant_type_manual.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/covariant_type.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/covariant_type_manual.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/name_collisions.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/only_test/bounds_inlined.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/only_test/bounds_mixed.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/only_test/bounds_where.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/only_test/contravariant_type.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/only_test/covariant_type.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/only_test/name_collisions.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/only_test/send_sync_type.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/only_test/struct_named_empty.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/only_test/struct_tuple_empty.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/only_test/struct_unit_to_tuple.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/send_sync_type.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/send_sync_type_manual.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/struct_named_empty.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/struct_named_empty_manual.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/struct_tuple_empty.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/struct_tuple_empty_manual.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/struct_unit_to_tuple.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/struct_unit_to_tuple_manual.rs diff --git a/module/core/derive_tools/Cargo.toml b/module/core/derive_tools/Cargo.toml index c0d83154f7..905ef0bcca 100644 --- a/module/core/derive_tools/Cargo.toml +++ b/module/core/derive_tools/Cargo.toml @@ -72,7 +72,7 @@ default = [ "derive_inner_from", "derive_new", - "derive_phantom" + "derive_phantom", # "use_std", ] @@ -119,7 +119,7 @@ full = [ "derive_inner_from", "derive_new", - "derive_phantom" + "derive_phantom", # "use_std", ] diff --git a/module/core/derive_tools/build.rs b/module/core/derive_tools/build.rs index bfce7f82f0..7bf86e248f 100644 --- a/module/core/derive_tools/build.rs +++ b/module/core/derive_tools/build.rs @@ -23,7 +23,8 @@ fn main() feature = "derive_from", feature = "derive_inner_from", feature = "derive_variadic_from", - feature = "derive_reflect" + feature = "derive_reflect", + feature = "derive_phantom" ) }, any_derive : @@ -37,7 +38,8 @@ fn main() feature = "derive_from", feature = "derive_inner_from", feature = "derive_variadic_from", - feature = "derive_reflect" + feature = "derive_reflect", + feature = "derive_phantom" ) }, } diff --git a/module/core/derive_tools/tests/inc/mod.rs b/module/core/derive_tools/tests/inc/mod.rs index 64dc024582..105aca981e 100644 --- a/module/core/derive_tools/tests/inc/mod.rs +++ b/module/core/derive_tools/tests/inc/mod.rs @@ -25,7 +25,7 @@ mod all_manual_test; feature = "derive_deref_mut", feature = "derive_from", feature = "derive_inner_from", - feature = "derive_phantom" + feature = "derive_phantom", ) )] mod all_test; @@ -257,6 +257,36 @@ mod phantom_tests mod struct_named; mod struct_named_manual; + mod struct_named_empty; + mod struct_named_empty_manual; mod struct_tuple; mod struct_tuple_manual; + mod struct_tuple_empty; + mod struct_tuple_empty_manual; + mod struct_unit_to_tuple; + mod struct_unit_to_tuple_manual; + mod bounds_inlined; + mod bounds_inlined_manual; + mod bounds_mixed; + mod bounds_mixed_manual; + mod bounds_where; + mod bounds_where_manual; + mod name_collisions; + mod covariant_type; + mod covariant_type_manual; + mod contravariant_type; + mod contravariant_type_manual; + mod send_sync_type; + mod send_sync_type_manual; + #[ test_tools::nightly ] + #[ test ] + fn phantom_trybuild() + { + + println!( "current_dir : {:?}", std::env::current_dir().unwrap() ); + let t = test_tools::compiletime::TestCases::new(); + + t.compile_fail( "tests/inc/phantom/compiletime/enum.rs" ); + t.compile_fail( "tests/inc/phantom/compiletime/invariant_type.rs" ); + } } diff --git a/module/core/derive_tools/tests/inc/phantom/bounds_inlined.rs b/module/core/derive_tools/tests/inc/phantom/bounds_inlined.rs new file mode 100644 index 0000000000..cfcb0969b2 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/bounds_inlined.rs @@ -0,0 +1,8 @@ +use std::fmt::Debug; +use super::*; + +#[ allow( dead_code ) ] +#[ the_module::phantom ] +struct BoundsInlined< T: ToString, U: Debug > {} + +include!( "./only_test/bounds_inlined.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/bounds_inlined_manual.rs b/module/core/derive_tools/tests/inc/phantom/bounds_inlined_manual.rs new file mode 100644 index 0000000000..01fd788326 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/bounds_inlined_manual.rs @@ -0,0 +1,13 @@ +use std:: +{ + fmt::Debug, + marker::PhantomData, +}; + +#[ allow( dead_code ) ] +struct BoundsInlined< T: ToString, U: Debug > +{ + _phantom: PhantomData< ( T, U ) >, +} + +include!( "./only_test/bounds_inlined.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/bounds_mixed.rs b/module/core/derive_tools/tests/inc/phantom/bounds_mixed.rs new file mode 100644 index 0000000000..3d0b390d19 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/bounds_mixed.rs @@ -0,0 +1,11 @@ +use std::fmt::Debug; +use super::*; + +#[ allow( dead_code ) ] +#[ the_module::phantom ] +struct BoundsMixed< T: ToString, U > +where + U: Debug, +{} + +include!( "./only_test/bounds_mixed.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/bounds_mixed_manual.rs b/module/core/derive_tools/tests/inc/phantom/bounds_mixed_manual.rs new file mode 100644 index 0000000000..2c1ad041dd --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/bounds_mixed_manual.rs @@ -0,0 +1,15 @@ +use std:: +{ + fmt::Debug, + marker::PhantomData, +}; + +#[ allow( dead_code ) ] +struct BoundsMixed< T: ToString, U > +where + U: Debug, +{ + _phantom: PhantomData< ( T, U ) >, +} + +include!( "./only_test/bounds_mixed.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/bounds_where.rs b/module/core/derive_tools/tests/inc/phantom/bounds_where.rs new file mode 100644 index 0000000000..b7e7d73dd9 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/bounds_where.rs @@ -0,0 +1,12 @@ +use std::fmt::Debug; +use super::*; + +#[ allow( dead_code ) ] +#[ the_module::phantom ] +struct BoundsWhere< T, U > +where + T: ToString, + U: Debug, +{} + +include!( "./only_test/bounds_where.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/bounds_where_manual.rs b/module/core/derive_tools/tests/inc/phantom/bounds_where_manual.rs new file mode 100644 index 0000000000..89e248dc60 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/bounds_where_manual.rs @@ -0,0 +1,16 @@ +use std:: +{ + fmt::Debug, + marker::PhantomData, +}; + +#[ allow( dead_code ) ] +struct BoundsWhere< T, U > + where + T: ToString, + U: Debug, +{ + _phantom: PhantomData< ( T, U ) > +} + +include!( "./only_test/bounds_where.rs" ); diff --git a/module/core/derive_tools/tests/inc/phantom/compiletime/enum.rs b/module/core/derive_tools/tests/inc/phantom/compiletime/enum.rs new file mode 100644 index 0000000000..fa8f131612 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/compiletime/enum.rs @@ -0,0 +1,13 @@ +use derive_tools_meta::phantom; + +#[ phantom ] +enum Enum< T > +{ + A, + B, + C( T ), +} + +fn main() +{ +} \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/compiletime/enum.stderr b/module/core/derive_tools/tests/inc/phantom/compiletime/enum.stderr new file mode 100644 index 0000000000..0a3888237c --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/compiletime/enum.stderr @@ -0,0 +1,5 @@ +error: expected `struct` + --> tests/inc/phantom/compiletime/enum.rs:4:1 + | +4 | enum Enum< T > + | ^^^^ diff --git a/module/core/derive_tools/tests/inc/phantom/compiletime/invariant_type.rs b/module/core/derive_tools/tests/inc/phantom/compiletime/invariant_type.rs new file mode 100644 index 0000000000..7febb58d57 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/compiletime/invariant_type.rs @@ -0,0 +1,18 @@ +use derive_tools_meta::phantom; + +#[ phantom ] +struct InvariantType< T > +{ + a: T, +} + +fn assert_invariant< 'a >( x: InvariantType< *mut &'static str > ) -> InvariantType< *mut &'a str > +{ + x +} + +fn main() +{ + let x: InvariantType< *mut &'static str > = InvariantType { a: &mut "boo", _phantom: Default::default() }; + let _: InvariantType< *mut &str > = assert_invariant( x ); +} \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/compiletime/invariant_type.stderr b/module/core/derive_tools/tests/inc/phantom/compiletime/invariant_type.stderr new file mode 100644 index 0000000000..5945c78a60 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/compiletime/invariant_type.stderr @@ -0,0 +1,12 @@ +error: lifetime may not live long enough + --> tests/inc/phantom/compiletime/invariant_type.rs:11:3 + | +9 | fn assert_invariant< 'a >( x: InvariantType< *mut &'static str > ) -> InvariantType< *mut &'a str > + | -- lifetime `'a` defined here +10 | { +11 | x + | ^ returning this value requires that `'a` must outlive `'static` + | + = note: requirement occurs because of a mutable pointer to `&str` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance diff --git a/module/core/derive_tools/tests/inc/phantom/contravariant_type.rs b/module/core/derive_tools/tests/inc/phantom/contravariant_type.rs new file mode 100644 index 0000000000..35e1d46946 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/contravariant_type.rs @@ -0,0 +1,10 @@ +use super::*; + +#[ allow( dead_code ) ] +#[ the_module::phantom ] +struct ContravariantType< T > +{ + a: T, +} + +include!( "./only_test/contravariant_type.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/contravariant_type_manual.rs b/module/core/derive_tools/tests/inc/phantom/contravariant_type_manual.rs new file mode 100644 index 0000000000..30ad26d10b --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/contravariant_type_manual.rs @@ -0,0 +1,10 @@ +use std::marker::PhantomData; + +#[ allow( dead_code ) ] +struct ContravariantType< T > +{ + a: T, + _phantom: PhantomData< T >, +} + +include!( "./only_test/contravariant_type.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/covariant_type.rs b/module/core/derive_tools/tests/inc/phantom/covariant_type.rs new file mode 100644 index 0000000000..bdcd40d573 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/covariant_type.rs @@ -0,0 +1,10 @@ +use super::*; + +#[ allow( dead_code ) ] +#[ the_module::phantom ] +struct CovariantType< T > +{ + a: T, +} + +include!( "./only_test/covariant_type.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/covariant_type_manual.rs b/module/core/derive_tools/tests/inc/phantom/covariant_type_manual.rs new file mode 100644 index 0000000000..ce4484519e --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/covariant_type_manual.rs @@ -0,0 +1,10 @@ +use std::marker::PhantomData; + +#[ allow( dead_code ) ] +struct CovariantType< T > +{ + a: T, + _phantom: PhantomData< T >, +} + +include!( "./only_test/covariant_type.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/name_collisions.rs b/module/core/derive_tools/tests/inc/phantom/name_collisions.rs new file mode 100644 index 0000000000..1686b4c1da --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/name_collisions.rs @@ -0,0 +1,15 @@ +use super::*; + +pub mod std {} +pub mod core {} +pub mod marker {} + +#[ allow( dead_code ) ] +#[ the_module::phantom ] +struct NameCollisions< T > +{ + a : String, + b : i32, +} + +include!( "./only_test/name_collisions.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/only_test/bounds_inlined.rs b/module/core/derive_tools/tests/inc/phantom/only_test/bounds_inlined.rs new file mode 100644 index 0000000000..c0320bc28f --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/only_test/bounds_inlined.rs @@ -0,0 +1,5 @@ +#[ test ] +fn phantom() +{ + let _ = BoundsInlined::< String, i32 > { _phantom: Default::default() }; +} \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/only_test/bounds_mixed.rs b/module/core/derive_tools/tests/inc/phantom/only_test/bounds_mixed.rs new file mode 100644 index 0000000000..773c57967d --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/only_test/bounds_mixed.rs @@ -0,0 +1,5 @@ +#[ test ] +fn phantom() +{ + let _ = BoundsMixed::< String, i32 > { _phantom: Default::default() }; +} \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/only_test/bounds_where.rs b/module/core/derive_tools/tests/inc/phantom/only_test/bounds_where.rs new file mode 100644 index 0000000000..3bf24a6d6c --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/only_test/bounds_where.rs @@ -0,0 +1,5 @@ +#[ test ] +fn phantom() +{ + let _ = BoundsWhere::< String, i32 > { _phantom: Default::default() }; +} \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/only_test/contravariant_type.rs b/module/core/derive_tools/tests/inc/phantom/only_test/contravariant_type.rs new file mode 100644 index 0000000000..f30c2a57e8 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/only_test/contravariant_type.rs @@ -0,0 +1,18 @@ +fn assert_contravariant( x: ContravariantType< &dyn Fn( &'static str ) -> String > ) -> String +{ + ( x.a )( "test" ) +} + +#[test] +fn contravariant() +{ + let x_fn: &dyn for< 'a > Fn( &'a str ) -> String = &| s: &str | + { + format!( "x_fn: {s}" ) + }; + + let x: ContravariantType< &dyn for< 'a > Fn( &'a str ) -> String > = ContravariantType { a: x_fn, _phantom: Default::default() }; + let value = assert_contravariant(x); + + assert_eq!( value, String::from( "x_fn: test" ) ); +} diff --git a/module/core/derive_tools/tests/inc/phantom/only_test/covariant_type.rs b/module/core/derive_tools/tests/inc/phantom/only_test/covariant_type.rs new file mode 100644 index 0000000000..75e02a1255 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/only_test/covariant_type.rs @@ -0,0 +1,12 @@ +fn assert_covariant< 'a >( x: CovariantType< &'static str > ) -> CovariantType< &'a str > +{ + x +} + +#[ test ] +fn covariant() +{ + let x: CovariantType< &'static str > = CovariantType { a: "boo", _phantom: Default::default(), }; + let y: CovariantType< &str > = assert_covariant( x ); + assert_eq!( y.a, "boo" ); +} diff --git a/module/core/derive_tools/tests/inc/phantom/only_test/name_collisions.rs b/module/core/derive_tools/tests/inc/phantom/only_test/name_collisions.rs new file mode 100644 index 0000000000..29badc6387 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/only_test/name_collisions.rs @@ -0,0 +1,5 @@ +#[ test ] +fn phantom() +{ + let _ = NameCollisions::< bool > { a : "boo".into(), b : 3, _phantom: Default::default() }; +} \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/only_test/send_sync_type.rs b/module/core/derive_tools/tests/inc/phantom/only_test/send_sync_type.rs new file mode 100644 index 0000000000..8276f07094 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/only_test/send_sync_type.rs @@ -0,0 +1,9 @@ +fn assert_send_sync< T: Send + Sync >( _x: SendSyncType< T > ) +{} + +#[ test ] +fn phantom() +{ + let x: SendSyncType::< bool > = SendSyncType { a: true, _phantom: Default::default() }; + assert_send_sync( x ); +} \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/only_test/struct_named.rs b/module/core/derive_tools/tests/inc/phantom/only_test/struct_named.rs index a1d823498d..d29423246f 100644 --- a/module/core/derive_tools/tests/inc/phantom/only_test/struct_named.rs +++ b/module/core/derive_tools/tests/inc/phantom/only_test/struct_named.rs @@ -1,5 +1,5 @@ #[ test ] fn phantom() { - let _ = StructNamed::< bool >{ a : "boo".into(), b : 3, _phantom: Default::default() }; + let _ = StructNamed::< bool > { a : "boo".into(), b : 3, _phantom: Default::default() }; } \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/only_test/struct_named_empty.rs b/module/core/derive_tools/tests/inc/phantom/only_test/struct_named_empty.rs new file mode 100644 index 0000000000..8b7da9540a --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/only_test/struct_named_empty.rs @@ -0,0 +1,5 @@ +#[ test ] +fn phantom() +{ + let _ = StructNamedEmpty::< bool > { _phantom: Default::default() }; +} \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/only_test/struct_tuple_empty.rs b/module/core/derive_tools/tests/inc/phantom/only_test/struct_tuple_empty.rs new file mode 100644 index 0000000000..865d3dc08e --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/only_test/struct_tuple_empty.rs @@ -0,0 +1,5 @@ +#[ test ] +fn phantom() +{ + let _ = StructTupleEmpty::< bool >( Default::default() ); +} \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/only_test/struct_unit_to_tuple.rs b/module/core/derive_tools/tests/inc/phantom/only_test/struct_unit_to_tuple.rs new file mode 100644 index 0000000000..abaa38b628 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/only_test/struct_unit_to_tuple.rs @@ -0,0 +1,5 @@ +#[ test ] +fn phantom() +{ + let _ = StructUnit::< bool >( Default::default() ); +} \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/send_sync_type.rs b/module/core/derive_tools/tests/inc/phantom/send_sync_type.rs new file mode 100644 index 0000000000..f50f2044f3 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/send_sync_type.rs @@ -0,0 +1,10 @@ +use super::*; + +#[ allow( dead_code ) ] +#[ the_module::phantom ] +struct SendSyncType< T > +{ + a: T, +} + +include!( "./only_test/send_sync_type.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/send_sync_type_manual.rs b/module/core/derive_tools/tests/inc/phantom/send_sync_type_manual.rs new file mode 100644 index 0000000000..0917d7db34 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/send_sync_type_manual.rs @@ -0,0 +1,10 @@ +use std::marker::PhantomData; + +#[ allow( dead_code ) ] +struct SendSyncType< T > +{ + a: T, + _phantom: PhantomData< T >, +} + +include!( "./only_test/send_sync_type.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/struct_named_empty.rs b/module/core/derive_tools/tests/inc/phantom/struct_named_empty.rs new file mode 100644 index 0000000000..aed495af34 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/struct_named_empty.rs @@ -0,0 +1,7 @@ +use super::*; + +#[ allow( dead_code ) ] +#[ the_module::phantom ] +struct StructNamedEmpty< T > {} + +include!( "./only_test/struct_named_empty.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/struct_named_empty_manual.rs b/module/core/derive_tools/tests/inc/phantom/struct_named_empty_manual.rs new file mode 100644 index 0000000000..e1929105e7 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/struct_named_empty_manual.rs @@ -0,0 +1,9 @@ +use std::marker::PhantomData; + +#[ allow( dead_code ) ] +struct StructNamedEmpty< T > +{ + _phantom : PhantomData< T >, +} + +include!( "./only_test/struct_named_empty.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/struct_named_manual.rs b/module/core/derive_tools/tests/inc/phantom/struct_named_manual.rs index 0099e18962..b98e75c0cc 100644 --- a/module/core/derive_tools/tests/inc/phantom/struct_named_manual.rs +++ b/module/core/derive_tools/tests/inc/phantom/struct_named_manual.rs @@ -1,4 +1,3 @@ -use super::*; use std::marker::PhantomData; #[ allow( dead_code ) ] diff --git a/module/core/derive_tools/tests/inc/phantom/struct_tuple_empty.rs b/module/core/derive_tools/tests/inc/phantom/struct_tuple_empty.rs new file mode 100644 index 0000000000..272672ccf5 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/struct_tuple_empty.rs @@ -0,0 +1,7 @@ +use super::*; + +#[ allow( dead_code ) ] +#[ the_module::phantom ] +struct StructTupleEmpty< T >(); + +include!( "./only_test/struct_tuple_empty.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/struct_tuple_empty_manual.rs b/module/core/derive_tools/tests/inc/phantom/struct_tuple_empty_manual.rs new file mode 100644 index 0000000000..4ebbe05a7b --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/struct_tuple_empty_manual.rs @@ -0,0 +1,6 @@ +use std::marker::PhantomData; + +#[ allow( dead_code ) ] +struct StructTupleEmpty< T >( PhantomData< T > ); + +include!( "./only_test/struct_tuple_empty.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/struct_tuple_manual.rs b/module/core/derive_tools/tests/inc/phantom/struct_tuple_manual.rs index 250c208a35..35ea17b962 100644 --- a/module/core/derive_tools/tests/inc/phantom/struct_tuple_manual.rs +++ b/module/core/derive_tools/tests/inc/phantom/struct_tuple_manual.rs @@ -1,5 +1,4 @@ use std::marker::PhantomData; -use super::*; #[ allow( dead_code ) ] struct StructTuple< T >( String, i32, PhantomData< T > ); diff --git a/module/core/derive_tools/tests/inc/phantom/struct_unit_to_tuple.rs b/module/core/derive_tools/tests/inc/phantom/struct_unit_to_tuple.rs new file mode 100644 index 0000000000..52e79926a6 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/struct_unit_to_tuple.rs @@ -0,0 +1,7 @@ +use super::*; + +#[ allow( dead_code ) ] +#[ the_module::phantom ] +struct StructUnit< T >; + +include!( "./only_test/struct_unit_to_tuple.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/struct_unit_to_tuple_manual.rs b/module/core/derive_tools/tests/inc/phantom/struct_unit_to_tuple_manual.rs new file mode 100644 index 0000000000..a4b093e7cf --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/struct_unit_to_tuple_manual.rs @@ -0,0 +1,6 @@ +use std::marker::PhantomData; + +#[ allow( dead_code ) ] +struct StructUnit< T >( PhantomData< T > ); + +include!( "./only_test/struct_unit_to_tuple.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools_meta/src/derive/phantom.rs b/module/core/derive_tools_meta/src/derive/phantom.rs index 0246cf240b..d9bf138242 100644 --- a/module/core/derive_tools_meta/src/derive/phantom.rs +++ b/module/core/derive_tools_meta/src/derive/phantom.rs @@ -1,22 +1,25 @@ use super::*; +use former_types::Assign; use macro_tools:: { - attr, diag, Result, phantom::add_to_item, quote::ToTokens, syn::ItemStruct, + AttributePropertyComponent, + AttributePropertyOptionalSingletone }; -pub fn phantom( input : proc_macro::TokenStream ) -> Result< proc_macro2::TokenStream > +pub fn phantom( _attr : proc_macro::TokenStream, input : proc_macro::TokenStream ) -> Result< proc_macro2::TokenStream > { + let attrs = syn::parse::< ItemAttributes >( _attr )?; let original_input = input.clone(); - let parsed = syn::parse::< ItemStruct >( input )?; - let has_debug = attr::has_debug( parsed.attrs.iter() )?; - let item_name = &parsed.ident; + let item_parsed = syn::parse::< ItemStruct >( input )?; - let result = add_to_item( &parsed ).to_token_stream(); + let has_debug = attrs.debug.value( false ); + let item_name = &item_parsed.ident; + let result = add_to_item( &item_parsed ).to_token_stream(); if has_debug { @@ -25,4 +28,94 @@ pub fn phantom( input : proc_macro::TokenStream ) -> Result< proc_macro2::Token } Ok( result ) -} \ No newline at end of file +} + +// == attributes + +/// Represents the attributes of a struct. Aggregates all its attributes. +#[ derive( Debug, Default ) ] +pub struct ItemAttributes +{ + /// Attribute for customizing generated code. + pub debug : AttributePropertyDebug, +} + +impl syn::parse::Parse for ItemAttributes +{ + fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + { + let mut result = Self::default(); + + let error = | ident : &syn::Ident | -> syn::Error + { + let known = const_format::concatcp! + ( + "Known properties of attribute `phantom` are : ", + AttributePropertyDebug::KEYWORD, + ".", + ); + syn_err! + ( + ident, + r#"Expects an attribute of format '#[ phantom( {} ) ]' + {known} + But got: '{}' +"#, + AttributePropertyDebug::KEYWORD, + qt!{ #ident } + ) + }; + + while !input.is_empty() + { + let lookahead = input.lookahead1(); + if lookahead.peek( syn::Ident ) + { + let ident : syn::Ident = input.parse()?; + match ident.to_string().as_str() + { + AttributePropertyDebug::KEYWORD => result.assign( AttributePropertyDebug::from( true ) ), + _ => return Err( error( &ident ) ), + } + } + else + { + return Err( lookahead.error() ); + } + + // Optional comma handling + if input.peek( syn::Token![ , ] ) + { + input.parse::< syn::Token![ , ] >()?; + } + } + + Ok( result ) + } +} + +impl< IntoT > Assign< AttributePropertyDebug, IntoT > for ItemAttributes + where + IntoT : Into< AttributePropertyDebug >, +{ + #[ inline( always ) ] + fn assign( &mut self, prop : IntoT ) + { + self.debug = prop.into(); + } +} + +// == attribute properties + +/// Marker type for attribute property to specify whether to provide a generated code as a hint. +#[ derive( Debug, Default, Clone, Copy ) ] +pub struct AttributePropertyDebugMarker; + +impl AttributePropertyComponent for AttributePropertyDebugMarker +{ + const KEYWORD : &'static str = "debug"; +} + +/// Specifies whether to provide a generated code as a hint. +/// Defaults to `false`, which means no debug is provided unless explicitly requested. +pub type AttributePropertyDebug = AttributePropertyOptionalSingletone< AttributePropertyDebugMarker >; diff --git a/module/core/derive_tools_meta/src/lib.rs b/module/core/derive_tools_meta/src/lib.rs index 6c439d73a4..d66ac3ca51 100644 --- a/module/core/derive_tools_meta/src/lib.rs +++ b/module/core/derive_tools_meta/src/lib.rs @@ -561,7 +561,7 @@ pub fn derive_variadic_from( input : proc_macro::TokenStream ) -> proc_macro::To #[ proc_macro_attribute ] pub fn phantom( _attr: proc_macro::TokenStream, input : proc_macro::TokenStream ) -> proc_macro::TokenStream { - let result = derive::phantom::phantom( input ); + let result = derive::phantom::phantom( _attr, input ); match result { Ok( stream ) => stream.into(), diff --git a/module/core/macro_tools/src/phantom.rs b/module/core/macro_tools/src/phantom.rs index 32f2de06b0..8f4a24900f 100644 --- a/module/core/macro_tools/src/phantom.rs +++ b/module/core/macro_tools/src/phantom.rs @@ -93,7 +93,20 @@ pub( crate ) mod private }, syn::Fields::Unit => { - // No fields to modify in a unit struct + let phantom_field : syn::Field = syn::parse_quote! + { + #phantom + }; + + // Replace syn::Fields::Unit to syn::Fields::Unnamed + input.fields = syn::Fields::Unnamed + ( + syn::FieldsUnnamed + { + paren_token : Default::default(), + unnamed : syn::punctuated::Punctuated::from_iter( vec![phantom_field] ) + } + ) } };