Skip to content

Commit aab1f8e

Browse files
authored
Use #[doc(fake_variadic)] to improve docs readability (#14703)
# Objective - Fixes #14697 ## Solution This PR modifies the existing `all_tuples!` macro to optionally accept a `#[doc(fake_variadic)]` attribute in its input. If the attribute is present, each invocation of the impl macro gets the correct attributes (i.e. the first impl receives `#[doc(fake_variadic)]` while the other impls are hidden using `#[doc(hidden)]`. Impls for the empty tuple (unit type) are left untouched (that's what the [standard library](https://doc.rust-lang.org/std/cmp/trait.PartialEq.html#impl-PartialEq-for-()) and [serde](https://docs.rs/serde/latest/serde/trait.Serialize.html#impl-Serialize-for-()) do). To work around rust-lang/cargo#8811 and to get impls on re-exports to correctly show up as variadic, `--cfg docsrs_dep` is passed when building the docs for the toplevel `bevy` crate. `#[doc(fake_variadic)]` only works on tuples and fn pointers, so impls for structs like `AnyOf<(T1, T2, ..., Tn)>` are unchanged. ## Testing I built the docs locally using `RUSTDOCFLAGS='--cfg docsrs' RUSTFLAGS='--cfg docsrs_dep' cargo +nightly doc --no-deps --workspace` and checked the documentation page of a trait both in its original crate and the re-exported version in `bevy`. The description should correctly mention for how many tuple items the trait is implemented. I added `rustc-args` for docs.rs to the `bevy` crate, I hope there aren't any other notable crates that re-export `#[doc(fake_variadic)]` traits. --- ## Showcase `bevy_ecs::query::QueryData`: <img width="1015" alt="Screenshot 2024-08-12 at 16 41 28" src="https://github.com/user-attachments/assets/d40136ed-6731-475f-91a0-9df255cd24e3"> `bevy::ecs::query::QueryData` (re-export): <img width="1005" alt="Screenshot 2024-08-12 at 16 42 57" src="https://github.com/user-attachments/assets/71d44cf0-0ab0-48b0-9a51-5ce332594e12"> ## Original Description <details> Resolves #14697 Submitting as a draft for now, very WIP. Unfortunately, the docs don't show the variadics nicely when looking at reexported items. For example: `bevy_ecs::bundle::Bundle` correctly shows the variadic impl: ![image](https://github.com/user-attachments/assets/90bf8af1-1d1f-4714-9143-cdd3d0199998) while `bevy::ecs::bundle::Bundle` (the reexport) shows all the impls (not good): ![image](https://github.com/user-attachments/assets/439c428e-f712-465b-bec2-481f7bf5870b) Built using `RUSTDOCFLAGS='--cfg docsrs' cargo +nightly doc --workspace --no-deps` (`--no-deps` because of wgpu-core). Maybe I missed something or this is a limitation in the *totally not private* `#[doc(fake_variadic)]` thingy. In any case I desperately need some sleep now :)) </details>
1 parent 6ab8767 commit aab1f8e

File tree

16 files changed

+275
-57
lines changed

16 files changed

+275
-57
lines changed

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ ref_as_ptr = "warn"
4949
unsafe_op_in_unsafe_fn = "warn"
5050
missing_docs = "warn"
5151
unsafe_code = "deny"
52+
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(docsrs_dep)'] }
5253

5354
[lints]
5455
workspace = true
@@ -3363,6 +3364,11 @@ lto = "fat"
33633364
panic = "abort"
33643365

33653366
[package.metadata.docs.rs]
3367+
# This cfg is needed so that #[doc(fake_variadic)] is correctly propagated for
3368+
# impls for re-exported traits. See https://github.com/rust-lang/cargo/issues/8811
3369+
# for details on why this is needed. Since dependencies don't expect to be built
3370+
# with `--cfg docsrs` (and thus fail to compile) we use a different cfg.
3371+
rustc-args = ["--cfg docsrs_dep"]
33663372
rustdoc-args = ["-Zunstable-options", "--generate-link-to-definition"]
33673373
all-features = true
33683374
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]

crates/bevy_ecs/src/bundle.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ impl<C: Component> DynamicBundle for C {
225225
}
226226

227227
macro_rules! tuple_impl {
228-
($($name: ident),*) => {
228+
($(#[$meta:meta])* $($name: ident),*) => {
229+
$(#[$meta])*
229230
// SAFETY:
230231
// - `Bundle::component_ids` calls `ids` for each component type in the
231232
// bundle, in the exact order that `DynamicBundle::get_components` is called.
@@ -270,7 +271,13 @@ macro_rules! tuple_impl {
270271
}
271272
}
272273

273-
all_tuples!(tuple_impl, 0, 15, B);
274+
all_tuples!(
275+
#[doc(fake_variadic)]
276+
tuple_impl,
277+
0,
278+
15,
279+
B
280+
);
274281

275282
/// For a specific [`World`], this stores a unique value identifying a type of a registered [`Bundle`].
276283
///

crates/bevy_ecs/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// FIXME(11590): remove this once the lint is fixed
22
#![allow(unsafe_op_in_unsafe_fn)]
33
#![doc = include_str!("../README.md")]
4-
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
4+
// `rustdoc_internals` is needed for `#[doc(fake_variadics)]`
5+
#![allow(internal_features)]
6+
#![cfg_attr(any(docsrs, docsrs_dep), feature(doc_auto_cfg, rustdoc_internals))]
57
#![allow(unsafe_code)]
68
#![doc(
79
html_logo_url = "https://bevyengine.org/assets/icon.png",

crates/bevy_ecs/src/query/fetch.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1793,10 +1793,11 @@ unsafe impl<T: Component> ReadOnlyQueryData for Has<T> {}
17931793
pub struct AnyOf<T>(PhantomData<T>);
17941794

17951795
macro_rules! impl_tuple_query_data {
1796-
($(($name: ident, $state: ident)),*) => {
1796+
($(#[$meta:meta])* $(($name: ident, $state: ident)),*) => {
17971797

17981798
#[allow(non_snake_case)]
17991799
#[allow(clippy::unused_unit)]
1800+
$(#[$meta])*
18001801
// SAFETY: defers to soundness `$name: WorldQuery` impl
18011802
unsafe impl<$($name: QueryData),*> QueryData for ($($name,)*) {
18021803
type ReadOnly = ($($name::ReadOnly,)*);
@@ -1938,7 +1939,14 @@ macro_rules! impl_anytuple_fetch {
19381939
};
19391940
}
19401941

1941-
all_tuples!(impl_tuple_query_data, 0, 15, F, S);
1942+
all_tuples!(
1943+
#[doc(fake_variadic)]
1944+
impl_tuple_query_data,
1945+
0,
1946+
15,
1947+
F,
1948+
S
1949+
);
19421950
all_tuples!(impl_anytuple_fetch, 0, 15, F, S);
19431951

19441952
/// [`WorldQuery`] used to nullify queries by turning `Query<D>` into `Query<NopWorldQuery<D>>`

crates/bevy_ecs/src/query/filter.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -493,11 +493,11 @@ macro_rules! impl_or_query_filter {
493493
}
494494

495495
macro_rules! impl_tuple_query_filter {
496-
($($name: ident),*) => {
496+
($(#[$meta:meta])* $($name: ident),*) => {
497497
#[allow(unused_variables)]
498498
#[allow(non_snake_case)]
499499
#[allow(clippy::unused_unit)]
500-
500+
$(#[$meta])*
501501
impl<$($name: QueryFilter),*> QueryFilter for ($($name,)*) {
502502
const IS_ARCHETYPAL: bool = true $(&& $name::IS_ARCHETYPAL)*;
503503

@@ -516,7 +516,13 @@ macro_rules! impl_tuple_query_filter {
516516
};
517517
}
518518

519-
all_tuples!(impl_tuple_query_filter, 0, 15, F);
519+
all_tuples!(
520+
#[doc(fake_variadic)]
521+
impl_tuple_query_filter,
522+
0,
523+
15,
524+
F
525+
);
520526
all_tuples!(impl_or_query_filter, 0, 15, F, S);
521527

522528
/// A filter on a component that only retains results the first time after they have been added.
@@ -958,11 +964,24 @@ impl<T: Component> ArchetypeFilter for With<T> {}
958964
impl<T: Component> ArchetypeFilter for Without<T> {}
959965

960966
macro_rules! impl_archetype_filter_tuple {
961-
($($filter: ident),*) => {
967+
($(#[$meta:meta])* $($filter: ident),*) => {
968+
$(#[$meta])*
962969
impl<$($filter: ArchetypeFilter),*> ArchetypeFilter for ($($filter,)*) {}
970+
};
971+
}
963972

973+
macro_rules! impl_archetype_or_filter_tuple {
974+
($($filter: ident),*) => {
964975
impl<$($filter: ArchetypeFilter),*> ArchetypeFilter for Or<($($filter,)*)> {}
965976
};
966977
}
967978

968-
all_tuples!(impl_archetype_filter_tuple, 0, 15, F);
979+
all_tuples!(
980+
#[doc(fake_variadic)]
981+
impl_archetype_filter_tuple,
982+
0,
983+
15,
984+
F
985+
);
986+
987+
all_tuples!(impl_archetype_or_filter_tuple, 0, 15, F);

crates/bevy_ecs/src/query/world_query.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,11 @@ pub unsafe trait WorldQuery {
144144
}
145145

146146
macro_rules! impl_tuple_world_query {
147-
($(($name: ident, $state: ident)),*) => {
147+
($(#[$meta:meta])* $(($name: ident, $state: ident)),*) => {
148148

149149
#[allow(non_snake_case)]
150150
#[allow(clippy::unused_unit)]
151+
$(#[$meta])*
151152
/// SAFETY:
152153
/// `fetch` accesses are the conjunction of the subqueries' accesses
153154
/// This is sound because `update_component_access` adds accesses according to the implementations of all the subqueries.
@@ -229,4 +230,11 @@ macro_rules! impl_tuple_world_query {
229230
};
230231
}
231232

232-
all_tuples!(impl_tuple_world_query, 0, 15, F, S);
233+
all_tuples!(
234+
#[doc(fake_variadic)]
235+
impl_tuple_world_query,
236+
0,
237+
15,
238+
F,
239+
S
240+
);

crates/bevy_ecs/src/schedule/config.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,8 @@ impl IntoSystemConfigs<()> for SystemConfigs {
521521
pub struct SystemConfigTupleMarker;
522522

523523
macro_rules! impl_system_collection {
524-
($(($param: ident, $sys: ident)),*) => {
524+
($(#[$meta:meta])* $(($param: ident, $sys: ident)),*) => {
525+
$(#[$meta])*
525526
impl<$($param, $sys),*> IntoSystemConfigs<(SystemConfigTupleMarker, $($param,)*)> for ($($sys,)*)
526527
where
527528
$($sys: IntoSystemConfigs<$param>),*
@@ -539,7 +540,14 @@ macro_rules! impl_system_collection {
539540
}
540541
}
541542

542-
all_tuples!(impl_system_collection, 1, 20, P, S);
543+
all_tuples!(
544+
#[doc(fake_variadic)]
545+
impl_system_collection,
546+
1,
547+
20,
548+
P,
549+
S
550+
);
543551

544552
/// A [`SystemSet`] with scheduling metadata.
545553
pub type SystemSetConfig = NodeConfig<InternedSystemSet>;
@@ -740,7 +748,8 @@ impl IntoSystemSetConfigs for SystemSetConfig {
740748
}
741749

742750
macro_rules! impl_system_set_collection {
743-
($($set: ident),*) => {
751+
($(#[$meta:meta])* $($set: ident),*) => {
752+
$(#[$meta])*
744753
impl<$($set: IntoSystemSetConfigs),*> IntoSystemSetConfigs for ($($set,)*)
745754
{
746755
#[allow(non_snake_case)]
@@ -756,4 +765,10 @@ macro_rules! impl_system_set_collection {
756765
}
757766
}
758767

759-
all_tuples!(impl_system_set_collection, 1, 20, S);
768+
all_tuples!(
769+
#[doc(fake_variadic)]
770+
impl_system_set_collection,
771+
1,
772+
20,
773+
S
774+
);

crates/bevy_ecs/src/system/exclusive_system_param.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,10 @@ impl<S: ?Sized> ExclusiveSystemParam for PhantomData<S> {
8787
}
8888

8989
macro_rules! impl_exclusive_system_param_tuple {
90-
($($param: ident),*) => {
90+
($(#[$meta:meta])* $($param: ident),*) => {
9191
#[allow(unused_variables)]
9292
#[allow(non_snake_case)]
93+
$(#[$meta])*
9394
impl<$($param: ExclusiveSystemParam),*> ExclusiveSystemParam for ($($param,)*) {
9495
type State = ($($param::State,)*);
9596
type Item<'s> = ($($param::Item<'s>,)*);
@@ -113,7 +114,13 @@ macro_rules! impl_exclusive_system_param_tuple {
113114
};
114115
}
115116

116-
all_tuples!(impl_exclusive_system_param_tuple, 0, 16, P);
117+
all_tuples!(
118+
#[doc(fake_variadic)]
119+
impl_exclusive_system_param_tuple,
120+
0,
121+
16,
122+
P
123+
);
117124

118125
#[cfg(test)]
119126
mod tests {

crates/bevy_ecs/src/system/system_param.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ fn assert_component_access_compatibility(
383383
/// # let _event = event;
384384
/// }
385385
/// set.p1().send(MyEvent::new());
386-
///
386+
///
387387
/// let entities = set.p2().entities();
388388
/// // ...
389389
/// # let _entities = entities;
@@ -1422,13 +1422,15 @@ unsafe impl SystemParam for SystemChangeTick {
14221422
}
14231423

14241424
macro_rules! impl_system_param_tuple {
1425-
($($param: ident),*) => {
1425+
($(#[$meta:meta])* $($param: ident),*) => {
1426+
$(#[$meta])*
14261427
// SAFETY: tuple consists only of ReadOnlySystemParams
14271428
unsafe impl<$($param: ReadOnlySystemParam),*> ReadOnlySystemParam for ($($param,)*) {}
14281429

14291430
// SAFETY: implementors of each `SystemParam` in the tuple have validated their impls
14301431
#[allow(clippy::undocumented_unsafe_blocks)] // false positive by clippy
14311432
#[allow(non_snake_case)]
1433+
$(#[$meta])*
14321434
unsafe impl<$($param: SystemParam),*> SystemParam for ($($param,)*) {
14331435
type State = ($($param::State,)*);
14341436
type Item<'w, 's> = ($($param::Item::<'w, 's>,)*);
@@ -1471,7 +1473,13 @@ macro_rules! impl_system_param_tuple {
14711473
};
14721474
}
14731475

1474-
all_tuples!(impl_system_param_tuple, 0, 16, P);
1476+
all_tuples!(
1477+
#[doc(fake_variadic)]
1478+
impl_system_param_tuple,
1479+
0,
1480+
16,
1481+
P
1482+
);
14751483

14761484
/// Contains type aliases for built-in [`SystemParam`]s with `'static` lifetimes.
14771485
/// This makes it more convenient to refer to these types in contexts where

crates/bevy_reflect/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// FIXME(3492): remove once docs are ready
22
#![allow(missing_docs)]
3-
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3+
// `rustdoc_internals` is needed for `#[doc(fake_variadics)]`
4+
#![allow(internal_features)]
5+
#![cfg_attr(any(docsrs, docsrs_dep), feature(doc_auto_cfg, rustdoc_internals))]
46
#![doc(
57
html_logo_url = "https://bevyengine.org/assets/icon.png",
68
html_favicon_url = "https://bevyengine.org/assets/icon.png"

crates/bevy_reflect/src/tuple.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J,
702702
impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K, 11: L}
703703

704704
macro_rules! impl_type_path_tuple {
705-
() => {
705+
($(#[$meta:meta])*) => {
706706
impl TypePath for () {
707707
fn type_path() -> &'static str {
708708
"()"
@@ -714,7 +714,8 @@ macro_rules! impl_type_path_tuple {
714714
}
715715
};
716716

717-
($param:ident) => {
717+
($(#[$meta:meta])* $param:ident) => {
718+
$(#[$meta])*
718719
impl <$param: TypePath> TypePath for ($param,) {
719720
fn type_path() -> &'static str {
720721
static CELL: GenericTypePathCell = GenericTypePathCell::new();
@@ -732,8 +733,8 @@ macro_rules! impl_type_path_tuple {
732733
}
733734
};
734735

735-
($last:ident $(,$param:ident)*) => {
736-
736+
($(#[$meta:meta])* $last:ident $(,$param:ident)*) => {
737+
$(#[$meta])*
737738
impl <$($param: TypePath,)* $last: TypePath> TypePath for ($($param,)* $last) {
738739
fn type_path() -> &'static str {
739740
static CELL: GenericTypePathCell = GenericTypePathCell::new();
@@ -752,7 +753,13 @@ macro_rules! impl_type_path_tuple {
752753
};
753754
}
754755

755-
all_tuples!(impl_type_path_tuple, 0, 12, P);
756+
all_tuples!(
757+
#[doc(fake_variadic)]
758+
impl_type_path_tuple,
759+
0,
760+
12,
761+
P
762+
);
756763

757764
#[cfg(feature = "functions")]
758765
const _: () = {

crates/bevy_render/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// FIXME(3492): remove once docs are ready
22
#![allow(missing_docs)]
33
#![allow(unsafe_code)]
4-
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
4+
// `rustdoc_internals` is needed for `#[doc(fake_variadics)]`
5+
#![allow(internal_features)]
6+
#![cfg_attr(any(docsrs, docsrs_dep), feature(doc_auto_cfg, rustdoc_internals))]
57
#![doc(
68
html_logo_url = "https://bevyengine.org/assets/icon.png",
79
html_favicon_url = "https://bevyengine.org/assets/icon.png"

crates/bevy_render/src/render_phase/draw.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,8 @@ pub enum RenderCommandResult {
228228
}
229229

230230
macro_rules! render_command_tuple_impl {
231-
($(($name: ident, $view: ident, $entity: ident)),*) => {
231+
($(#[$meta:meta])* $(($name: ident, $view: ident, $entity: ident)),*) => {
232+
$(#[$meta])*
232233
impl<P: PhaseItem, $($name: RenderCommand<P>),*> RenderCommand<P> for ($($name,)*) {
233234
type Param = ($($name::Param,)*);
234235
type ViewQuery = ($($name::ViewQuery,)*);
@@ -268,7 +269,15 @@ macro_rules! render_command_tuple_impl {
268269
};
269270
}
270271

271-
all_tuples!(render_command_tuple_impl, 0, 15, C, V, E);
272+
all_tuples!(
273+
#[doc(fake_variadic)]
274+
render_command_tuple_impl,
275+
0,
276+
15,
277+
C,
278+
V,
279+
E
280+
);
272281

273282
/// Wraps a [`RenderCommand`] into a state so that it can be used as a [`Draw`] function.
274283
///

crates/bevy_state/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
//! - The [`in_state<S>`](crate::condition::in_state) and [`state_changed<S>`](crate::condition::state_changed) run conditions - which are used
2828
//! to determine whether a system should run based on the current state.
2929
30+
// `rustdoc_internals` is needed for `#[doc(fake_variadics)]`
31+
#![allow(internal_features)]
32+
#![cfg_attr(any(docsrs, docsrs_dep), feature(rustdoc_internals))]
33+
3034
#[cfg(feature = "bevy_app")]
3135
/// Provides [`App`](bevy_app::App) and [`SubApp`](bevy_app::SubApp) with state installation methods
3236
pub mod app;

0 commit comments

Comments
 (0)