bevy/crates/bevy_ecs/compile_fail/tests/ui
Chris Russell 94e6fa168f
Fix unsoundness in QueryIter::sort_by (#17826)
# Objective

`QueryIter::sort_by()` is unsound. It passes the lens items with the
full `'w` lifetime, and a malicious user could smuggle them out of the
closure where they could alias with the query results.

## Solution

Make the sort closures generic in the lifetime parameter of the lens
item. This ensures the lens items cannot outlive the call to the
closure.

## Testing

Added a compile-fail test that demonstrates the unsound pattern.

## Migration Guide

The `sort` family of methods on `QueryIter` unsoundly gave access
`L::Item<'w>` with the full `'w` lifetime. It has been shortened to
`L::Item<'w>` so that items cannot escape the comparer. If you get
lifetime errors using these methods, you will need to make the comparer
generic in the new lifetime. Often this can be done by replacing named
`'w` with `'_`, or by replacing the use of a function item with a
closure.

```rust
// Before: Now fails with "error: implementation of `FnMut` is not general enough"
query.iter().sort_by::<&C>(Ord::cmp);
// After: Wrap in a closure
query.iter().sort_by::<&C>(|l, r| Ord::cmp(l, r));

query.iter().sort_by::<&C>(comparer);
// Before: Uses specific `'w` lifetime from some outer scope
// now fails with "error: implementation of `FnMut` is not general enough"
fn comparer(left: &&'w C, right: &&'w C) -> Ordering { /* ... */ }
// After: Accepts any lifetime using inferred lifetime parameter
fn comparer(left: &&C, right: &&C) -> Ordering { /* ... */ }
2025-02-26 20:36:37 +00:00
..
entity_ref_mut_lifetime_safety.rs
entity_ref_mut_lifetime_safety.stderr
query_exact_sized_iterator_safety.rs
query_exact_sized_iterator_safety.stderr
query_iter_combinations_mut_iterator_safety.rs
query_iter_combinations_mut_iterator_safety.stderr
query_iter_many_mut_iterator_safety.rs
query_iter_many_mut_iterator_safety.stderr
query_lens_lifetime_safety.rs Shorten the 'world lifetime returned from QueryLens::query(). (#17694) 2025-02-12 22:41:02 +00:00
query_lens_lifetime_safety.stderr Shorten the 'world lifetime returned from QueryLens::query(). (#17694) 2025-02-12 22:41:02 +00:00
query_lifetime_safety.rs
query_lifetime_safety.stderr
query_to_readonly.rs
query_to_readonly.stderr
query_transmute_safety.rs
query_transmute_safety.stderr
system_param_derive_readonly.rs
system_param_derive_readonly.stderr
system_query_get_lifetime_safety.rs
system_query_get_lifetime_safety.stderr
system_query_get_many_lifetime_safety.rs
system_query_get_many_lifetime_safety.stderr
system_query_get_many_mut_lifetime_safety.rs
system_query_get_many_mut_lifetime_safety.stderr
system_query_iter_lifetime_safety.rs
system_query_iter_lifetime_safety.stderr
system_query_iter_many_mut_lifetime_safety.rs
system_query_iter_many_mut_lifetime_safety.stderr
system_query_iter_sort_lifetime_safety.rs Fix unsoundness in QueryIter::sort_by (#17826) 2025-02-26 20:36:37 +00:00
system_query_iter_sort_lifetime_safety.stderr Fix unsoundness in QueryIter::sort_by (#17826) 2025-02-26 20:36:37 +00:00
system_query_set_get_lifetime_safety.rs
system_query_set_get_lifetime_safety.stderr
system_query_set_iter_lifetime_safety.rs
system_query_set_iter_lifetime_safety.stderr
system_state_get_lifetime_safety.rs
system_state_get_lifetime_safety.stderr
system_state_iter_lifetime_safety.rs
system_state_iter_lifetime_safety.stderr
system_state_iter_mut_overlap_safety.rs
system_state_iter_mut_overlap_safety.stderr
world_query_derive.rs
world_query_derive.stderr