Skip to content
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

Replace ValidationOutcome with Result #18541

Merged
merged 4 commits into from
Mar 26, 2025

Conversation

chescock
Copy link
Contributor

Objective

Make it easier to short-circuit system parameter validation.

Simplify the API surface by combining ValidationOutcome with SystemParamValidationError.

Solution

Replace ValidationOutcome with Result<(), SystemParamValidationError>. Move the docs from ValidationOutcome to SystemParamValidationError.

Add a skipped field to SystemParamValidationError to distinguish the Skipped and Invalid variants.

Use the ? operator to short-circuit validation in tuples of system params.

@alice-i-cecile alice-i-cecile added this to the 0.16 milestone Mar 25, 2025
@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events C-Code-Quality A section of code that is hard to understand or change C-Usability A targeted quality-of-life change that makes Bevy easier to use X-Uncontroversial This work is generally agreed upon D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Mar 25, 2025
// combining the results into a single `ValidationOutcome`.
ValidationOutcome::Valid$(.combine($param::validate_param($param, system_meta, world)))*
$(
$param::validate_param($param, system_meta, world)?;
Copy link
Member

Choose a reason for hiding this comment

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

This is the tricky macro code that I was struggling to make short-circuit before.

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.

Semantically this makes sense to me: parma-validation is very Result-like. I also like cutting down on the code needed, and you managed to get the macro short-circuiting properly!

Good cleanup; thanks for chewing on this :)

Copy link
Contributor

@ElliottjPierce ElliottjPierce left a comment

Choose a reason for hiding this comment

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

A few suggestions but nothing blocking approval.

There's other ways to do the short circuiting in the macro, but I agree that Result is semantically valuable here. Might be worth a type alias to provide documentation for what the result means more directly, but that's not a huge deal.

}

/// Constructs a `SystemParamValidationError` that skips the system.
pub fn skipped() -> Self {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a small thing, but could we make these constants instead? Or make them const functions with inline?(Though they're probably inlined already)

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 don't want to make them actual constants because I'm anticipating we'll want to add parameters (#18515) and it should be a smoother transition if they're already functions.

Making them const fn is a good idea, though! I'll do that.

pub struct SystemParamValidationError;
pub struct SystemParamValidationError {
/// Whether the system should be skipped.
pub skipped: bool,
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need this to be public? If we're already exposing is_skipped, etc, I don't see the need for this. Making it private would make this easier to change in the future, and it forces users to use the better documented functions.

Suggested change
pub skipped: bool,
skipped: bool,

Copy link
Member

Choose a reason for hiding this comment

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

I'd prefer to keep this pub and kill the helper method if we're deduplicating.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Whoops, I had started with it pub and failed to remove it after I added the method. Good catch!

But it sounds like we want it pub, so I'll go remove the helper methods instead. (I guess I still have some old C# habits.)

Copy link
Contributor

Choose a reason for hiding this comment

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

Works for me!

/// and handled using the unified error handling mechanisms defined in [`bevy_ecs::error`].
#[derive(Debug, PartialEq, Eq, Clone, Display, Error)]
pub struct SystemParamValidationError;
pub struct SystemParamValidationError {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a thiserror derive, but I don't see the #[error(msg)] attribute. Instead Display is derived directly. Nothing wrong with that, but is this intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No clue, sorry. It was like that when I got here, and I'm not familliar with thiserror.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's fine. We can revisit this later if we need to.

);
Ok(()) => (),
Err(e) => {
if !e.is_skipped() {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is repeated in a bunch of places. It was before too, but it might be worth pulling out into an associated function on the error type. Definitely not a problem, but worth mentioning.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup, I said the same thing on the original PR :) #18504 (comment) It sounded like it was tricky to solve at the moment, so I didn't try.

Copy link
Contributor

Choose a reason for hiding this comment

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

Well, it's only a little duplication, and it may be subject to change anyway. So we can come back to it if it's final form still has duplication and it becomes boiler plate.

@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 25, 2025
@alice-i-cecile
Copy link
Member

I'll give you a couple days to respond to feedback here, but I'm going to merge this before the next release candidate regardless <3

@alice-i-cecile alice-i-cecile 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 26, 2025
@alice-i-cecile alice-i-cecile added this pull request to the merge queue Mar 26, 2025
Merged via the queue into bevyengine:main with commit 837991a Mar 26, 2025
33 checks passed
mockersf pushed a commit that referenced this pull request Mar 26, 2025
# Objective

Make it easier to short-circuit system parameter validation.  

Simplify the API surface by combining `ValidationOutcome` with
`SystemParamValidationError`.

## Solution

Replace `ValidationOutcome` with `Result<(),
SystemParamValidationError>`. Move the docs from `ValidationOutcome` to
`SystemParamValidationError`.

Add a `skipped` field to `SystemParamValidationError` to distinguish the
`Skipped` and `Invalid` variants.

Use the `?` operator to short-circuit validation in tuples of system
params.
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-Code-Quality A section of code that is hard to understand or change C-Usability A targeted quality-of-life change that makes Bevy easier to use D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it X-Uncontroversial This work is generally agreed upon
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants