[Merged by Bors] - Fix unsound lifetime annotation on Query::get_component#2964
Closed
BoxyUwU wants to merge 1 commit intobevyengine:mainfrom
Closed
[Merged by Bors] - Fix unsound lifetime annotation on Query::get_component#2964BoxyUwU wants to merge 1 commit intobevyengine:mainfrom
Query::get_component#2964BoxyUwU wants to merge 1 commit intobevyengine:mainfrom
Conversation
Query::get_component lifetimesQuery::get_component
Contributor
|
Sorry for stupid question, but how removing 'w lifetime helps here? |
Contributor
|
It turns the function signature from impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> where F::Fetch: FilterFetch {
pub fn get_component<'a, T: Component>(&'a self, entity: Entity) -> Result<&'w T, QueryComponentError> { ... }
}into impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> where F::Fetch: FilterFetch {
pub fn get_component<'a, T: Component>(&'a self, entity: Entity) -> Result<&'a T, QueryComponentError> { ... }
}diff: ```rust
impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> where F::Fetch: FilterFetch {
- pub fn get_component<'a, T: Component>(&'a self, entity: Entity) -> Result<&'w T, QueryComponentError> { ... }
+ pub fn get_component<'a, T: Component>(&'a self, entity: Entity) -> Result<&'a T, QueryComponentError> { ... }
}Previously the result reference was bound to the world ( |
alice-i-cecile
approved these changes
Oct 14, 2021
Member
|
bors r+ |
bors bot
pushed a commit
that referenced
this pull request
Oct 15, 2021
#2605 changed the lifetime annotations on `get_component` introducing unsoundness as you could keep the returned borrow even after using the query. Example unsoundness: ```rust use bevy::prelude::*; fn main() { App::new() .add_startup_system(startup) .add_system(unsound) .run(); } #[derive(Debug, Component, PartialEq, Eq)] struct Foo(Vec<u32>); fn startup(mut c: Commands) { let e = c.spawn().insert(Foo(vec![10])).id(); c.insert_resource(e); } fn unsound(mut q: Query<&mut Foo>, res: Res<Entity>) { let foo = q.get_component::<Foo>(*res).unwrap(); let mut foo2 = q.iter_mut().next().unwrap(); let first_elem = &foo.0[0]; for _ in 0..16 { foo2.0.push(12); } dbg!(*first_elem); } ``` output: `[src/main.rs:26] *first_elem = 0`
Contributor
Query::get_componentQuery::get_component
Member
Author
|
oh god bors is so damn fast on this repo compared to rust-lang/rust..... 😆 |
bors bot
pushed a commit
that referenced
this pull request
Mar 22, 2022
# Objective Continuation of #2964 (I really should have checked other methods when I made that PR) yeet unsound lifetime annotations on `Query` methods. Example unsoundness: ```rust use bevy::prelude::*; fn main() { App::new().add_startup_system(bar).add_system(foo).run(); } pub fn bar(mut cmds: Commands) { let e = cmds.spawn().insert(Foo { a: 10 }).id(); cmds.insert_resource(e); } #[derive(Component, Debug, PartialEq, Eq)] pub struct Foo { a: u32, } pub fn foo(mut query: Query<&mut Foo>, e: Res<Entity>) { dbg!("hi"); { let data: &Foo = query.get(*e).unwrap(); let data2: Mut<Foo> = query.get_mut(*e).unwrap(); assert_eq!(data, &*data2); // oops UB } { let data: &Foo = query.single(); let data2: Mut<Foo> = query.single_mut(); assert_eq!(data, &*data2); // oops UB } { let data: &Foo = query.get_single().unwrap(); let data2: Mut<Foo> = query.get_single_mut().unwrap(); assert_eq!(data, &*data2); // oops UB } { let data: &Foo = query.iter().next().unwrap(); let data2: Mut<Foo> = query.iter_mut().next().unwrap(); assert_eq!(data, &*data2); // oops UB } { let mut opt_data: Option<&Foo> = None; let mut opt_data_2: Option<Mut<Foo>> = None; query.for_each(|data| opt_data = Some(data)); query.for_each_mut(|data| opt_data_2 = Some(data)); assert_eq!(opt_data.unwrap(), &*opt_data_2.unwrap()); // oops UB } dbg!("bye"); } ``` ## Solution yeet unsound lifetime annotations on `Query` methods Co-authored-by: Carter Anderson <mcanders1@gmail.com>
aevyrie
pushed a commit
to aevyrie/bevy
that referenced
this pull request
Jun 7, 2022
# Objective Continuation of bevyengine#2964 (I really should have checked other methods when I made that PR) yeet unsound lifetime annotations on `Query` methods. Example unsoundness: ```rust use bevy::prelude::*; fn main() { App::new().add_startup_system(bar).add_system(foo).run(); } pub fn bar(mut cmds: Commands) { let e = cmds.spawn().insert(Foo { a: 10 }).id(); cmds.insert_resource(e); } #[derive(Component, Debug, PartialEq, Eq)] pub struct Foo { a: u32, } pub fn foo(mut query: Query<&mut Foo>, e: Res<Entity>) { dbg!("hi"); { let data: &Foo = query.get(*e).unwrap(); let data2: Mut<Foo> = query.get_mut(*e).unwrap(); assert_eq!(data, &*data2); // oops UB } { let data: &Foo = query.single(); let data2: Mut<Foo> = query.single_mut(); assert_eq!(data, &*data2); // oops UB } { let data: &Foo = query.get_single().unwrap(); let data2: Mut<Foo> = query.get_single_mut().unwrap(); assert_eq!(data, &*data2); // oops UB } { let data: &Foo = query.iter().next().unwrap(); let data2: Mut<Foo> = query.iter_mut().next().unwrap(); assert_eq!(data, &*data2); // oops UB } { let mut opt_data: Option<&Foo> = None; let mut opt_data_2: Option<Mut<Foo>> = None; query.for_each(|data| opt_data = Some(data)); query.for_each_mut(|data| opt_data_2 = Some(data)); assert_eq!(opt_data.unwrap(), &*opt_data_2.unwrap()); // oops UB } dbg!("bye"); } ``` ## Solution yeet unsound lifetime annotations on `Query` methods Co-authored-by: Carter Anderson <mcanders1@gmail.com>
ItsDoot
pushed a commit
to ItsDoot/bevy
that referenced
this pull request
Feb 1, 2023
# Objective Continuation of bevyengine#2964 (I really should have checked other methods when I made that PR) yeet unsound lifetime annotations on `Query` methods. Example unsoundness: ```rust use bevy::prelude::*; fn main() { App::new().add_startup_system(bar).add_system(foo).run(); } pub fn bar(mut cmds: Commands) { let e = cmds.spawn().insert(Foo { a: 10 }).id(); cmds.insert_resource(e); } #[derive(Component, Debug, PartialEq, Eq)] pub struct Foo { a: u32, } pub fn foo(mut query: Query<&mut Foo>, e: Res<Entity>) { dbg!("hi"); { let data: &Foo = query.get(*e).unwrap(); let data2: Mut<Foo> = query.get_mut(*e).unwrap(); assert_eq!(data, &*data2); // oops UB } { let data: &Foo = query.single(); let data2: Mut<Foo> = query.single_mut(); assert_eq!(data, &*data2); // oops UB } { let data: &Foo = query.get_single().unwrap(); let data2: Mut<Foo> = query.get_single_mut().unwrap(); assert_eq!(data, &*data2); // oops UB } { let data: &Foo = query.iter().next().unwrap(); let data2: Mut<Foo> = query.iter_mut().next().unwrap(); assert_eq!(data, &*data2); // oops UB } { let mut opt_data: Option<&Foo> = None; let mut opt_data_2: Option<Mut<Foo>> = None; query.for_each(|data| opt_data = Some(data)); query.for_each_mut(|data| opt_data_2 = Some(data)); assert_eq!(opt_data.unwrap(), &*opt_data_2.unwrap()); // oops UB } dbg!("bye"); } ``` ## Solution yeet unsound lifetime annotations on `Query` methods Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#2605 changed the lifetime annotations on
get_componentintroducing unsoundness as you could keep the returned borrow even after using the query.Example unsoundness:
output:
[src/main.rs:26] *first_elem = 0