From fb0d61cf8b2ac0ca0dbd71356588d04852338f02 Mon Sep 17 00:00:00 2001 From: Jan Haller Date: Tue, 11 Mar 2025 21:59:08 +0100 Subject: [PATCH] Remove paste, simplify plugin macros No longer mangle the macro name. Since there are no more proc-macros (paste) involved, this should also speed up compile times in case of hundreds of class or #[itest] registrations. --- .../src/builtin/collections/packed_array.rs | 1 - godot-core/src/private.rs | 2 +- godot-ffi/Cargo.toml | 5 +- godot-ffi/src/lib.rs | 5 -- godot-ffi/src/plugins.rs | 65 +++++++------------ godot-macros/src/bench.rs | 2 +- .../src/class/data_models/inherent_impl.rs | 2 +- .../class/data_models/interface_trait_impl.rs | 2 +- godot-macros/src/class/derive_godot_class.rs | 2 +- godot-macros/src/class/godot_dyn.rs | 2 +- godot-macros/src/itest.rs | 2 +- .../rust/src/register_tests/constant_test.rs | 8 +-- 12 files changed, 36 insertions(+), 62 deletions(-) diff --git a/godot-core/src/builtin/collections/packed_array.rs b/godot-core/src/builtin/collections/packed_array.rs index a52a34cd8..3aae8dd0b 100644 --- a/godot-core/src/builtin/collections/packed_array.rs +++ b/godot-core/src/builtin/collections/packed_array.rs @@ -58,7 +58,6 @@ macro_rules! impl_packed_array { $($trait_impls:tt)* }, ) => { - // TODO expand type names in doc comments (use e.g. `paste` crate) #[doc = concat!("Implements Godot's `", stringify!($PackedArray), "` type,")] #[doc = concat!("which is a space-efficient array of `", stringify!($Element), "`s.")] /// diff --git a/godot-core/src/private.rs b/godot-core/src/private.rs index 033b8155e..c321ce256 100644 --- a/godot-core/src/private.rs +++ b/godot-core/src/private.rs @@ -135,7 +135,7 @@ pub(crate) fn iterate_plugins(mut visitor: impl FnMut(&ClassPlugin)) { #[cfg(feature = "codegen-full")] // Remove if used in other scenarios. pub(crate) fn find_inherent_impl(class_name: crate::meta::ClassName) -> Option { // We do this manually instead of using `iterate_plugins()` because we want to break as soon as we find a match. - let plugins = __godot_rust_plugin___GODOT_PLUGIN_REGISTRY.lock().unwrap(); + let plugins = __GODOT_PLUGIN_REGISTRY.lock().unwrap(); plugins.iter().find_map(|elem| { if elem.class_name == class_name { diff --git a/godot-ffi/Cargo.toml b/godot-ffi/Cargo.toml index 5ad1d5a84..f47b73514 100644 --- a/godot-ffi/Cargo.toml +++ b/godot-ffi/Cargo.toml @@ -33,11 +33,10 @@ api-4-3 = ["godot-bindings/api-4-3"] api-4-4 = ["godot-bindings/api-4-4"] # ]] -# TODO: get rid of paste and gensym, they are trivially implementable with proc-macros. Update cargo-deny. -# Especially gensym which pulls in entire syn for 10 LoC. See https://github.com/regiontog/gensym/blob/master/src/lib.rs. +# TODO: get rid of gensym, which is implementable with proc-macros. Update cargo-deny. +# gensym pulls in entire syn for 10 LoC. See https://github.com/regiontog/gensym/blob/master/src/lib.rs. # Might however require godot-ffi to depend on godot-macro, which is not ideal... [dependencies] -paste = "1" [target.'cfg(target_os = "linux")'.dependencies] libc = "0.2.153" diff --git a/godot-ffi/src/lib.rs b/godot-ffi/src/lib.rs index d5ee1f52d..01827166b 100644 --- a/godot-ffi/src/lib.rs +++ b/godot-ffi/src/lib.rs @@ -61,11 +61,6 @@ mod plugins; mod string_cache; mod toolbox; -// See https://github.com/dtolnay/paste/issues/69#issuecomment-962418430 -// and https://users.rust-lang.org/t/proc-macros-using-third-party-crate/42465/4 -#[doc(hidden)] -pub use paste; - #[doc(hidden)] #[cfg(target_family = "wasm")] pub use gensym::gensym; diff --git a/godot-ffi/src/plugins.rs b/godot-ffi/src/plugins.rs index ed6767b47..a0ab8cd1a 100644 --- a/godot-ffi/src/plugins.rs +++ b/godot-ffi/src/plugins.rs @@ -17,34 +17,29 @@ #[macro_export] macro_rules! plugin_registry { ($vis:vis $registry:ident: $Type:ty) => { - $crate::paste::paste! { - #[used] - #[allow(non_upper_case_globals)] - #[doc(hidden)] - $vis static [< __godot_rust_plugin_ $registry >]: - std::sync::Mutex> = std::sync::Mutex::new(Vec::new()); - } + #[used] + #[allow(non_upper_case_globals)] + #[doc(hidden)] + $vis static $registry: std::sync::Mutex> + = std::sync::Mutex::new(Vec::new()); }; } #[doc(hidden)] #[macro_export] -#[allow(clippy::deprecated_cfg_attr)] -#[cfg_attr(rustfmt, rustfmt::skip)] -// ^ skip: paste's [< >] syntax chokes fmt +// Following rustfmt::skip is no longer needed, but there are 2 workarounds good to know, thus preserved. +// #[allow(clippy::deprecated_cfg_attr)] +// #[cfg_attr(rustfmt, rustfmt::skip)] // cfg_attr: workaround for https://github.com/rust-lang/rust/pull/52234#issuecomment-976702997 macro_rules! plugin_execute_pre_main_wasm { ($gensym:ident,) => { // Rust presently requires that statics with a custom `#[link_section]` must be a simple - // list of bytes on the wasm target (with no extra levels of indirection such as references). + // list of bytes on the Wasm target (with no extra levels of indirection such as references). // - // As such, instead we export a fn with a random name of predictable format to be used - // by the embedder. - $crate::paste::paste! { - #[no_mangle] - extern "C" fn [< rust_gdext_registrant_ $gensym >] () { - __init(); - } + // As such, instead we export a function with a random name of predictable format to be used by the embedder. + #[no_mangle] + extern "C" fn $gensym() { + __init(); } }; } @@ -52,10 +47,6 @@ macro_rules! plugin_execute_pre_main_wasm { /// Executes a block of code before main, by utilising platform specific linker instructions. #[doc(hidden)] #[macro_export] -#[allow(clippy::deprecated_cfg_attr)] -#[cfg_attr(rustfmt, rustfmt::skip)] -// ^ skip: paste's [< >] syntax chokes fmt -// cfg_attr: workaround for https://github.com/rust-lang/rust/pull/52234#issuecomment-976702997 macro_rules! plugin_execute_pre_main { ($body:expr) => { const _: () = { @@ -63,7 +54,7 @@ macro_rules! plugin_execute_pre_main { #[used] // Windows: #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")] - // MacOS + iOS: + // macOS + iOS: #[cfg_attr(target_os = "ios", link_section = "__DATA,__mod_init_func")] #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")] // Linux, Android, BSD: @@ -88,43 +79,33 @@ macro_rules! plugin_execute_pre_main { }; } -/// register a plugin by executing code pre-main that adds the plugin to the plugin registry +/// Register a plugin by executing code pre-main that adds the plugin to the registry. #[doc(hidden)] #[macro_export] -#[allow(clippy::deprecated_cfg_attr)] -#[cfg_attr(rustfmt, rustfmt::skip)] -// ^ skip: paste's [< >] syntax chokes fmt -// cfg_attr: workaround for https://github.com/rust-lang/rust/pull/52234#issuecomment-976702997 macro_rules! plugin_add_inner { - ($registry:ident; $plugin:expr; $( $path_tt:tt )* ) => { + ($registry:path; $plugin:expr) => { $crate::plugin_execute_pre_main!({ - let mut guard = $crate::paste::paste!( $( $path_tt )* [< __godot_rust_plugin_ $registry >] ) - .lock() - .unwrap(); + let mut guard = $registry.lock().unwrap(); + guard.push($plugin); }); }; } -/// Register a plugin to a registry +/// Register a plugin to a registry. #[doc(hidden)] #[macro_export] macro_rules! plugin_add { - ( $registry:ident; $plugin:expr ) => { - $crate::plugin_add_inner!($registry; $plugin; ); - }; - - ( $registry:ident in $path:path; $plugin:expr ) => { - $crate::plugin_add_inner!($registry; $plugin; $path ::); + ( $registry:path; $plugin:expr ) => { + $crate::plugin_add_inner!($registry; $plugin); }; } -/// Iterate over all plugins in unspecified order #[doc(hidden)] #[macro_export] macro_rules! plugin_foreach_inner { ( $registry:ident; $closure:expr; $( $path_tt:tt )* ) => { - let guard = $crate::paste::paste!( $( $path_tt )* [< __godot_rust_plugin_ $registry >] ) + let guard = $( $path_tt )* $registry .lock() .unwrap(); @@ -135,7 +116,7 @@ macro_rules! plugin_foreach_inner { }; } -/// Register a plugin to a registry +/// Iterate over all plugins in unspecified order. #[doc(hidden)] #[macro_export] macro_rules! plugin_foreach { diff --git a/godot-macros/src/bench.rs b/godot-macros/src/bench.rs index b09eec225..9a42b639a 100644 --- a/godot-macros/src/bench.rs +++ b/godot-macros/src/bench.rs @@ -50,7 +50,7 @@ pub fn attribute_bench(input_decl: venial::Item) -> ParseResult { } } - ::godot::sys::plugin_add!(__GODOT_BENCH in crate::framework; crate::framework::RustBenchmark { + ::godot::sys::plugin_add!(crate::framework::__GODOT_BENCH; crate::framework::RustBenchmark { name: #bench_name_str, file: std::file!(), line: std::line!(), diff --git a/godot-macros/src/class/data_models/inherent_impl.rs b/godot-macros/src/class/data_models/inherent_impl.rs index 2316308a9..1019b96fe 100644 --- a/godot-macros/src/class/data_models/inherent_impl.rs +++ b/godot-macros/src/class/data_models/inherent_impl.rs @@ -172,7 +172,7 @@ pub fn transform_inherent_impl( }; let class_registration = quote! { - ::godot::sys::plugin_add!(__GODOT_PLUGIN_REGISTRY in #prv; #prv::ClassPlugin::new::<#class_name>( + ::godot::sys::plugin_add!(#prv::__GODOT_PLUGIN_REGISTRY; #prv::ClassPlugin::new::<#class_name>( #prv::PluginItem::InherentImpl(#prv::InherentImpl::new::<#class_name>(#docs)) )); }; diff --git a/godot-macros/src/class/data_models/interface_trait_impl.rs b/godot-macros/src/class/data_models/interface_trait_impl.rs index ffd5c7efc..30045602b 100644 --- a/godot-macros/src/class/data_models/interface_trait_impl.rs +++ b/godot-macros/src/class/data_models/interface_trait_impl.rs @@ -354,7 +354,7 @@ pub fn transform_trait_impl(original_impl: venial::Impl) -> ParseResult( + ::godot::sys::plugin_add!(#prv::__GODOT_PLUGIN_REGISTRY; #prv::ClassPlugin::new::<#class_name>( #prv::PluginItem::ITraitImpl(#item_constructor) )); }; diff --git a/godot-macros/src/class/derive_godot_class.rs b/godot-macros/src/class/derive_godot_class.rs index 17775d6f0..781e7cb5f 100644 --- a/godot-macros/src/class/derive_godot_class.rs +++ b/godot-macros/src/class/derive_godot_class.rs @@ -178,7 +178,7 @@ pub fn derive_godot_class(item: venial::Item) -> ParseResult { #( #deprecations )* #( #errors )* - ::godot::sys::plugin_add!(__GODOT_PLUGIN_REGISTRY in #prv; #prv::ClassPlugin::new::<#class_name>( + ::godot::sys::plugin_add!(#prv::__GODOT_PLUGIN_REGISTRY; #prv::ClassPlugin::new::<#class_name>( #prv::PluginItem::Struct( #prv::Struct::new::<#class_name>(#docs)#(.#modifiers())* ) diff --git a/godot-macros/src/class/godot_dyn.rs b/godot-macros/src/class/godot_dyn.rs index ee6b16d08..47b8f8551 100644 --- a/godot-macros/src/class/godot_dyn.rs +++ b/godot-macros/src/class/godot_dyn.rs @@ -66,7 +66,7 @@ pub fn attribute_godot_dyn(input_decl: venial::Item) -> ParseResult } } - ::godot::sys::plugin_add!(__GODOT_PLUGIN_REGISTRY in #prv; #prv::ClassPlugin::new::<#class_path>( + ::godot::sys::plugin_add!(#prv::__GODOT_PLUGIN_REGISTRY; #prv::ClassPlugin::new::<#class_path>( #prv::PluginItem::DynTraitImpl(#prv::DynTraitImpl::new::<#class_path, dyn #trait_path #assoc_type_constraints>())) ); diff --git a/godot-macros/src/itest.rs b/godot-macros/src/itest.rs index f6a3bbbdb..d0d23b696 100644 --- a/godot-macros/src/itest.rs +++ b/godot-macros/src/itest.rs @@ -64,7 +64,7 @@ pub fn attribute_itest(input_item: venial::Item) -> ParseResult { #body } - ::godot::sys::plugin_add!(__GODOT_ITEST in crate::framework; crate::framework::RustTestCase { + ::godot::sys::plugin_add!(crate::framework::__GODOT_ITEST; crate::framework::RustTestCase { name: #test_name_str, skipped: #skipped, focused: #focused, diff --git a/itest/rust/src/register_tests/constant_test.rs b/itest/rust/src/register_tests/constant_test.rs index 8e8649a78..f9d5969a8 100644 --- a/itest/rust/src/register_tests/constant_test.rs +++ b/itest/rust/src/register_tests/constant_test.rs @@ -166,10 +166,10 @@ impl godot::obj::cap::ImplementsGodotApi for HasOtherConstants { // TODO once this is done via proc-macro, see if `register-docs` is still used in register_docs_test.rs. Otherwise, remove feature from Cargo.toml. godot::sys::plugin_add!( - __GODOT_PLUGIN_REGISTRY in ::godot::private; - ::godot::private::ClassPlugin::new::( - ::godot::private::PluginItem::InherentImpl( - ::godot::private::InherentImpl::new::( + godot::private::__GODOT_PLUGIN_REGISTRY; + godot::private::ClassPlugin::new::( + godot::private::PluginItem::InherentImpl( + godot::private::InherentImpl::new::( #[cfg(feature = "register-docs")] Default::default() )