-
-
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
Improve or-with disjoint checks #7085
Improve or-with disjoint checks #7085
Conversation
Wording improvement for you.
Improved system and query data access compatibility checks in scenarios involving |
bb8359f
to
9218793
Compare
The implementation looks correct to me. The methods definitely need better names, now that the filter is no longer represented as a set (maybe names based on "and/or"). We can use the same |
I would like to see both of these things done in this PR. |
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.
This mostly makes sense, I don't see where union_with is used 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.
I'd like to see the small comments resolved, and add another system compatibility test for nested Ors:
fn sys(_: Query<&mut D, Or<(Or<(With<A>, With<B>)>), (Or<(With<A>, With<C>))>>>, _: Query<&mut D, Without<A>>) {}
I have zero confidence that I got those brackets right, but you get the idea.
Updated the implementation to support |
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.
Being unusually harsh around clarity here: this code was already tricky, and I'm nervous about ongoing correctness and ability to change this code as needed.
The short discussion on Discord prompted me to try to explain what this PR does as operations on boolean SAT formulas. I feel like this might be a nice addition to the internal documentation: The new The sequence of ORs is represented as two Regarding the operations:
|
@SkiFire13 thanks for the excellent write-up! It's quite on point, and it's even been educational for me: for example, I was looking myself for terminology such as DNF to describe the idea behind this. You've done a much better job, as I still struggle with correct semantics, naming and documenting things :D
I was considering it, but I found it made the code much messier. Lengths of
I'm afraid I didn't understand this part, could you expand on that, please? I'm trying to understand if that means that I overlooked some edge cases. |
@alice-i-cecile thank you for the comments! That's absolutely fair, I totally agree that things can be named and documented better. I feel somewhat limited by my vocabulary and discrete maths knowledge, so I'll appreciate direct suggestions for naming things and documentation. I feel a bit awkward asking others to document my code, so I'll do my best to improve the bits that I can, but I suspect that this PR will need an additional round of polish from someone with better tech writing skills |
238e97f
to
eb910ad
Compare
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.
Dramatically better now that we have more tests, more docs, and a clear theoretical framework. Some clarity suggestions for the docs.
e6d6550
to
25498a4
Compare
|
||
impl<T: SparseSetIndex> AccessFilters<T> { | ||
fn is_ruled_out_by(&self, other: &Self) -> bool { | ||
!self.with.is_disjoint(&other.without) || !self.without.is_disjoint(&other.with) |
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.
Technically speaking to be complete this also needs || !self.with.is_disjoing(&self.without) || !other.with.is_disjoint(&other.without)
in order to handle extreme cases like (With<T>, Without<T>)
being empty and thus disjoint with everything else. Not sure if we want to properly support those cases though, in practice if they happen they're almost always a mistake. The condition being at the end means it would be checked only if we're about to find a conflict, so the performance hit should not happen in the happy path.
However if it's kept like this I would add a comment explaining the missing conditions and why they're not implemented.
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, I was also thinking about this case. I'm inclined not to support it, I agree that it almost always means there's an error. Added a comment.
fca1ef2
to
09c7810
Compare
_intersected_access.extend_intersect_filter(&intermediate); | ||
_intersected_access.extend_access(&intermediate); | ||
_new_access.append_or(&intermediate); | ||
_new_access.extend_access(&intermediate); |
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.
This made me wonder if this line is actually needed. I see why we call extend_access
for AnyOf
, but I don't think we need to do this for Or
. If anyone can confirm, I'll drop it.
Co-authored-by: MinerSebas <66798382+MinerSebas@users.noreply.github.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
09c7810
to
cfc634d
Compare
Objective
This PR attempts to improve query compatibility checks in scenarios involving
Or
filters.Currently, for the following two disjoint queries, Bevy will throw a panic:
This PR addresses this particular scenario.
Solution
FilteredAccess::with
now stores a vector ofAccessFilters
(representing a pair ofwith
andwithout
bitsets), where each member represents anOr
"variant".Filters like
(With<A>, Or<(With<B>, Without<C>)>
are expected to be expanded intoA * B + A * !C
.When calculating whether queries are compatible, every
AccessFilters
of a query is tested for incompatibility with everyAccessFilters
of another query.Changelog
Or
filters