From 5f8ea593be6cd9febad47c1741edb1197a517cd8 Mon Sep 17 00:00:00 2001 From: Dmytro Kriuchkov <75734980+BigglesworthCat@users.noreply.github.com> Date: Tue, 11 Jun 2024 12:54:53 +0300 Subject: [PATCH] NOT READY: Attribute macros `phantom` implementation (#1375) derive_tools : first implementation of derive_phantom --- module/core/derive_tools/Cargo.toml | 6 +++ module/core/derive_tools/tests/inc/mod.rs | 14 +++++ .../inc/phantom/only_test/struct_named.rs | 5 ++ .../inc/phantom/only_test/struct_tuple.rs | 5 ++ .../tests/inc/phantom/struct_named.rs | 11 ++++ .../tests/inc/phantom/struct_named_manual.rs | 12 +++++ .../tests/inc/phantom/struct_tuple.rs | 7 +++ .../tests/inc/phantom/struct_tuple_manual.rs | 7 +++ module/core/derive_tools_meta/Cargo.toml | 3 ++ module/core/derive_tools_meta/src/derive.rs | 2 + .../derive_tools_meta/src/derive/phantom.rs | 28 ++++++++++ module/core/derive_tools_meta/src/lib.rs | 51 +++++++++++++++++++ 12 files changed, 151 insertions(+) create mode 100644 module/core/derive_tools/tests/inc/phantom/only_test/struct_named.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/only_test/struct_tuple.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/struct_named.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/struct_named_manual.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/struct_tuple.rs create mode 100644 module/core/derive_tools/tests/inc/phantom/struct_tuple_manual.rs create mode 100644 module/core/derive_tools_meta/src/derive/phantom.rs diff --git a/module/core/derive_tools/Cargo.toml b/module/core/derive_tools/Cargo.toml index 6c7b624b38..c0d83154f7 100644 --- a/module/core/derive_tools/Cargo.toml +++ b/module/core/derive_tools/Cargo.toml @@ -72,6 +72,8 @@ default = [ "derive_inner_from", "derive_new", + "derive_phantom" + # "use_std", ] @@ -117,6 +119,8 @@ full = [ "derive_inner_from", "derive_new", + "derive_phantom" + # "use_std", ] no_std = [] @@ -177,6 +181,8 @@ derive_from = [ "derive_tools_meta/derive_from" ] derive_inner_from = [ "derive_tools_meta/derive_inner_from" ] derive_new = [ "derive_tools_meta/derive_new" ] +derive_phantom = [ "derive_tools_meta/derive_phantom" ] + parse_display = [ "parse-display" ] diff --git a/module/core/derive_tools/tests/inc/mod.rs b/module/core/derive_tools/tests/inc/mod.rs index 3a192d777a..50b89b3e88 100644 --- a/module/core/derive_tools/tests/inc/mod.rs +++ b/module/core/derive_tools/tests/inc/mod.rs @@ -31,6 +31,7 @@ mod all_manual_test; feature = "derive_deref_mut", feature = "derive_from", feature = "derive_inner_from", + feature = "derive_phantom" ) )] mod all_test; @@ -252,3 +253,16 @@ mod inner_from_tests mod multiple_unnamed_test; } + +#[ cfg( feature = "derive_phantom" ) ] +#[ path = "phantom" ] +mod phantom_tests +{ + #[ allow( unused_imports ) ] + use super::*; + + mod struct_named; + mod struct_named_manual; + mod struct_tuple; + mod struct_tuple_manual; +} 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 new file mode 100644 index 0000000000..a1d823498d --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/only_test/struct_named.rs @@ -0,0 +1,5 @@ +#[ test ] +fn phantom() +{ + 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_tuple.rs b/module/core/derive_tools/tests/inc/phantom/only_test/struct_tuple.rs new file mode 100644 index 0000000000..a54f6e6636 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/only_test/struct_tuple.rs @@ -0,0 +1,5 @@ +#[ test ] +fn phantom() +{ + let _ = StructTuple::< bool >( "boo".into(), 3, Default::default() ); +} diff --git a/module/core/derive_tools/tests/inc/phantom/struct_named.rs b/module/core/derive_tools/tests/inc/phantom/struct_named.rs new file mode 100644 index 0000000000..51ba45b723 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/struct_named.rs @@ -0,0 +1,11 @@ +use super::*; + +#[ allow( dead_code ) ] +#[ the_module::phantom ] +struct StructNamed< T > +{ + a : String, + b : i32, +} + +include!( "./only_test/struct_named.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 new file mode 100644 index 0000000000..0099e18962 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/struct_named_manual.rs @@ -0,0 +1,12 @@ +use super::*; +use std::marker::PhantomData; + +#[ allow( dead_code ) ] +struct StructNamed< T > +{ + a : String, + b : i32, + _phantom : PhantomData< T >, +} + +include!( "./only_test/struct_named.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools/tests/inc/phantom/struct_tuple.rs b/module/core/derive_tools/tests/inc/phantom/struct_tuple.rs new file mode 100644 index 0000000000..d19af977f8 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/struct_tuple.rs @@ -0,0 +1,7 @@ +use super::*; + +#[ allow( dead_code ) ] +#[ the_module::phantom ] +struct StructTuple< T >( String, i32 ); + +include!( "./only_test/struct_tuple.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 new file mode 100644 index 0000000000..250c208a35 --- /dev/null +++ b/module/core/derive_tools/tests/inc/phantom/struct_tuple_manual.rs @@ -0,0 +1,7 @@ +use std::marker::PhantomData; +use super::*; + +#[ allow( dead_code ) ] +struct StructTuple< T >( String, i32, PhantomData< T > ); + +include!( "./only_test/struct_tuple.rs" ); \ No newline at end of file diff --git a/module/core/derive_tools_meta/Cargo.toml b/module/core/derive_tools_meta/Cargo.toml index 28db43d34a..ce8da61ae6 100644 --- a/module/core/derive_tools_meta/Cargo.toml +++ b/module/core/derive_tools_meta/Cargo.toml @@ -40,6 +40,7 @@ default = [ "derive_as_ref", "derive_as_mut", "derive_variadic_from", + "derive_phantom" ] full = [ "enabled", @@ -51,6 +52,7 @@ full = [ "derive_as_ref", "derive_as_mut", "derive_variadic_from", + "derive_phantom" ] enabled = [ "macro_tools/enabled", "iter_tools/enabled", "former_types/enabled" ] @@ -62,6 +64,7 @@ derive_from = [] derive_new = [] derive_inner_from = [] derive_variadic_from = [] +derive_phantom = [] [dependencies] # zzz : qqq : optimize features set diff --git a/module/core/derive_tools_meta/src/derive.rs b/module/core/derive_tools_meta/src/derive.rs index 5008fe2fab..1cce024835 100644 --- a/module/core/derive_tools_meta/src/derive.rs +++ b/module/core/derive_tools_meta/src/derive.rs @@ -26,3 +26,5 @@ pub mod new; pub mod variadic_from; #[ cfg( feature = "derive_reflect" ) ] pub mod reflect; +#[ cfg( feature = "derive_phantom" ) ] +pub mod phantom; diff --git a/module/core/derive_tools_meta/src/derive/phantom.rs b/module/core/derive_tools_meta/src/derive/phantom.rs new file mode 100644 index 0000000000..0246cf240b --- /dev/null +++ b/module/core/derive_tools_meta/src/derive/phantom.rs @@ -0,0 +1,28 @@ +use super::*; +use macro_tools:: +{ + attr, + diag, + Result, + phantom::add_to_item, + quote::ToTokens, + syn::ItemStruct, +}; + +pub fn phantom( input : proc_macro::TokenStream ) -> Result< proc_macro2::TokenStream > +{ + 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 result = add_to_item( &parsed ).to_token_stream(); + + if has_debug + { + let about = format!( "derive : PhantomData\nstructure : {item_name}" ); + diag::report_print( about, &original_input, &result ); + } + + Ok( result ) +} \ No newline at end of file diff --git a/module/core/derive_tools_meta/src/lib.rs b/module/core/derive_tools_meta/src/lib.rs index 0868a82f77..6c439d73a4 100644 --- a/module/core/derive_tools_meta/src/lib.rs +++ b/module/core/derive_tools_meta/src/lib.rs @@ -15,6 +15,7 @@ feature = "derive_from", feature = "derive_inner_from", feature = "derive_variadic_from", + feature = "derive_phantom" ) )] #[ cfg( feature = "enabled" ) ] @@ -30,6 +31,7 @@ mod derive; // feature = "derive_from", // feature = "derive_inner_from", // feature = "derive_variadic_from", +// feature = "derive_phantom" // ) // )] // #[ cfg( feature = "enabled" ) ] @@ -517,3 +519,52 @@ pub fn derive_variadic_from( input : proc_macro::TokenStream ) -> proc_macro::To Err( err ) => err.to_compile_error().into(), } } + +/// +/// Provides an automatic `PhantomData` field for a struct based on its generic types. +/// +/// This macro simplifies the addition of a `PhantomData` field to a struct +/// to indicate that the struct logically owns instances of the generic types, +/// even though it does not store them. +/// +/// ## Example Usage +/// +/// Instead of manually adding `PhantomData` to `MyStruct`: +/// +/// ```rust +/// use std::marker::PhantomData; +/// +/// pub struct MyStruct +/// { +/// data: i32, +/// _phantom: PhantomData, +/// } +/// ``` +/// +/// Use `#[ phantom ]` to automatically generate the `PhantomData` field: +/// +/// ```rust +/// use derive_tools_meta::*; +/// +/// #[ phantom ] +/// pub struct MyStruct< T > +/// { +/// data: i32, +/// } +/// ``` +/// +/// The macro facilitates the addition of the `PhantomData` field without additional boilerplate code. +/// + +#[ cfg( feature = "enabled" ) ] +#[ cfg ( feature = "derive_phantom" ) ] +#[ proc_macro_attribute ] +pub fn phantom( _attr: proc_macro::TokenStream, input : proc_macro::TokenStream ) -> proc_macro::TokenStream +{ + let result = derive::phantom::phantom( input ); + match result + { + Ok( stream ) => stream.into(), + Err( err ) => err.to_compile_error().into(), + } +}