-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
SOUNDNESS: Query should not be Copy
#17693
Comments
Good eye; that's worth double checking. I think the best way to test this is to open a draft PR with a test that tries to exploit this, and see if miri complains. |
To check if I understand this idea correctly: fn test(query: Query<&mut Test>) {
let lens = query.transmute_lens::<&Test>();
let query2 = lens.query();
let query_copy = query2;
let lens2 = query_copy.transmute_lens::<&Test>();
let query3 = lens2.query(); // And the issue is that this potentially no longer has a reference on `query`?
} |
I think that translates to fn foo(mut query: Query<EntityMut>) {
let mut first_lens = query.as_query_lens();
let second_query = first_lens.query();
let mut second_query_copy = second_query;
let mut second_lens = second_query_copy.as_query_lens();
let bad_item_one = query.iter_mut().next();
let bad_item_two = second_lens.query().into_iter().next();
} That does give me a "cannot borrow Oh, but wait, rust-analyzer tells me everything there is a |
I think you need to use |
The chain of custody should be in the If that's unsound here, would it have already been unsound with So, I still haven't worked out the exact way to reproduce it, but I agree that I introduced unsoundness! Could we fix it by changing Oh, but maybe we could have |
Okay, one reproduction is fn bad<'w>(mut lens: QueryLens<'w, EntityMut>, entity: Entity) {
let one: EntityMut<'w> = lens.query().get_inner(entity).unwrap();
let two: EntityMut<'w> = lens.query().get_inner(entity).unwrap();
assert!(one.entity() == two.entity());
} And changing the return type of |
I remember making this comment on another PR, I think it summarizes the
|
I believe the semantics for I would expect the same thing for Do those rules seem reasonable? If not, what should the rules be? Under those rules, But I think a I'll try to push up a PR with those two changes in case that's the way we want to go. |
This captures why this all is so confusing!
Note that in some items, In general, we have the inconsistent naming scheme of |
I think we might be talking past each other somehow? I understand the language-level rules, and that lifetime parameters can be substituted with different arguments. Here we're building safe abstractions with unsafe implementations, so we need to define our own safety requirements. That is, somewhere in Do you agree that that's a good way to construct proofs for unsafe operations? I'm proposing that the safety requirements for I am not including the Do you think that is a reasonable safety requirement for those types? The signature of Do you agree that |
I think we agree? In the sense that we need to determine each use of unsafe to be sound for safe abstraction to be sound in turn.
Hmm, I don't have full overview over the access infrastructure in the engine, so I am a bit cautious about this, I would definitely want other eyes to confirm that
I agree that it is unsound. If |
Oh, good! It must just have been me failing to understand something, then. Sorry!
Yup, agreed that more eyes are good! I already missed that It might also help to document the safety rules a little better. I'm not sure where to put them, though. The obvious place is on the |
I don't think
Query
beingCopy
is sound?IIUC you can go from a mutable
Query
to a read-onlyQueryLens
, make aQuery
out of that lens again, then copy thatQuery
,transmute_lens
it again, and get aQuery
from it for a last time. Then you'd have a read-only query that is no longer bound to the&mut self
of the original mutableQuery
.Did I overlook something?
Originally posted by @Victoronz in #15858 (review)
The text was updated successfully, but these errors were encountered: