-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Fix safety invariants for WorldQuery::fetch
and simplify cloning
#8246
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 change: these safety invariants are clearer and more correct. Code simplification is a nice win too.
Co-authored-by: Alice Cecile <[email protected]>
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.
The code is a lot cleaner, and the safety requirement seems better placed as well.
I'd like to tweak the wording a bit, but otherwise this looks good to me.
crates/bevy_ecs/src/query/fetch.rs
Outdated
/// If this type does not implement [`ReadOnlyWorldQuery`], then the caller must ensure that | ||
/// it is impossible for more than one `Self::Item` to exist for the same entity at any given time. |
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'm not a fan of the wording here, because it sounds like only the Entity
needs to be unique.
Maybe something like "the caller must ensure that fetch isn't called with the same entity
or table_row
, which could lead to unsound aliasing of the Item
"?
I would like something shorter but I can't think of anything right now.
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 updated the wording, do you prefer it now?
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.
Just did a review. I'm on board, but something weird is going on with this branch. I can't do a merge locally because the branches have "unrelated histories", nor can I rebase without getting a ton of conflicts from files untouched by this PR.
Git has a way of overriding this for merges (--allow-unrelated-histories
) but thats the kind of thing that makes me uncomfortable.
A couple of questions for @JoJoJet :
- Can you think of any reasons for why that would happen?
- Can you re-apply these changes somehow on a valid branch from
main
?
Moving to 0.12 as we've run out of time and this branch needs fixing. This is good to fix, but its not a pressing issue. |
Not sure what the problem was, but it seems to be resolved now. |
Objective
Cloning a
WorldQuery
type's "fetch" struct was made unsafe in #5593, by adding theunsafe fn clone_fetch
toWorldQuery
. However, as that method's documentation explains, it is not the right place to put the safety invariant:You can clone a fetch struct all you want and it will never cause undefined behavior -- in order for something to go wrong, you need to improperly call
WorldQuery::fetch
with it (which is marked unsafe). Additionally, making it unsafe to clone a fetch struct does not even prevent undefined behavior, since there are other ways to incorrectly use a fetch struct. For example, you could just call fetch more than once for the same entity, which is not currently forbidden by any documented invariants.Solution
Document a safety invariant on
WorldQuery::fetch
that requires the caller to not create aliasedWorldQueryItem
s for mutable types. Remove theclone_fetch
function, and add the boundFetch: Clone
instead.Changelog
WorldQuery::clone_fetch
, and added aClone
bound toWorldQuery::Fetch
.Migration Guide
fetch
invariantsThe function
WorldQuery::fetch
has had the following safety invariant added:This invariant was always required for soundness, but was previously undocumented. If you called this function manually anywhere, you should check to make sure that this invariant is not violated.
Removed
clone_fetch
The function
WorldQuery::clone_fetch
has been removed. The associated typeWorldQuery::Fetch
now has the boundClone
.Before:
After: