Allow write access in NestedQuery - #25642
tim-blackbird wants to merge 1 commit into
Conversation
a7b2b17 to
14498b1
Compare
|
Oh! Hah, I was just about to create a PR with a different approach to this when I saw this one had been opened :). ... Ah, okay, you're storing Let me go open my PR with the other approach for comparison. ... okay, #25652! And now I'm going to go copy the unit tests from this PR, since I didn't think to write any. |
chescock
left a comment
There was a problem hiding this comment.
That said, I'm happy to go with this approach if we want! I do think it works, but we'll probably want to adjust the safety comments a bit to make it clear that it works.
| @@ -148,14 +179,30 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> { | |||
| /// `NewD` must have a subset of the access that `D` does and match the exact same archetypes/tables | |||
There was a problem hiding this comment.
This safety requirement will need to be changed if we take this approach, since it's not satisfied by the calls in NestedQuery.
| } | ||
|
|
||
| fn init_state(world: &mut World) -> Self::State { | ||
| // SAFETY: `WorldQuery::init_nested_access` calls `QueryState::init_access`, |
There was a problem hiding this comment.
I think this needs to be changed somehow, too, but I couldn't figure out what to write here.
We need to show that we call QueryState<D, F>::init_access and not QueryState<D::ReadOnly, F>::init_access, and we might need to modify the safety requirements on new_unchecked, since it doesn't currently allow that sort of shenanigans.
Or maybe I was overthinking it and this is just fine, since the transmutes are obviously opposites of each other?
There was a problem hiding this comment.
I think your thought process here sums up why I feel your implementation is better :)
This transmute hokey pokey does feel "simply" correct considering the constraints, but it's messy and hard to pin down exactly
| // If `D::IS_ARCHETYPAL == false` or `F::IS_ARCHETYPAL == false`, | ||
| // then the nested query may filter out some entities that *it* matches, | ||
| // but it will never filter the outer query. | ||
| impl<D: ReadOnlyQueryData, F: QueryFilter> ArchetypeQueryData for NestedQuery<D, F> {} |
There was a problem hiding this comment.
This bound should be loosened, too.
| impl<D: QueryData, F: QueryFilter> ArchetypeQueryData for NestedQuery<D, F> {} |
Hmm, GitHub is being weird about suggestions on lines you didn't change.
|
I'm inclined to close this in favor of #25652 |
Objective
Remove the
ReadOnlyQueryDatabound onDforNestedQuery<D, F>Solution
As far as I could tell the only remaining issue here is the need to store the the same
QueryStatefor bothQueryDataandQueryData::ReadOnly, but that same bound allows us to soundly transmute between theStateofDandD::ReadOnlyas much as we want.Hopefully I'm right about that, kinda awkward otherwise
Notes For Reviewers
QueryDataimpl yoinked from Nested Queries #21557's description for testing these changes.ReadOnlyQueryDatabound forQueryState::as_transmuted_state. I don't think that's an issue?as_transmuted_stateisn't quite precise enough. In this PR I effectively do the exact opposite of what it says is safe. I useto_readonlyto getD::ReadOnlyand then useas_transmuted_stateto get back toD. I feel it should reference theDandFthe state was created with instead of theDandFit currently has?QueryState::to_readonlyimpl is kinda funny, hihiTesting
Mirrored the existing
NestedQuerytests to check that the mutable access withinNestedQuerycorrectly conflicts with other accesses.In 5067e4b there are some tests including one that mutably accesses a component through the inner
NestedQuery.This simple test passes miri at least.
Hi! :3