Skip to content

Document required components with a marker trait #18169

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

bushrat011899
Copy link
Contributor

@bushrat011899 bushrat011899 commented Mar 6, 2025

Objective

Solution

  • Added a new trait, Require<C: Component>: Component, which is automatically implemented in the Component derive macro.

Testing

  • CI

Notes

  • This trait is purely for documentation purposes and has no impact on the functionality of required components.
  • I recommend using cargo doc --open with this PR and inspecting the Button and Node components as examples for the effects of this PR.
  • I have based this PR off of Fix Component require() IDE integration #18165 and will rebase once it is merged.

Examples

Button required components are listed logically in Trait Implementations
image

The method used to insert a required component can also be documented
image

Node can document components it requires and components that require it
image

Comparison to #18171 (Rustdoc Extension)

Cons

  • Can only place information within the trait implementation section, whereas the extension can place it anywhere, including at the top of the page as-if a user had done so themselves.
  • Information is more verbose, as it includes where bounds, etc.

Pros

  • This PR works for all ecosystem and user crates automatically, whereas the extension requires opt-in configuration during doc generation.
  • List format is better suited for items with many required components.
  • Can easily show additional information, such as the method used to insert a required component if it is not present.
  • Automatically shows documentation on the required and requiring components (e.g., Button and Node both get documentation for Button requiring Node)

@bushrat011899 bushrat011899 added C-Docs An addition or correction to our documentation A-ECS Entities, components, systems, and events X-Controversial There is active debate or serious implications around merging this PR S-Needs-Review Needs reviewer attention (from anyone!) to move forward D-Macros Code that generates Rust code labels Mar 6, 2025
@@ -202,6 +202,40 @@ pub fn derive_component(input: TokenStream) -> TokenStream {
let struct_name = &ast.ident;
let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();

let required_component_impls = attrs.requires.as_ref().map(|r| {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add #[cfg(doc)] to the generated impl/trait?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly not, I tried but cargo doc doesn't propagate doc to dependencies or macros in a way that worked reliably.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that's because of rust-lang/cargo#8811. For docs.rs and dev-doc.bevyengine.org you could set the flags in Cargo.toml/docs.yaml.

@jnhyatt
Copy link
Contributor

jnhyatt commented Mar 6, 2025

I'm not exactly a new user, but my knee-jerk reaction to seeing impl Require<FocusPolicy> for Button was "oh, I guess I can impl Require<X> for my component to require X". I'd be wary of newer users (especially new to Rust) having this misconception.

@bushrat011899
Copy link
Contributor Author

I'm not exactly a new user, but my knee-jerk reaction to seeing impl Require<FocusPolicy> for Button was "oh, I guess I can impl Require<X> for my component to require X". I'd be wary of newer users (especially new to Rust) having this misconception.

Agreed. I'm going to mark the trait as unsafe and document that you must sync implementations of this trait with the implementation of Component itself.

@SpecificProtagonist
Copy link
Contributor

Saw this just after making my own solution: #18171 :P

bushrat011899 and others added 2 commits March 6, 2025 14:09
Discourages users from implementing it themselves, since it is purely for documentation purposes.

Co-Authored-By: JoshValjosh <[email protected]>
@bushrat011899 bushrat011899 force-pushed the DocumentRequireComponentsWithMarkerTrait branch from 8376275 to 0cd1cda Compare March 6, 2025 03:10
Copy link
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm on board with this plan: the backlinks are incredibly useful. That said, this trait needs to be way more explicit about a) it just being a marker for docs and b) the fact that users should effectively never ever implement this because it's automatically generated.

I think that we should do that and remove the unsafe: there's no actual memory safety hazards here.

@alice-i-cecile alice-i-cecile added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Mar 6, 2025
@alice-i-cecile alice-i-cecile requested a review from cart March 6, 2025 23:12
bushrat011899 and others added 2 commits March 7, 2025 10:39
Co-Authored-By: Alice Cecile <[email protected]>
@bushrat011899
Copy link
Contributor Author

I've moved the trait into a doc(hidden) module named document_required_components, which ensures Require is never suggested by an IDE, and clearly communicates to users importing the trait that it's a documentation marker. I've also amended the documentation for Require to make it clear that it's up to the implementer to ensure Component actually requires the components as marked by Require.

Co-Authored-By: Alice Cecile <[email protected]>
@BD103 BD103 added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Mar 7, 2025
@@ -455,6 +455,24 @@ pub trait Component: Send + Sync + 'static {
fn visit_entities_mut(_this: &mut Self, _f: impl FnMut(&mut Entity)) {}
}

// doc(hidden) module makes it clear that usage of this trait outside of `bevy_ecs` is unsupported.
#[doc(hidden)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me, this removes all Require listings from the docs, which defeats the purpose of this feature :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah whoops, should be tested first! I assumed keeping the trait public would keep it in the documentation.

quote! {
/// If not already present, the required component will be inserted using
#[doc = #insertion_info]
impl #impl_generics #bevy_ecs_path::component::document_required_components::Require<#path> for #struct_name #type_generics #where_clause {}
Copy link
Member

@cart cart Mar 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not convinced that this is meaningfully "better" than the current "required list in Component docs":

  1. Because traits are listed alphabetically, users will hit the Component trait before they hit the Require<X> traits.
  2. The require list in Component is significantly less "noisy". You can consume the entire list at a glance, rather than needing to parse out multiple lines of docs for each required component (and needing to look "around" generics / formatting / etc)
  3. The Require trait impl is confusing / introduces a weirdness factor (even if we manage to hide it). This is non-standard trait usage (traits are generally about "rust behaviors"). People reading the docs need to deal with the fact that
  4. This introduces additional codegen, which is something we should be wary of, given that we are already "heavy" on the codegen side.

From my perspective the only real win here is that the require list shows up in the sidebar, but that is also a downside, as a long list takes up significant space and obscures other "real" trait impls. And it doesn't necessarily meaningfully improve the prominence of the require list. The sidebar is often littered with other things (ex: I have to scroll to see the list for Node).

Edit: The backlinks are kind of nice, but the fact that A->B and C->A requires are interleaved together in the list is super confusing to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additionally, our docs are just generally already very "noisy" and this adds even more to the pile.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these are valid concerns, and I don't think this technique can be amended to satisfy them. Thanks for providing the feedback! I'll close this out

@bushrat011899
Copy link
Contributor Author

Closed based on feedback as not being the desired path forward. Thanks for the reviews and feedback! Good to explore and experiment even if it doesn't get merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Docs An addition or correction to our documentation D-Macros Code that generates Rust code S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it X-Controversial There is active debate or serious implications around merging this PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants