diff --git a/crates/bevy_app/Cargo.toml b/crates/bevy_app/Cargo.toml index 9f02f25554d1a..a719ddd4c9371 100644 --- a/crates/bevy_app/Cargo.toml +++ b/crates/bevy_app/Cargo.toml @@ -34,6 +34,7 @@ derive_more = { version = "1", default-features = false, features = [ "from", "display", ] } +variadics_please = "1.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] ctrlc = "3.4.4" diff --git a/crates/bevy_app/src/plugin.rs b/crates/bevy_app/src/plugin.rs index c264264695c63..73c2e452a81ee 100644 --- a/crates/bevy_app/src/plugin.rs +++ b/crates/bevy_app/src/plugin.rs @@ -129,7 +129,7 @@ pub trait Plugins: sealed::Plugins {} impl Plugins for T where T: sealed::Plugins {} mod sealed { - use bevy_utils::all_tuples; + use variadics_please::all_tuples; use crate::{App, AppError, Plugin, PluginGroup}; diff --git a/crates/bevy_ecs/Cargo.toml b/crates/bevy_ecs/Cargo.toml index 30117f71277d5..be80709fb55c2 100644 --- a/crates/bevy_ecs/Cargo.toml +++ b/crates/bevy_ecs/Cargo.toml @@ -43,6 +43,7 @@ derive_more = { version = "1", default-features = false, features = [ nonmax = "0.5" arrayvec = { version = "0.7.4", optional = true } smallvec = { version = "1", features = ["union"] } +variadics_please = "1.0" [dev-dependencies] rand = "0.8" diff --git a/crates/bevy_ecs/src/bundle.rs b/crates/bevy_ecs/src/bundle.rs index 384b7517c77b2..3da2339c0d501 100644 --- a/crates/bevy_ecs/src/bundle.rs +++ b/crates/bevy_ecs/src/bundle.rs @@ -21,10 +21,11 @@ use crate::{ world::{unsafe_world_cell::UnsafeWorldCell, ON_ADD, ON_INSERT, ON_REPLACE}, }; use bevy_ptr::{ConstNonNull, OwningPtr}; -use bevy_utils::{all_tuples, HashMap, HashSet, TypeIdMap}; +use bevy_utils::{HashMap, HashSet, TypeIdMap}; #[cfg(feature = "track_change_detection")] use core::panic::Location; use core::{any::TypeId, ptr::NonNull}; +use variadics_please::all_tuples; /// The `Bundle` trait enables insertion and removal of [`Component`]s from an entity. /// diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 77f40555c28ef..6bd32117dd1ea 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -12,9 +12,9 @@ use crate::{ }, }; use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref}; -use bevy_utils::all_tuples; use core::{cell::UnsafeCell, marker::PhantomData}; use smallvec::SmallVec; +use variadics_please::all_tuples; /// Types that can be fetched from a [`World`] using a [`Query`]. /// diff --git a/crates/bevy_ecs/src/query/filter.rs b/crates/bevy_ecs/src/query/filter.rs index ff73d6ca50016..b096e801f4cc2 100644 --- a/crates/bevy_ecs/src/query/filter.rs +++ b/crates/bevy_ecs/src/query/filter.rs @@ -7,8 +7,8 @@ use crate::{ world::{unsafe_world_cell::UnsafeWorldCell, World}, }; use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref}; -use bevy_utils::all_tuples; use core::{cell::UnsafeCell, marker::PhantomData}; +use variadics_please::all_tuples; /// Types that filter the results of a [`Query`]. /// diff --git a/crates/bevy_ecs/src/query/world_query.rs b/crates/bevy_ecs/src/query/world_query.rs index f2da8b3558f26..47bb1be40d237 100644 --- a/crates/bevy_ecs/src/query/world_query.rs +++ b/crates/bevy_ecs/src/query/world_query.rs @@ -6,7 +6,7 @@ use crate::{ storage::{Table, TableRow}, world::{unsafe_world_cell::UnsafeWorldCell, World}, }; -use bevy_utils::all_tuples; +use variadics_please::all_tuples; /// Types that can be used as parameters in a [`Query`]. /// Types that implement this should also implement either [`QueryData`] or [`QueryFilter`] diff --git a/crates/bevy_ecs/src/schedule/config.rs b/crates/bevy_ecs/src/schedule/config.rs index fd0aa58a8d950..0b4fdad860f69 100644 --- a/crates/bevy_ecs/src/schedule/config.rs +++ b/crates/bevy_ecs/src/schedule/config.rs @@ -1,4 +1,4 @@ -use bevy_utils::all_tuples; +use variadics_please::all_tuples; use crate::{ schedule::{ diff --git a/crates/bevy_ecs/src/system/builder.rs b/crates/bevy_ecs/src/system/builder.rs index ceef80dc3c4bf..d474a52de0987 100644 --- a/crates/bevy_ecs/src/system/builder.rs +++ b/crates/bevy_ecs/src/system/builder.rs @@ -1,4 +1,5 @@ -use bevy_utils::{all_tuples, synccell::SyncCell}; +use bevy_utils::synccell::SyncCell; +use variadics_please::all_tuples; use crate::{ prelude::QueryBuilder, diff --git a/crates/bevy_ecs/src/system/exclusive_function_system.rs b/crates/bevy_ecs/src/system/exclusive_function_system.rs index 8b1a06fb3a60c..2face3a9f0cb3 100644 --- a/crates/bevy_ecs/src/system/exclusive_function_system.rs +++ b/crates/bevy_ecs/src/system/exclusive_function_system.rs @@ -11,8 +11,8 @@ use crate::{ }; use alloc::borrow::Cow; -use bevy_utils::all_tuples; use core::marker::PhantomData; +use variadics_please::all_tuples; /// A function system that runs with exclusive [`World`] access. /// diff --git a/crates/bevy_ecs/src/system/exclusive_system_param.rs b/crates/bevy_ecs/src/system/exclusive_system_param.rs index 9d3279e3e053a..cc24cb7904304 100644 --- a/crates/bevy_ecs/src/system/exclusive_system_param.rs +++ b/crates/bevy_ecs/src/system/exclusive_system_param.rs @@ -4,8 +4,9 @@ use crate::{ system::{Local, SystemMeta, SystemParam, SystemState}, world::World, }; -use bevy_utils::{all_tuples, synccell::SyncCell}; +use bevy_utils::synccell::SyncCell; use core::marker::PhantomData; +use variadics_please::all_tuples; /// A parameter that can be used in an exclusive system (a system with an `&mut World` parameter). /// Any parameters implementing this trait must come after the `&mut World` parameter. diff --git a/crates/bevy_ecs/src/system/function_system.rs b/crates/bevy_ecs/src/system/function_system.rs index 43f6a3350251b..7c5806abbcd6a 100644 --- a/crates/bevy_ecs/src/system/function_system.rs +++ b/crates/bevy_ecs/src/system/function_system.rs @@ -12,8 +12,8 @@ use crate::{ }; use alloc::borrow::Cow; -use bevy_utils::all_tuples; use core::marker::PhantomData; +use variadics_please::all_tuples; #[cfg(feature = "trace")] use bevy_utils::tracing::{info_span, Span}; diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index c3e2645864094..5c6055a0e2959 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -19,7 +19,7 @@ use crate::{ use bevy_ecs_macros::impl_param_set; pub use bevy_ecs_macros::{Resource, SystemParam}; use bevy_ptr::UnsafeCellDeref; -use bevy_utils::{all_tuples, synccell::SyncCell}; +use bevy_utils::synccell::SyncCell; #[cfg(feature = "track_change_detection")] use core::panic::Location; use core::{ @@ -30,6 +30,7 @@ use core::{ }; use super::Populated; +use variadics_please::all_tuples; /// A parameter that can be used in a [`System`](super::System). /// diff --git a/crates/bevy_reflect/Cargo.toml b/crates/bevy_reflect/Cargo.toml index efc3e2d34f12e..3fe4e07a5dfb7 100644 --- a/crates/bevy_reflect/Cargo.toml +++ b/crates/bevy_reflect/Cargo.toml @@ -51,6 +51,7 @@ glam = { version = "0.29", features = ["serde"], optional = true } petgraph = { version = "0.6", features = ["serde-1"], optional = true } smol_str = { version = "0.2.0", features = ["serde"], optional = true } uuid = { version = "1.0", optional = true, features = ["v4", "serde"] } +variadics_please = "1.0" wgpu-types = { version = "23", features = ["serde"], optional = true } [dev-dependencies] diff --git a/crates/bevy_reflect/src/func/info.rs b/crates/bevy_reflect/src/func/info.rs index 39accdf52dceb..bc68469829fe8 100644 --- a/crates/bevy_reflect/src/func/info.rs +++ b/crates/bevy_reflect/src/func/info.rs @@ -1,6 +1,6 @@ use alloc::borrow::Cow; -use bevy_utils::all_tuples; +use variadics_please::all_tuples; use crate::{ func::args::{ArgInfo, GetOwnership, Ownership}, diff --git a/crates/bevy_reflect/src/func/reflect_fn.rs b/crates/bevy_reflect/src/func/reflect_fn.rs index 6e29fd4e075eb..a2b2051717359 100644 --- a/crates/bevy_reflect/src/func/reflect_fn.rs +++ b/crates/bevy_reflect/src/func/reflect_fn.rs @@ -1,4 +1,4 @@ -use bevy_utils::all_tuples; +use variadics_please::all_tuples; use crate::{ func::{ diff --git a/crates/bevy_reflect/src/func/reflect_fn_mut.rs b/crates/bevy_reflect/src/func/reflect_fn_mut.rs index be73aca79b6bb..91ff07d75af70 100644 --- a/crates/bevy_reflect/src/func/reflect_fn_mut.rs +++ b/crates/bevy_reflect/src/func/reflect_fn_mut.rs @@ -1,4 +1,4 @@ -use bevy_utils::all_tuples; +use variadics_please::all_tuples; use crate::{ func::{ diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 3807ac2fce207..5a576e2ffa574 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -1,5 +1,5 @@ use bevy_reflect_derive::impl_type_path; -use bevy_utils::all_tuples; +use variadics_please::all_tuples; use crate::generics::impl_generic_info_methods; use crate::{ diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index 8a28253c5ecc1..9559942d1eb12 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -95,6 +95,7 @@ async-channel = "2.3.0" nonmax = "0.5" smallvec = { version = "1.11", features = ["const_new"] } offset-allocator = "0.2" +variadics_please = "1.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] # Omit the `glsl` feature in non-WebAssembly by default. diff --git a/crates/bevy_render/src/render_graph/node.rs b/crates/bevy_render/src/render_graph/node.rs index c8469ee9aecea..c9ec725ff798f 100644 --- a/crates/bevy_render/src/render_graph/node.rs +++ b/crates/bevy_render/src/render_graph/node.rs @@ -13,10 +13,10 @@ use bevy_ecs::{ query::{QueryItem, QueryState, ReadOnlyQueryData}, world::{FromWorld, World}, }; -use bevy_utils::all_tuples_with_size; use core::fmt::Debug; use derive_more::derive::{Display, Error, From}; use downcast_rs::{impl_downcast, Downcast}; +use variadics_please::all_tuples_with_size; pub use bevy_render_macros::RenderLabel; diff --git a/crates/bevy_render/src/render_phase/draw.rs b/crates/bevy_render/src/render_phase/draw.rs index 44356331bc705..a03ae0a0c6feb 100644 --- a/crates/bevy_render/src/render_phase/draw.rs +++ b/crates/bevy_render/src/render_phase/draw.rs @@ -6,10 +6,11 @@ use bevy_ecs::{ system::{ReadOnlySystemParam, Resource, SystemParam, SystemParamItem, SystemState}, world::World, }; -use bevy_utils::{all_tuples, TypeIdMap}; +use bevy_utils::TypeIdMap; use core::{any::TypeId, fmt::Debug, hash::Hash}; use derive_more::derive::{Display, Error}; use std::sync::{PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard}; +use variadics_please::all_tuples; /// A draw function used to draw [`PhaseItem`]s. /// diff --git a/crates/bevy_render/src/render_resource/bind_group_entries.rs b/crates/bevy_render/src/render_resource/bind_group_entries.rs index 298a4e41fd5a1..3aaf46183ffb1 100644 --- a/crates/bevy_render/src/render_resource/bind_group_entries.rs +++ b/crates/bevy_render/src/render_resource/bind_group_entries.rs @@ -1,4 +1,4 @@ -use bevy_utils::all_tuples_with_size; +use variadics_please::all_tuples_with_size; use wgpu::{BindGroupEntry, BindingResource}; use super::{Sampler, TextureView}; diff --git a/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs b/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs index 45f4c26c6cd22..3a811a5dbe41b 100644 --- a/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs +++ b/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs @@ -1,5 +1,5 @@ -use bevy_utils::all_tuples_with_size; use core::num::NonZero; +use variadics_please::all_tuples_with_size; use wgpu::{BindGroupLayoutEntry, BindingType, ShaderStages}; /// Helper for constructing bind group layouts. diff --git a/crates/bevy_state/Cargo.toml b/crates/bevy_state/Cargo.toml index d8dafee87d16d..a4e93255f7c6e 100644 --- a/crates/bevy_state/Cargo.toml +++ b/crates/bevy_state/Cargo.toml @@ -23,6 +23,7 @@ bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev" } bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", optional = true } bevy_app = { path = "../bevy_app", version = "0.15.0-dev", optional = true } bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.15.0-dev", optional = true } +variadics_please = "1.0" [lints] workspace = true diff --git a/crates/bevy_state/src/state/state_set.rs b/crates/bevy_state/src/state/state_set.rs index 67cbe1a90c069..ca167d4970596 100644 --- a/crates/bevy_state/src/state/state_set.rs +++ b/crates/bevy_state/src/state/state_set.rs @@ -3,7 +3,7 @@ use bevy_ecs::{ schedule::{IntoSystemConfigs, IntoSystemSetConfigs, Schedule}, system::{Commands, IntoSystem, Res, ResMut}, }; -use bevy_utils::all_tuples; +use variadics_please::all_tuples; use self::sealed::StateSetSealed; diff --git a/crates/bevy_utils/Cargo.toml b/crates/bevy_utils/Cargo.toml index 6eb9a32020986..91bf2710e0aee 100644 --- a/crates/bevy_utils/Cargo.toml +++ b/crates/bevy_utils/Cargo.toml @@ -26,7 +26,6 @@ ahash = { version = "0.8.7", default-features = false, features = [ ] } tracing = { version = "0.1", default-features = false } hashbrown = { version = "0.14.2", default-features = false } -bevy_utils_proc_macros = { version = "0.15.0-dev", path = "macros" } thread_local = { version = "1.0", optional = true } [dev-dependencies] diff --git a/crates/bevy_utils/macros/Cargo.toml b/crates/bevy_utils/macros/Cargo.toml deleted file mode 100644 index 6c2b41a798cdc..0000000000000 --- a/crates/bevy_utils/macros/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "bevy_utils_proc_macros" -version = "0.15.0-dev" -description = "Bevy Utils Proc Macros" -edition = "2021" -license = "MIT OR Apache-2.0" -repository = "https://github.com/bevyengine/bevy" - -[lib] -proc-macro = true - -[dependencies] -syn = "2.0" -quote = "1.0" -proc-macro2 = "1.0" - -[lints] -workspace = true - -[package.metadata.docs.rs] -rustdoc-args = ["-Zunstable-options", "--generate-link-to-definition"] -all-features = true diff --git a/crates/bevy_utils/macros/src/lib.rs b/crates/bevy_utils/macros/src/lib.rs deleted file mode 100644 index d6b9cb1d83eae..0000000000000 --- a/crates/bevy_utils/macros/src/lib.rs +++ /dev/null @@ -1,402 +0,0 @@ -// FIXME(15321): solve CI failures, then replace with `#![expect()]`. -#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] - -use proc_macro::TokenStream; -use proc_macro2::{Span as Span2, TokenStream as TokenStream2}; -use quote::{format_ident, quote}; -use syn::{ - parse::{Parse, ParseStream}, - parse_macro_input, - spanned::Spanned as _, - token::Comma, - Attribute, Error, Ident, LitInt, LitStr, Result, -}; -struct AllTuples { - fake_variadic: bool, - macro_ident: Ident, - start: usize, - end: usize, - idents: Vec, -} - -impl Parse for AllTuples { - fn parse(input: ParseStream) -> Result { - let fake_variadic = input.call(parse_fake_variadic_attr)?; - let macro_ident = input.parse::()?; - input.parse::()?; - let start = input.parse::()?.base10_parse()?; - input.parse::()?; - let end = input.parse::()?.base10_parse()?; - input.parse::()?; - let mut idents = vec![input.parse::()?]; - while input.parse::().is_ok() { - idents.push(input.parse::()?); - } - - if start > 1 && fake_variadic { - return Err(Error::new( - input.span(), - "#[doc(fake_variadic)] only works when the tuple with length one is included", - )); - } - - Ok(AllTuples { - fake_variadic, - macro_ident, - start, - end, - idents, - }) - } -} - -/// Helper macro to generate tuple pyramids. Useful to generate scaffolding to work around Rust -/// lacking variadics. Invoking `all_tuples!(impl_foo, start, end, P, Q, ..)` -/// invokes `impl_foo` providing ident tuples through arity `start..=end`. -/// If you require the length of the tuple, see [`all_tuples_with_size!`]. -/// -/// # Examples -/// -/// ## Single parameter -/// -/// ``` -/// # use core::marker::PhantomData; -/// # use bevy_utils_proc_macros::all_tuples; -/// # -/// struct Foo { -/// // .. -/// # _phantom: PhantomData -/// } -/// -/// trait WrappedInFoo { -/// type Tup; -/// } -/// -/// macro_rules! impl_wrapped_in_foo { -/// ($($T:ident),*) => { -/// impl<$($T),*> WrappedInFoo for ($($T,)*) { -/// type Tup = ($(Foo<$T>,)*); -/// } -/// }; -/// } -/// -/// all_tuples!(impl_wrapped_in_foo, 0, 15, T); -/// // impl_wrapped_in_foo!(); -/// // impl_wrapped_in_foo!(T0); -/// // impl_wrapped_in_foo!(T0, T1); -/// // .. -/// // impl_wrapped_in_foo!(T0 .. T14); -/// ``` -/// -/// # Multiple parameters -/// -/// ``` -/// # use bevy_utils_proc_macros::all_tuples; -/// # -/// trait Append { -/// type Out; -/// fn append(tup: Self, item: Item) -> Self::Out; -/// } -/// -/// impl Append for () { -/// type Out = (Item,); -/// fn append(_: Self, item: Item) -> Self::Out { -/// (item,) -/// } -/// } -/// -/// macro_rules! impl_append { -/// ($(($P:ident, $p:ident)),*) => { -/// impl<$($P),*> Append for ($($P,)*) { -/// type Out = ($($P),*, Item); -/// fn append(($($p,)*): Self, item: Item) -> Self::Out { -/// ($($p),*, item) -/// } -/// } -/// } -/// } -/// -/// all_tuples!(impl_append, 1, 15, P, p); -/// // impl_append!((P0, p0)); -/// // impl_append!((P0, p0), (P1, p1)); -/// // impl_append!((P0, p0), (P1, p1), (P2, p2)); -/// // .. -/// // impl_append!((P0, p0) .. (P14, p14)); -/// ``` -/// -/// **`#[doc(fake_variadic)]`** -/// -/// To improve the readability of your docs when implementing a trait for -/// tuples or fn pointers of varying length you can use the rustdoc-internal `fake_variadic` marker. -/// All your impls are collapsed and shown as a single `impl Trait for (F₁, F₂, …, Fₙ)`. -/// -/// The `all_tuples!` macro does most of the work for you, the only change to your implementation macro -/// is that you have to accept attributes using `$(#[$meta:meta])*`. -/// -/// Since this feature requires a nightly compiler, it's only enabled on docs.rs by default. -/// Add the following to your lib.rs if not already present: -/// -/// ``` -/// // `rustdoc_internals` is needed for `#[doc(fake_variadics)]` -/// #![allow(internal_features)] -/// #![cfg_attr(any(docsrs, docsrs_dep), feature(rustdoc_internals))] -/// ``` -/// -/// ``` -/// # use bevy_utils_proc_macros::all_tuples; -/// # -/// trait Variadic {} -/// -/// impl Variadic for () {} -/// -/// macro_rules! impl_variadic { -/// ($(#[$meta:meta])* $(($P:ident, $p:ident)),*) => { -/// $(#[$meta])* -/// impl<$($P),*> Variadic for ($($P,)*) {} -/// } -/// } -/// -/// all_tuples!(#[doc(fake_variadic)] impl_variadic, 1, 15, P, p); -/// ``` -#[proc_macro] -pub fn all_tuples(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as AllTuples); - let len = 1 + input.end - input.start; - let mut ident_tuples = Vec::with_capacity(len); - for i in 0..=len { - let idents = input - .idents - .iter() - .map(|ident| format_ident!("{}{}", ident, i)); - ident_tuples.push(to_ident_tuple(idents, input.idents.len())); - } - - let macro_ident = &input.macro_ident; - let invocations = (input.start..=input.end).map(|i| { - let ident_tuples = choose_ident_tuples(&input, &ident_tuples, i); - let attrs = if input.fake_variadic { - fake_variadic_attrs(len, i) - } else { - TokenStream2::default() - }; - quote! { - #macro_ident!(#attrs #ident_tuples); - } - }); - TokenStream::from(quote! { - #( - #invocations - )* - }) -} - -/// Helper macro to generate tuple pyramids with their length. Useful to generate scaffolding to -/// work around Rust lacking variadics. Invoking `all_tuples_with_size!(impl_foo, start, end, P, Q, ..)` -/// invokes `impl_foo` providing ident tuples through arity `start..=end` preceded by their length. -/// If you don't require the length of the tuple, see [`all_tuples!`]. -/// -/// # Examples -/// -/// ## Single parameter -/// -/// ``` -/// # use core::marker::PhantomData; -/// # use bevy_utils_proc_macros::all_tuples_with_size; -/// # -/// struct Foo { -/// // .. -/// # _phantom: PhantomData -/// } -/// -/// trait WrappedInFoo { -/// type Tup; -/// const LENGTH: usize; -/// } -/// -/// macro_rules! impl_wrapped_in_foo { -/// ($N:expr, $($T:ident),*) => { -/// impl<$($T),*> WrappedInFoo for ($($T,)*) { -/// type Tup = ($(Foo<$T>,)*); -/// const LENGTH: usize = $N; -/// } -/// }; -/// } -/// -/// all_tuples_with_size!(impl_wrapped_in_foo, 0, 15, T); -/// // impl_wrapped_in_foo!(0); -/// // impl_wrapped_in_foo!(1, T0); -/// // impl_wrapped_in_foo!(2, T0, T1); -/// // .. -/// // impl_wrapped_in_foo!(15, T0 .. T14); -/// ``` -/// -/// ## Multiple parameters -/// -/// ``` -/// # use bevy_utils_proc_macros::all_tuples_with_size; -/// # -/// trait Append { -/// type Out; -/// fn append(tup: Self, item: Item) -> Self::Out; -/// } -/// -/// impl Append for () { -/// type Out = (Item,); -/// fn append(_: Self, item: Item) -> Self::Out { -/// (item,) -/// } -/// } -/// -/// macro_rules! impl_append { -/// ($N:expr, $(($P:ident, $p:ident)),*) => { -/// impl<$($P),*> Append for ($($P,)*) { -/// type Out = ($($P),*, Item); -/// fn append(($($p,)*): Self, item: Item) -> Self::Out { -/// ($($p),*, item) -/// } -/// } -/// } -/// } -/// -/// all_tuples_with_size!(impl_append, 1, 15, P, p); -/// // impl_append!(1, (P0, p0)); -/// // impl_append!(2, (P0, p0), (P1, p1)); -/// // impl_append!(3, (P0, p0), (P1, p1), (P2, p2)); -/// // .. -/// // impl_append!(15, (P0, p0) .. (P14, p14)); -/// ``` -/// -/// **`#[doc(fake_variadic)]`** -/// -/// To improve the readability of your docs when implementing a trait for -/// tuples or fn pointers of varying length you can use the rustdoc-internal `fake_variadic` marker. -/// All your impls are collapsed and shown as a single `impl Trait for (F₁, F₂, …, Fₙ)`. -/// -/// The `all_tuples!` macro does most of the work for you, the only change to your implementation macro -/// is that you have to accept attributes using `$(#[$meta:meta])*`. -/// -/// Since this feature requires a nightly compiler, it's only enabled on docs.rs by default. -/// Add the following to your lib.rs if not already present: -/// -/// ``` -/// // `rustdoc_internals` is needed for `#[doc(fake_variadics)]` -/// #![allow(internal_features)] -/// #![cfg_attr(any(docsrs, docsrs_dep), feature(rustdoc_internals))] -/// ``` -/// -/// ``` -/// # use bevy_utils_proc_macros::all_tuples_with_size; -/// # -/// trait Variadic {} -/// -/// impl Variadic for () {} -/// -/// macro_rules! impl_variadic { -/// ($N:expr, $(#[$meta:meta])* $(($P:ident, $p:ident)),*) => { -/// $(#[$meta])* -/// impl<$($P),*> Variadic for ($($P,)*) {} -/// } -/// } -/// -/// all_tuples_with_size!(#[doc(fake_variadic)] impl_variadic, 1, 15, P, p); -/// ``` -#[proc_macro] -pub fn all_tuples_with_size(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as AllTuples); - let len = 1 + input.end - input.start; - let mut ident_tuples = Vec::with_capacity(len); - for i in 0..=len { - let idents = input - .idents - .iter() - .map(|ident| format_ident!("{}{}", ident, i)); - ident_tuples.push(to_ident_tuple(idents, input.idents.len())); - } - let macro_ident = &input.macro_ident; - let invocations = (input.start..=input.end).map(|i| { - let ident_tuples = choose_ident_tuples(&input, &ident_tuples, i); - let attrs = if input.fake_variadic { - fake_variadic_attrs(len, i) - } else { - TokenStream2::default() - }; - quote! { - #macro_ident!(#i, #attrs #ident_tuples); - } - }); - TokenStream::from(quote! { - #( - #invocations - )* - }) -} - -/// Parses the attribute `#[doc(fake_variadic)]` -fn parse_fake_variadic_attr(input: ParseStream) -> Result { - let attribute = match input.call(Attribute::parse_outer)? { - attributes if attributes.is_empty() => return Ok(false), - attributes if attributes.len() == 1 => attributes[0].clone(), - attributes => { - return Err(Error::new( - input.span(), - format!("Expected exactly one attribute, got {}", attributes.len()), - )) - } - }; - - if attribute.path().is_ident("doc") { - let nested = attribute.parse_args::()?; - if nested == "fake_variadic" { - return Ok(true); - } - } - - Err(Error::new( - attribute.meta.span(), - "Unexpected attribute".to_string(), - )) -} - -fn choose_ident_tuples(input: &AllTuples, ident_tuples: &[TokenStream2], i: usize) -> TokenStream2 { - // `rustdoc` uses the first ident to generate nice - // idents with subscript numbers e.g. (F₁, F₂, …, Fₙ). - // We don't want two numbers, so we use the - // original, unnumbered idents for this case. - if input.fake_variadic && i == 1 { - let ident_tuple = to_ident_tuple(input.idents.iter().cloned(), input.idents.len()); - quote! { #ident_tuple } - } else { - let ident_tuples = &ident_tuples[..i]; - quote! { #(#ident_tuples),* } - } -} - -fn to_ident_tuple(idents: impl Iterator, len: usize) -> TokenStream2 { - if len < 2 { - quote! { #(#idents)* } - } else { - quote! { (#(#idents),*) } - } -} - -fn fake_variadic_attrs(len: usize, i: usize) -> TokenStream2 { - let cfg = quote! { any(docsrs, docsrs_dep) }; - match i { - // An empty tuple (i.e. the unit type) is still documented separately, - // so no `#[doc(hidden)]` here. - 0 => TokenStream2::default(), - // The `#[doc(fake_variadic)]` attr has to be on the first impl block. - 1 => { - let doc = LitStr::new( - &format!("This trait is implemented for tuples up to {len} items long."), - Span2::call_site(), - ); - quote! { - #[cfg_attr(#cfg, doc(fake_variadic))] - #[cfg_attr(#cfg, doc = #doc)] - } - } - _ => quote! { #[cfg_attr(#cfg, doc(hidden))] }, - } -} diff --git a/crates/bevy_utils/src/lib.rs b/crates/bevy_utils/src/lib.rs index 32cf483251b21..00329f652b02f 100644 --- a/crates/bevy_utils/src/lib.rs +++ b/crates/bevy_utils/src/lib.rs @@ -36,7 +36,6 @@ mod parallel_queue; mod time; pub use ahash::{AHasher, RandomState}; -pub use bevy_utils_proc_macros::*; pub use default::default; pub use hashbrown; #[cfg(feature = "std")] diff --git a/tools/publish.sh b/tools/publish.sh index 6576430791a12..682f4f5b3b9d1 100644 --- a/tools/publish.sh +++ b/tools/publish.sh @@ -1,6 +1,5 @@ # if crate A depends on crate B, B must come before A in this list crates=( - bevy_utils/macros bevy_utils bevy_ptr bevy_macro_utils