-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Make Query::single (and friends) return a Result #18082
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
Make Query::single (and friends) return a Result #18082
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good direction for the engine. I look forward to reclaiming those names so get_single
can just be single
in 0.17.
examples/stress_tests/many_text2d.rs
Outdated
let mut camera_transform = camera_query.single_mut(); | ||
let Ok(mut camera_transform) = camera_query.get_single_mut() else { | ||
return; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could the signature for move_camera
not be changed to return Result
, allowing the use of ?
here too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but this is an example of a case where silently failing and just returning is always correct. You never want to panic here.
crates/bevy_ecs/src/query/builder.rs
Outdated
assert_eq!(entity_a, query_a.single(&world)); | ||
assert_eq!(entity_a, query_a.get_single(&world).unwrap()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I prefer to wrap the reference value in Ok(...)
rather an unwrap
in an assert_eq
, as that will print a nicer error message. Has the same end-result of failing the test so it's not that big of a deal though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, mildly agree.
/// fn my_system(query: Query<&A>, mut commands: Commands) { | ||
/// match query.single() { | ||
/// Ok(a) => (), // Do something with `a` | ||
/// Err(err) => match err { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like these docs!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Im a fan!
I still need to fix CI, but once that's done I'm going to call this good to merge. |
# Objective Alternative to and closes #18120. Sibling to #18082, see that PR for broader reasoning. Folks weren't sold on the name `many` (get_many is clearer, and this is rare), and that PR is much more complex. ## Solution - Simply deprecate `Query::many` and `Query::many_mut` - Clean up internal usages Mentions of this in the docs can wait until it's fully removed in the 0.17 cycle IMO: it's much easier to catch the problems when doing that. ## Testing CI! ## Migration Guide `Query::many` and `Query::many_mut` have been deprecated to reduce panics and API duplication. Use `Query::get_many` and `Query::get_many_mut` instead, and handle the `Result`. --------- Co-authored-by: Chris Russell <[email protected]>
Objective
As discussed in #14275, Bevy is currently too prone to panic, and makes the easy / beginner-friendly way to do a large number of operations just to panic on failure.
This is seriously frustrating in library code, but also slows down development, as many of the
Query::single
panics can actually safely be an early return (these panics are often due to a small ordering issue or a change in game state.More critically, in most "finished" products, panics are unacceptable: any unexpected failures should be handled elsewhere. That's where the new
With the advent of good system error handling, we can now remove this.
Note: I was instrumental in a) introducing this idea in the first place and b) pushing to make the panicking variant the default. The introduction of both
let else
statements in Rust and the fancy system error handling work in 0.16 have changed my mind on the right balance here.Solution
Query::single
andQuery::single_mut
(and other random related methods) return aResult
.Query::get_single
and friends, since we've moved their functionality to the nice names.Generally I like the diff here, although
get_single().unwrap()
in tests is a bit of a downgrade.Testing
I've done a global search for
.single
to track down any missed deprecated usages.As to whether or not all the migrations were successful, that's what CI is for :)
Future work
RenameQuery::get_single
and friends toQuery::single
!I've opted not to do this in this PR, and smear it across two releases in order to ease the migration. Successive deprecations are much easier to manage than the semantics and types shifting under your feet.Cart has convinced me to change my mind on this; see #18082 (comment).
Migration guide
Query::single
,Query::single_mut
and theirQueryState
equivalents now return aResult
. Generally, you'll want to:Result
using the?
operator.let else Ok(data)
block to early return if it's an expected failure.unwrap()
orOk
destructuring inside of tests.The old
Query::get_single
(etc) methods which did this have been deprecated.