Commit graph

463 commits

Author SHA1 Message Date
James Liu
012ae07dc8 Add global init and get accessors for all newtyped TaskPools (#2250)
Right now, a direct reference to the target TaskPool is required to launch tasks on the pools, despite the three newtyped pools (AsyncComputeTaskPool, ComputeTaskPool, and IoTaskPool) effectively acting as global instances. The need to pass a TaskPool reference adds notable friction to spawning subtasks within existing tasks. Possible use cases for this may include chaining tasks within the same pool like spawning separate send/receive I/O tasks after waiting on a network connection to be established, or allowing cross-pool dependent tasks like starting dependent multi-frame computations following a long I/O load. 

Other task execution runtimes provide static access to spawning tasks (i.e. `tokio::spawn`), which is notably easier to use than the reference passing required by `bevy_tasks` right now.

This PR makes does the following:

 * Adds `*TaskPool::init` which initializes a `OnceCell`'ed with a provided TaskPool. Failing if the pool has already been initialized.
 * Adds `*TaskPool::get` which fetches the initialized global pool of the respective type or panics. This generally should not be an issue in normal Bevy use, as the pools are initialized before they are accessed.
 * Updated default task pool initialization to either pull the global handles and save them as resources, or if they are already initialized, pull the a cloned global handle as the resource.

This should make it notably easier to build more complex task hierarchies for dependent tasks. It should also make writing bevy-adjacent, but not strictly bevy-only plugin crates easier, as the global pools ensure it's all running on the same threads.

One alternative considered is keeping a thread-local reference to the pool for all threads in each pool to enable the same `tokio::spawn` interface. This would spawn tasks on the same pool that a task is currently running in. However this potentially leads to potential footgun situations where long running blocking tasks run on `ComputeTaskPool`.
2022-06-09 02:43:24 +00:00
ira
92ddfe8ad4 Add methods for querying lists of entities. (#4879)
# Objective
Improve querying ergonomics around collections and iterators of entities.

Example how queries over Children might be done currently. 
```rust
fn system(foo_query: Query<(&Foo, &Children)>, bar_query: Query<(&Bar, &Children)>) {
    for (foo, children) in &foo_query {
        for child in children.iter() {
            if let Ok((bar, children)) = bar_query.get(*child) {
                for child in children.iter() {
                    if let Ok((foo, children)) = foo_query.get(*child) {
                        // D:
                    }
                }
            }
        }
    }
}
```
Answers #4868
Partially addresses #4864
Fixes #1470
## Solution
Based on the great work by @deontologician in #2563 

Added `iter_many` and `many_for_each_mut` to `Query`.
These take a list of entities (Anything that implements `IntoIterator<Item: Borrow<Entity>>`).

`iter_many` returns a `QueryManyIter` iterator over immutable results of a query (mutable data will be cast to an immutable form).

`many_for_each_mut` calls a closure for every result of the query, ensuring not aliased mutability. 
This iterator goes over the list of entities in order and returns the result from the query for it. Skipping over any entities that don't match the query.

Also added `unsafe fn iter_many_unsafe`.

### Examples
```rust
#[derive(Component)]
struct Counter {
    value: i32
}

#[derive(Component)]
struct Friends {
    list: Vec<Entity>,
}

fn system(
    friends_query: Query<&Friends>,
    mut counter_query: Query<&mut Counter>,
) {
    for friends in &friends_query {
        for counter in counter_query.iter_many(&friends.list) {
            println!("Friend's counter: {:?}", counter.value);
        }
        
        counter_query.many_for_each_mut(&friends.list, |mut counter| {
            counter.value += 1;
            println!("Friend's counter: {:?}", counter.value);
        });
    }
}

```

Here's how example in the Objective section can be written with this PR.
```rust
fn system(foo_query: Query<(&Foo, &Children)>, bar_query: Query<(&Bar, &Children)>) {
    for (foo, children) in &foo_query {
        for (bar, children) in bar_query.iter_many(children) {
            for (foo, children) in foo_query.iter_many(children) {
                // :D
            }
        }
    }
}
```
## Additional changes
Implemented `IntoIterator` for `&Children` because why not.
## Todo
- Bikeshed!

Co-authored-by: deontologician <deontologician@gmail.com>

Co-authored-by: devil-ira <justthecooldude@gmail.com>
2022-06-06 16:09:16 +00:00
TheRawMeatball
85cd0eb445 Add ParallelCommands system parameter (#4749)
(follow-up to #4423)
# Objective
Currently, it isn't possible to easily fire commands from within par_for_each blocks. This PR allows for issuing commands from within parallel scopes.
2022-06-06 14:46:41 +00:00
Alex Saveau
caef967d14 Derive default on ReportExecutionOrderAmbiguities (#4873) 2022-05-31 15:54:38 +00:00
Félix Lescaudey de Maneville
f000c2b951 Clippy improvements (#4665)
# Objective

Follow up to my previous MR #3718 to add new clippy warnings to bevy:

- [x] [~~option_if_let_else~~](https://rust-lang.github.io/rust-clippy/master/#option_if_let_else) (reverted)
- [x] [redundant_else](https://rust-lang.github.io/rust-clippy/master/#redundant_else)
- [x] [match_same_arms](https://rust-lang.github.io/rust-clippy/master/#match_same_arms)
- [x] [semicolon_if_nothing_returned](https://rust-lang.github.io/rust-clippy/master/#semicolon_if_nothing_returned)
- [x] [explicit_iter_loop](https://rust-lang.github.io/rust-clippy/master/#explicit_iter_loop)
- [x] [map_flatten](https://rust-lang.github.io/rust-clippy/master/#map_flatten)

There is one commit per clippy warning, and the matching flags are added to the CI execution.

To test the CI execution you may run `cargo run -p ci -- clippy` at the root.

I choose the add the flags in the `ci` tool crate to avoid having them in every `lib.rs` but I guess it could become an issue with suprise warnings coming up after a commit/push


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-05-31 01:38:07 +00:00
Giacomo Stevanato
e543941fb9 Improve soundness of CommandQueue (#4863)
# Objective

This PR aims to improve the soundness of `CommandQueue`. In particular it aims to:
- make it sound to store commands that contain padding or uninitialized bytes;
- avoid uses of commands after moving them in the queue's buffer (`std::mem::forget` is technically a use of its argument);
- remove useless checks: `self.bytes.as_mut_ptr().is_null()` is always `false` because even `Vec`s that haven't allocated use a dangling pointer. Moreover the same pointer was used to write the command, so it ought to be valid for reads if it was for writes.

## Solution

- To soundly store padding or uninitialized bytes `CommandQueue` was changed to contain a `Vec<MaybeUninit<u8>>` instead of `Vec<u8>`;
- To avoid uses of the command through `std::mem::forget`, `ManuallyDrop` was used.
 
## Other observations

While writing this PR I noticed that `CommandQueue` doesn't seem to drop the commands that weren't applied. While this is a pretty niche case (you would have to be manually using `CommandQueue`/`std::mem::swap`ping one), I wonder if it should be documented anyway.
2022-05-30 22:45:09 +00:00
James Liu
d313ba59bd Don't allocate for ComponentDescriptors of non-dynamic component types (#4725)
# Objective
Don't allocate memory for Component types known at compile-time. Save a bit of memory.

## Solution
Change `ComponentDescriptor::name` from `String` to `Cow<'static, str>` to use the `&'static str` returned by `std::any::type_name`.
2022-05-30 21:16:47 +00:00
James Liu
c174945208 Fix release builds: Move asserts under #[cfg(debug_assertions)] (#4871)
# Objective
`debug_assert!` macros must still compile properly in release mode due to how they're implemented. This is causing release builds to fail.

## Solution
Change them to `assert!` macros inside `#[cfg(debug_assertions)]` blocks.
2022-05-30 20:57:33 +00:00
Daniel McNab
80b08ea45d Allow higher order systems (#4833)
# Objective

- Higher order system could not be created by users.
- However, a simple change to `SystemParamFunction` allows this.
- Higher order systems in this case mean functions which return systems created using other systems, such as `chain` (which is basically equivalent to map)

## Solution

- Change `SystemParamFunction` to be a safe abstraction over `FnMut([In<In>,] ...params)->Out`.
- Note that I believe `SystemParamFunction` should not have been counted as part of our public api before this PR.
    - This is because its only use was an unsafe function without an actionable safety comment.
    - The safety comment was basically 'call this within bevy code'.
    - I also believe that there are no external users in its current form. 
        - A quick search on Google and in the discord confirmed this.

## See also

- https://github.com/bevyengine/bevy/pull/4666, which uses this and subsumes the example here

---

## Changelog

### Added

- `SystemParamFunction`, which can be used to create higher order systems.
2022-05-30 17:59:20 +00:00
James Liu
8e4e5a5634 Use u32 over usize for ComponentSparseSet indicies (#4723)
# Objective
Use less memory to store SparseSet components.

## Solution
Change `ComponentSparseSet` to only use `Entity::id` in it's key internally, and change the usize value in it's SparseArray to use u32 instead, as it cannot have more than u32::MAX live entities stored at once.

This should reduce the overhead of storing components in sparse set storage by 50%.
2022-05-30 16:59:40 +00:00
James Liu
c5e89894f4 Remove task_pool parameter from par_for_each(_mut) (#4705)
# Objective
Fixes #3183. Requiring a `&TaskPool` parameter is sort of meaningless if the only correct one is to use the one provided by `Res<ComputeTaskPool>` all the time.

## Solution
Have `QueryState` save a clone of the `ComputeTaskPool` which is used for all `par_for_each` functions.

~~Adds a small overhead of the internal `Arc` clone as a part of the startup, but the ergonomics win should be well worth this hardly-noticable overhead.~~

Updated the docs to note that it will panic the task pool is not present as a resource.

# Future Work
If https://github.com/bevyengine/rfcs/pull/54 is approved, we can replace these resource lookups with a static function call instead to get the `ComputeTaskPool`.

---

## Changelog
Removed: The `task_pool` parameter of `Query(State)::par_for_each(_mut)`. These calls will use the `World`'s `ComputeTaskPool` resource instead.

## Migration Guide
The `task_pool` parameter for `Query(State)::par_for_each(_mut)` has been removed. Remove these parameters from all calls to these functions.

Before:
```rust
fn parallel_system(
   task_pool: Res<ComputeTaskPool>,
   query: Query<&MyComponent>,
) {
   query.par_for_each(&task_pool, 32, |comp| {
        ...
   });
}
```

After:

```rust
fn parallel_system(query: Query<&MyComponent>) {
   query.par_for_each(32, |comp| {
        ...
   });
}
```

If using `Query(State)` outside of a system run by the scheduler, you may need to manually configure and initialize a `ComputeTaskPool` as a resource in the `World`.
2022-05-30 16:59:38 +00:00
James Liu
f59ea7e6e8 Remove redundant ComponentId in Column (#4855)
# Objective
The `ComponentId` in `Column` is redundant as it's stored in parallel in the surrounding `SparseSet` all the time.

## Solution
Remove it. Add `SparseSet::iter(_mut)` to parallel `HashMap::iter(_mut)` to allow iterating pairs of columns and their IDs.

---

## Changelog
Added: `SparseSet::iter` and `SparseSet::iter_mut`.
2022-05-30 16:41:34 +00:00
Hennadii Chernyshchyk
c02beabe22 Add QueryState::get_single_unchecked_manual and its family (#4841)
# Objective

- Rebase of #3159.
- Fixes https://github.com/bevyengine/bevy/issues/3156
- add #[inline] to single related functions so that they matches with other function defs

## Solution

* added functions to QueryState
  *  get_single_unchecked_manual
  *  get_single_unchecked
  *  get_single
  *  get_single_mut
  *  single
  *  single_mut
* make Query::get_single use QueryState::get_single_unchecked_manual
* added #[inline]

---

## Changelog

### Added

Functions `QueryState::single`, `QueryState::get_single`, `QueryState::single_mut`, `QueryState::get_single_mut`, `QueryState::get_single_unchecked`, `QueryState::get_single_unchecked_manual`.

### Changed

`QuerySingleError` is now in the `state` module.

## Migration Guide

Change `query::QuerySingleError` to `state::QuerySingleError`


Co-authored-by: 2ne1ugly <chattermin@gmail.com>
Co-authored-by: 2ne1ugly <47616772+2ne1ugly@users.noreply.github.com>
2022-05-30 16:41:33 +00:00
Boxy
e528b63e11 merge matches_archetype and matches_table (#4807)
# Objective

the code in these fns are always identical so stop having two functions

## Solution

make them the same function

---

## Changelog

change `matches_archetype` and `matches_table` to `fn matches_component_set(&self, &SparseArray<ComponentId, usize>) -> bool` then do extremely boring updating of all `FetchState` impls

## Migration Guide

- move logic of `matches_archetype` and `matches_table` into `matches_component_set` in any manual `FetchState` impls
2022-05-30 16:41:32 +00:00
Jakob Hellermann
60584139de untyped APIs for components and resources (#4447)
# Objective

Even if bevy itself does not provide any builtin scripting or modding APIs, it should have the foundations for building them yourself.
For that it should be enough to have APIs that are not tied to the actual rust types with generics, but rather accept `ComponentId`s and `bevy_ptr` ptrs.

## Solution

Add the following APIs to bevy
```rust
fn EntityRef::get_by_id(ComponentId) -> Option<Ptr<'w>>;
fn EntityMut::get_by_id(ComponentId) -> Option<Ptr<'_>>;
fn EntityMut::get_mut_by_id(ComponentId) -> Option<MutUntyped<'_>>;

fn World::get_resource_by_id(ComponentId) -> Option<Ptr<'_>>;
fn World::get_resource_mut_by_id(ComponentId) -> Option<MutUntyped<'_>>;

// Safety: `value` must point to a valid value of the component
unsafe fn World::insert_resource_by_id(ComponentId, value: OwningPtr);

fn ComponentDescriptor::new_with_layout(..) -> Self;
fn World::init_component_with_descriptor(ComponentDescriptor) -> ComponentId;
```

~~This PR would definitely benefit from #3001 (lifetime'd pointers) to make sure that the lifetimes of the pointers are valid and the my-move pointer in `insert_resource_by_id` could be an `OwningPtr`, but that can be adapter later if/when #3001 is merged.~~

### Not in this PR
- inserting components on entities (this is very tied to types with bundles and the `BundleInserter`)
- an untyped version of a query (needs good API design, has a large implementation complexity, can be done in a third-party crate)

Co-authored-by: Jakob Hellermann <hellermann@sipgate.de>
2022-05-30 15:32:47 +00:00
Boxy
1320818f96 Fix unsoundness with Or/AnyOf/Option component access' (#4659)
# Objective

Fixes #4657

Example code that wasnt panic'ing before this PR (and so was unsound):
```rust
    #[test]
    #[should_panic = "error[B0001]"]
    fn option_has_no_filter_with() {
        fn sys(_1: Query<(Option<&A>, &mut B)>, _2: Query<&mut B, Without<A>>) {}
        let mut world = World::default();
        run_system(&mut world, sys);
    }

    #[test]
    #[should_panic = "error[B0001]"]
    fn any_of_has_no_filter_with() {
        fn sys(_1: Query<(AnyOf<(&A, ())>, &mut B)>, _2: Query<&mut B, Without<A>>) {}
        let mut world = World::default();
        run_system(&mut world, sys);
    }

    #[test]
    #[should_panic = "error[B0001]"]
    fn or_has_no_filter_with() {
        fn sys(_1: Query<&mut B, Or<(With<A>, With<B>)>>, _2: Query<&mut B, Without<A>>) {}
        let mut world = World::default();
        run_system(&mut world, sys);
    }
```
## Solution

- Only add the intersection of `with`/`without` accesses of all the elements in `Or/AnyOf` to the world query's `FilteredAccess<ComponentId>` instead of the union.
- `Option`'s fix can be thought of the same way since its basically `AnyOf<T, ()>` but its impl is just simpler as `()` has no `with`/`without` accesses
---

## Changelog

- `Or`/`AnyOf`/`Option` will now report more query conflicts in order to fix unsoundness

## Migration Guide

- If you are now getting query conflicts from `Or`/`AnyOf`/`Option` rip to you and ur welcome for it now being caught
2022-05-18 20:57:24 +00:00
James Liu
2c93b5cf73 Reduce code duplication by using QueryIterationCursor in QueryIter (#4733)
# Objective
We have duplicated code between `QueryIter` and `QueryIterationCursor`. Reuse that code.

## Solution
 - Reuse `QueryIterationCursor` inside `QueryIter`.
 - Slim down `QueryIter` by removing the `&'w World`. It was only being used by the `size_hint` and `ExactSizeIterator` impls, which can use the QueryState and &Archetypes in the type already.
 - Benchmark to make sure there is no significant regression.

Relevant benchmark results seem to show that there is no tangible difference between the two. Everything seems to be either identical or within a workable margin of error here.

```
group                                          embed-cursor                            main
-----                                          ------------                            ----
fragmented_iter/base                           1.00   387.4±19.70ns        ? ?/sec     1.07   413.1±27.95ns        ? ?/sec
many_maps_iter                                 1.00     27.3±0.22ms        ? ?/sec     1.00     27.4±0.10ms        ? ?/sec
simple_iter/base                               1.00     13.8±0.07µs        ? ?/sec     1.00     13.7±0.17µs        ? ?/sec
simple_iter/sparse                             1.00     61.9±0.37µs        ? ?/sec     1.00     62.2±0.64µs        ? ?/sec
simple_iter/system                             1.00     13.7±0.34µs        ? ?/sec     1.00     13.7±0.10µs        ? ?/sec
sparse_fragmented_iter/base                    1.00     11.0±0.54ns        ? ?/sec     1.03     11.3±0.48ns        ? ?/sec
world_query_iter/50000_entities_sparse         1.08    105.0±2.68µs        ? ?/sec     1.00     97.5±2.18µs        ? ?/sec
world_query_iter/50000_entities_table          1.00     27.3±0.13µs        ? ?/sec     1.00     27.3±0.37µs        ? ?/sec
```
2022-05-18 18:34:52 +00:00
Daniel McNab
7da21b12f7 Add some more documentation to SystemParam (#4787)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/4783

## Solution

- Add more documentation about the derive, and the obscure failure case for this.
- Link to [`StaticSystemParam`](https://docs.rs/bevy/latest/bevy/ecs/system/struct.StaticSystemParam.html) in these docs.
- Also explain the attributes whilst here.
2022-05-17 22:24:50 +00:00
SarthakSingh31
dbd856de71 Nightly clippy fixes (#3491)
Fixes the following nightly clippy lints:
- ~~[map_flatten](https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten)~~ (Fixed on main)
- ~~[needless_borrow](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow)~~ (Fixed on main)
- [return_self_not_must_use](https://rust-lang.github.io/rust-clippy/master/index.html#return_self_not_must_use) (Added in 1.59.0)
- ~~[unnecessary_lazy_evaluations](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations)~~ (Fixed on main)
- [extra_unused_lifetimes](https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_lifetimes) outside of macros
- [let_unit_value](https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value)
2022-05-17 04:38:03 +00:00
Daniel McNab
b1b3bd533b Skip drop when needs_drop is false (#4773)
# Objective

- We do a lot of function pointer calls in a hot loop (clearing entities in render). This is slow, since calling function pointers cannot be optimised out. We can avoid that in the cases where the function call is a no-op.
- Alternative to https://github.com/bevyengine/bevy/pull/2897
- On my machine, in `many_cubes`, this reduces dropping time from ~150μs to ~80μs.

## Solution
-  Make `drop` in `BlobVec` an `Option`, recording whether the given drop impl is required or not.
- Note that this does add branching in some cases - we could consider splitting this into two fields, i.e. unconditionally call the `drop` fn pointer.
- My intuition of how often types stored in `World` should have non-trivial drops makes me think that would be slower, however. 

N.B. Even once this lands, we should still test having a 'drop_multiple' variant - for types with a real `Drop` impl, the current implementation is definitely optimal.
2022-05-17 04:16:55 +00:00
TheRawMeatball
516e4aaa10 Add Commands::new_from_entities (#4423)
This change allows for creating `Commands` objects from just an entities reference, which allows for creating multiple dynamically in a normal system.

Context: https://discord.com/channels/691052431525675048/774027865020039209/960857605943726142
2022-05-14 14:40:09 +00:00
James Liu
c309acd432 Fail to compile on 16-bit platforms (#4736)
# Objective
`bevy_ecs` assumes that `u32 as usize` is a lossless operation and in a few cases relies on this for soundness and correctness. The only platforms that Rust compiles to where this invariant is broken are 16-bit systems.

A very clear example of this behavior is in the SparseSetIndex impl for Entity, where it converts a u32 into a usize to act as an index. If usize is 16-bit, the conversion will overflow and provide the caller with the wrong index. This can easily result in previously unforseen aliased mutable borrows (i.e. Query::get_many_mut).

## Solution
Explicitly fail compilation on 16-bit platforms instead of introducing UB. 

Properly supporting 16-bit systems will likely need a workable use case first.

---

## Changelog
Removed: Ability to compile `bevy_ecs` on 16-bit platforms.

## Migration Guide
`bevy_ecs` will now explicitly fail to compile on 16-bit platforms.  If this is required, there is currently no alternative. Please file an issue (https://github.com/bevyengine/bevy/issues) to help detail your use case.
2022-05-13 13:18:53 +00:00
Charles
dfee7879c3 Add a clear() method to the EventReader that consumes the iterator (#4693)
# Objective

- It's pretty common to want to check if an EventReader has received one or multiple events while also needing to consume the iterator to "clear" the EventReader.
- The current approach is to do something like `events.iter().count() > 0` or `events.iter().last().is_some()`. It's not immediately obvious that the purpose of that is to consume the events and check if there were any events. My solution doesn't really solve that part, but it encapsulates the pattern.

## Solution

- Add a `.clear()` method that consumes the iterator.
	- It takes the EventReader by value to make sure it isn't used again after it has been called.

---

## Migration Guide

Not a breaking change, but if you ever found yourself in a situation where you needed to consume the EventReader and check if there was any events you can now use

```rust
fn system(events: EventReader<MyEvent>) {
	if !events.is_empty {
		events.clear();
		// Process the fact that one or more event was received
	}
}
```


Co-authored-by: Charles <IceSentry@users.noreply.github.com>
2022-05-13 00:57:04 +00:00
James Liu
0166c4f7fc Profile par_for_each(_mut) tasks (#4711)
# Objective
`Query::par_for_each` and it's variants do not show up when profiling using `tracy` or other profilers. Failing to show the impact of changing batch size, the overhead of scheduling tasks, overall thread utilization, etc. other than the effect on the surrounding system.

## Solution
Add a child span that is entered on every spawned task.

Example view of the results in `tracy` using a modified `parallel_query`: 
![image](https://user-images.githubusercontent.com/3137680/167560036-626bd091-344b-4664-b323-b692f4f16084.png)

---

## Changelog
Added: `tracing` spans for `Query::par_for_each` and its variants. Spans should now be visible for all
2022-05-13 00:33:13 +00:00
Daniel McNab
94d941661d Tidy up the code of events (#4713)
# Objective

- The code in `events.rs` was a bit messy. There was lots of duplication between `EventReader` and `ManualEventReader`, and the state management code is not needed.

## Solution

- Clean it up.

## Future work

Should we remove the type parameter from `ManualEventReader`? 
It doesn't have any meaning outside of its source `Events`. But there's no real reason why it needs to have a type parameter - it's just plain data. I didn't remove it yet to keep the type safety in some of the users of it (primarily related to `&mut World` usage)
2022-05-10 20:18:59 +00:00
Mike
9a54e2bed6 Add a tracing span for run criteria. (#4709)
# Objective

Adds a tracing span for run critieria.

This change will be invalidated by stageless, but it was a simple change.

Fixes #4681.

## Changelog

Shows how long a run criteria takes to run when tracing is enabled.
![image](https://user-images.githubusercontent.com/2180432/167517447-93dba7db-8c85-4686-90e0-30e9636f120f.png)
2022-05-10 20:18:58 +00:00
Daniel McNab
38a940dbbe Make derived SystemParam readonly if possible (#4650)
Required for https://github.com/bevyengine/bevy/pull/4402.

# Objective

- derived `SystemParam` implementations were never `ReadOnlySystemParamFetch`
- We want them to be, e.g. for `EventReader`

## Solution

- If possible, 'forward' the impl of `ReadOnlySystemParamFetch`.
2022-05-09 16:09:33 +00:00
Joy
4c878ef790 Add comparison methods to FilteredAccessSet (#4211)
# Objective

- (Eventually) reduce noise in reporting access conflicts between unordered systems. 
	- `SystemStage` only looks at unfiltered `ComponentId` access, any conflicts reported are potentially `false`.
		- the systems could still be accessing disjoint archetypes
	- Comparing systems' filtered access sets can maybe avoid that (for statically known component types).
		- #4204

## Solution

- Modify `SparseSetIndex` trait to require `PartialEq`, `Eq`, and `Hash` (all internal types except `BundleId` already did).
- Add `is_compatible` and `get_conflicts` methods to `FilteredAccessSet<T>`
	- (existing method renamed to `get_conflicts_single`)
- Add docs for those and all the other methods while I'm at it.
2022-05-09 14:39:22 +00:00
Joy
fca1c861d2 Make change lifespan deterministic and update docs (#3956)
## Objective

- ~~Make absurdly long-lived changes stay detectable for even longer (without leveling up to `u64`).~~
- Give all changes a consistent maximum lifespan.
- Improve code clarity.

## Solution

- ~~Increase the frequency of `check_tick` scans to increase the oldest reliably-detectable change.~~
(Deferred until we can benchmark the cost of a scan.)
- Ignore changes older than the maximum reliably-detectable age.
- General refactoring—name the constants, use them everywhere, and update the docs.
- Update test cases to check for the specified behavior.

## Related

This PR addresses (at least partially) the concerns raised in:

- #3071
- #3082 (and associated PR #3084)

## Background

- #1471

Given the minimum interval between `check_ticks` scans, `N`, the oldest reliably-detectable change is `u32::MAX - (2 * N - 1)` (or `MAX_CHANGE_AGE`). Reducing `N` from ~530 million (current value) to something like ~2 million would extend the lifetime of changes by a billion.

| minimum `check_ticks` interval | oldest reliably-detectable change  | usable % of `u32::MAX` |
| --- | --- | --- |
| `u32::MAX / 8`  (536,870,911) | `(u32::MAX / 4) * 3` | 75.0% |
| `2_000_000` | `u32::MAX - 3_999_999` | 99.9% |

Similarly, changes are still allowed to be between `MAX_CHANGE_AGE`-old and `u32::MAX`-old in the interim between `check_tick` scans. While we prevent their age from overflowing, the test to detect changes still compares raw values. This makes failure ultimately unreliable, since when ancient changes stop being detected varies depending on when the next scan occurs.

## Open Question

Currently, systems and system states are incorrectly initialized with their `last_change_tick` set to `0`, which doesn't handle wraparound correctly.

For consistent behavior, they should either be initialized to the world's `last_change_tick` (and detect no changes) or to `MAX_CHANGE_AGE` behind the world's current `change_tick` (and detect everything as a change). I've currently gone with the latter since that was closer to the existing behavior.

## Follow-up Work

(Edited: entire section)

We haven't actually profiled how long a `check_ticks` scan takes on a "large" `World` , so we don't know if it's safe to increase their frequency. However, we are currently relying on play sessions not lasting long enough to trigger a scan and apps not having enough entities/archetypes for it to be "expensive" (our assumption). That isn't a real solution. (Either scanning never costs enough to impact frame times or we provide an option to use `u64` change ticks. Nobody will accept random hiccups.)

To further extend the lifetime of changes, we actually only need to increment the world tick if a system has `Fetch: !ReadOnlySystemParamFetch`. The behavior will be identical because all writes are sequenced, but I'm not sure how to implement that in a way that the compiler can optimize the branch out.

Also, since having no false positives depends on a `check_ticks` scan running at least every `2 * N - 1` ticks, a `last_check_tick` should also be stored in the `World` so that any lull in system execution (like a command flush) could trigger a scan if needed. To be completely robust, all the systems initialized on the world should be scanned, not just those in the current stage.
2022-05-09 14:00:16 +00:00
TheRawMeatball
900e339a33 Add IntoIterator impls for &Query and &mut Query (#4692)
# Objective

These types of IntoIterator impls are a common pattern in Rust, and these implementations make this common pattern work for bevy queries.
2022-05-09 13:37:39 +00:00
François
89f4943157 exact sized event iterators (#3863)
# Objective

- Remove `Resource` binding on events, introduce a new `Event` trait
- Ensure event iterators are `ExactSizeIterator`

## Solution

- Builds on #2382 and #2969

## Changelog

- Events<T>, EventWriter<T>, EventReader<T> and so on now require that the underlying type is Event, rather than Resource. Both of these are trivial supertraits of Send + Sync + 'static with universal blanket implementations: this change is currently purely cosmetic.
- Event reader iterators now implement ExactSizeIterator
2022-05-09 13:19:32 +00:00
Jakob Hellermann
d63b7e9568 some cleanup for bevy_ptr (#4668)
1. change `PtrMut::as_ptr(self)` and `OwnedPtr::as_ptr(self)` to take `&self`, otherwise printing the pointer will prevent doing anything else afterwards
2. make all `as_ptr` methods safe. There's nothing unsafe about obtaining a pointer, these kinds of methods are safe in std as well [str::as_ptr](https://doc.rust-lang.org/stable/std/primitive.str.html#method.as_ptr), [Rc::as_ptr](https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#method.as_ptr)
3. rename `offset`/`add` to `byte_offset`/`byte_add`. The unprefixed methods in std add in increments of `std::mem::size_of::<T>`, not in bytes. There's a PR for rust to add these byte_ methods https://github.com/rust-lang/rust/pull/95643 and at the call site it makes it much more clear that you need to do `.byte_add(i * layout_size)` instead of `.add(i)`
2022-05-06 19:15:24 +00:00
Daniel McNab
ec805e9e07 Apply buffers in ParamSet (#4677)
# Objective

- Fix https://github.com/bevyengine/bevy/issues/4676

## Solution

- Fixes https://github.com/bevyengine/bevy/issues/4676
- I have no reason to think this isn't sound, but `ParamSet` is a bit spooky
2022-05-06 18:52:26 +00:00
Boxy
96b4956126 Fix CI (#4675) 2022-05-06 18:27:37 +00:00
Jakob Hellermann
1e322d9f76 bevy_ptr standalone crate (#4653)
# Objective

The pointer types introduced in #3001 are useful not just in `bevy_ecs`, but also in crates like `bevy_reflect` (#4475) or even outside of bevy.

## Solution

Extract `Ptr<'a>`, `PtrMut<'a>`, `OwnedPtr<'a>`, `ThinSlicePtr<'a, T>` and `UnsafeCellDeref` from `bevy_ecs::ptr` into `bevy_ptr`.

**Note:** `bevy_ecs` still reexports the `bevy_ptr` as `bevy_ecs::ptr` so that crates like `bevy_transform` can use the `Bundle` derive without needing to depend on `bevy_ptr` themselves.
2022-05-04 19:16:10 +00:00
Daniel McNab
9d440fbcb5 Make RunOnce a non-manual System impl (#3922)
# Objective

- `RunOnce` was a manual `System` implementation.
- Adding run criteria to stages was yet to be systemyoten

## Solution

- Make it a normal function
- yeet

##  Changelog

- Replaced `RunOnce` with `ShouldRun::once`

## Migration guide

The run criterion `RunOnce`, which would make the controlled systems run only once, has been replaced with a new run criterion function `ShouldRun::once`. Replace all instances of `RunOnce` with `ShouldRun::once`.
2022-05-04 18:41:37 +00:00
James Liu
3e24b725af Pointerfication followup: Type safety and cleanup (#4621)
# Objective
The `Ptr` types gives free access to the underlying `NonNull<u8>`, which adds more publicly visible pointer wrangling than there needs to be. There are also a few edge cases where Ptr types could be more readily utilized for properly validating the soundness of ECS operations.

## Solution
 - Replace `*Ptr(Mut)::inner` with `cast` which requires a concrete type to give the pointer. This function could also have a `debug_assert` with an alignment check to ensure that the pointer is aligned properly, but is currently not included.
 - Use `OwningPtr::read` in ECS macros over casting the inner pointer around.
2022-05-03 20:07:58 +00:00
TheRawMeatball
5ca78b1e27 Add get_change_ticks method to EntityRef and EntityMut (#2539)
Direct access to the change ticks is useful for integrating the reliable change detection with external stuff.
2022-05-02 18:44:58 +00:00
Alice Cecile
3fbe3683d9 Improve debugging tools for change detection (#4160)
# Objective

1. Previously, the `change_tick` and `last_change_tick` fields on `SystemChangeTick` [were `pub`](https://docs.rs/bevy/0.6.1/bevy/ecs/system/struct.SystemChangeTick.html).
   1.  This was actively misleading, as while this can be fetched as a `SystemParam`, a copy is returned instead
2. This information could be useful for debugging, but there was no way to investigate when data was changed.
3. There were no docs!

## Solution

1. Move these to a getter method.
2. Add `last_changed` method to the `DetectChanges` trait to enable inspection of when data was last changed.
3. Add docs.

# Changelog

 `SystemChangeTick` now provides getter methods for the current and previous change tick, rather than public fields.
 This can be combined with `DetectChanges::last_changed()` to debug the timing of changes.

# Migration guide

The `change_tick` and `last_change_tick` fields on `SystemChangeTick` are now private, use the corresponding getter method instead.
2022-05-02 18:26:52 +00:00
Alice Cecile
8283db69b4 Remind users to initialize their systems before running them (#3947)
# Objective

- Manually running systems is a somewhat obscure process: systems must be initialized before they are run
- The unwrap is rather hard to debug.

## Solution

- Replace unwraps in `FunctionSystem` methods with expects (progress towards #3892).
- Briefly document this requirement.
2022-05-02 16:04:49 +00:00
Boxy
b9102b8836 Introduce tests for derive(WorldQuery) (#4625)
The only tests we had for `derive(WorldQuery)` checked that the derive doesnt panic/emit a `compiler_error!`. This PR adds tests that actually assert the returned values of a query using the derived `WorldQuery` impl. Also adds a compile fail test to check that we correctly error on read only world queries containing mutable world queries.
2022-04-28 21:06:20 +00:00
TheRawMeatball
73c78c3667 Use lifetimed, type erased pointers in bevy_ecs (#3001)
# Objective

`bevy_ecs` has large amounts of unsafe code which is hard to get right and makes it difficult to audit for soundness.

## Solution

Introduce lifetimed, type-erased pointers: `Ptr<'a>` `PtrMut<'a>` `OwningPtr<'a>'` and `ThinSlicePtr<'a, T>` which are newtypes around a raw pointer with a lifetime and conceptually representing strong invariants about the pointee and validity of the pointer.

The process of converting bevy_ecs to use these has already caught multiple cases of unsound behavior.

## Changelog

TL;DR for release notes: `bevy_ecs` now uses lifetimed, type-erased pointers internally, significantly improving safety and legibility without sacrificing performance. This should have approximately no end user impact, unless you were meddling with the (unfortunately public) internals of `bevy_ecs`.

- `Fetch`, `FilterFetch` and `ReadOnlyFetch` trait no longer have a `'state` lifetime
    - this was unneeded
- `ReadOnly/Fetch` associated types on `WorldQuery` are now on a new `WorldQueryGats<'world>` trait
    - was required to work around lack of Generic Associated Types (we wish to express `type Fetch<'a>: Fetch<'a>`)
- `derive(WorldQuery)` no longer requires `'w` lifetime on struct
    - this was unneeded, and improves the end user experience
- `EntityMut::get_unchecked_mut` returns `&'_ mut T` not `&'w mut T`
    - allows easier use of unsafe API with less footguns, and can be worked around via lifetime transmutery as a user
- `Bundle::from_components` now takes a `ctx` parameter to pass to the `FnMut` closure
    - required because closure return types can't borrow from captures
- `Fetch::init` takes `&'world World`, `Fetch::set_archetype` takes `&'world Archetype` and `&'world Tables`, `Fetch::set_table` takes `&'world Table`
    - allows types implementing `Fetch` to store borrows into world
- `WorldQuery` trait now has a `shrink` fn to shorten the lifetime in `Fetch::<'a>::Item`
    - this works around lack of subtyping of assoc types, rust doesnt allow you to turn `<T as Fetch<'static>>::Item'` into `<T as Fetch<'a>>::Item'`
    - `QueryCombinationsIter` requires this
- Most types implementing `Fetch` now have a lifetime `'w`
    - allows the fetches to store borrows of world data instead of using raw pointers

## Migration guide

- `EntityMut::get_unchecked_mut` returns a more restricted lifetime, there is no general way to migrate this as it depends on your code
- `Bundle::from_components` implementations must pass the `ctx` arg to `func`
- `Bundle::from_components` callers have to use a fn arg instead of closure captures for borrowing from world
- Remove lifetime args on `derive(WorldQuery)` structs as it is nonsensical
- `<Q as WorldQuery>::ReadOnly/Fetch` should be changed to either `RO/QueryFetch<'world>` or `<Q as WorldQueryGats<'world>>::ReadOnly/Fetch`
- `<F as Fetch<'w, 's>>` should be changed to `<F as Fetch<'w>>`
- Change the fn sigs of `Fetch::init/set_archetype/set_table` to match respective trait fn sigs
- Implement the required `fn shrink` on any `WorldQuery` implementations
- Move assoc types `Fetch` and `ReadOnlyFetch` on `WorldQuery` impls to `WorldQueryGats` impls
- Pass an appropriate `'world` lifetime to whatever fetch struct you are for some reason using

### Type inference regression

in some cases rustc may give spurrious errors when attempting to infer the `F` parameter on a query/querystate this can be fixed by manually specifying the type, i.e. `QueryState:🆕:<_, ()>(world)`. The error is rather confusing:

```rust=
error[E0271]: type mismatch resolving `<() as Fetch<'_>>::Item == bool`
    --> crates/bevy_pbr/src/render/light.rs:1413:30
     |
1413 |             main_view_query: QueryState::new(world),
     |                              ^^^^^^^^^^^^^^^ expected `bool`, found `()`
     |
     = note: required because of the requirements on the impl of `for<'x> FilterFetch<'x>` for `<() as WorldQueryGats<'x>>::Fetch`
note: required by a bound in `bevy_ecs::query::QueryState::<Q, F>::new`
    --> crates/bevy_ecs/src/query/state.rs:49:32
     |
49   |     for<'x> QueryFetch<'x, F>: FilterFetch<'x>,
     |                                ^^^^^^^^^^^^^^^ required by this bound in `bevy_ecs::query::QueryState::<Q, F>::new`
```

---

Made with help from @BoxyUwU and @alice-i-cecile 

Co-authored-by: Boxy <supbscripter@gmail.com>
2022-04-27 23:44:06 +00:00
bjorn3
ddce22b614 Decouple some dependencies (#3886)
# Objective

Reduce from scratch build time.

## Solution

Reduce the size of the critical path by removing dependencies between crates where not necessary. For `cargo check --no-default-features` this reduced build time from ~51s to ~45s. For some commits I am not completely sure if the tradeoff between build time reduction and convenience caused by the commit is acceptable. If not, I can drop them.
2022-04-27 19:08:11 +00:00
Nicola Papale
71a246ce9e Improve QueryIter size_hint hints (#4244)
## Objective

This fixes #1686.

`size_hint` can be useful even if a little niche. For example,
`collect::<Vec<_>>()` uses the `size_hint` of Iterator it collects from
to pre-allocate a memory slice large enough to not require re-allocating
when pushing all the elements of the iterator.

## Solution

To this effect I made the following changes:
* Add a `IS_ARCHETYPAL` associated constant to the `Fetch` trait,
  this constant tells us when it is safe to assume that the `Fetch`
  relies exclusively on archetypes to filter queried entities
* Add `IS_ARCHETYPAL` to all the implementations of `Fetch`
* Use that constant in `QueryIter::size_hint` to provide a more useful

## Migration guide

The new associated constant is an API breaking change. For the user,
if they implemented a custom `Fetch`, it means they have to add this
associated constant to their implementation. Either `true` if it doesn't limit
the number of entities returned in a query beyond that of archetypes, or
`false` for when it does.
2022-04-27 18:02:06 +00:00
Aevyrie
4aa56050b6 Add infallible resource getters for WorldCell (#4104)
# Objective

- Eliminate all `worldcell.get_resource().unwrap()` cases.
- Provide helpful messages on panic.

## Solution

- Adds infallible resource getters to `WorldCell`, mirroring `World`.
2022-04-25 23:19:13 +00:00
Alice Cecile
4bcb310008 Basic EntityRef and EntityMut docs (#3388)
# Objective

- `EntityRef` and `EntityMut` are surpisingly important public types when working directly with the `World`.
- They're undocumented.

## Solution

- Just add docs!
2022-04-25 14:32:57 +00:00
SpecificProtagonist
46acb7753c SystemSet::before and after: take AsSystemLabel (#4503)
# Objective

`AsSystemLabel` has been introduced on system descriptors to make ordering systems more convenient, but `SystemSet::before` and `SystemSet::after` still take `SystemLabels` directly:

    use bevy::ecs::system::AsSystemLabel;
    /*…*/ SystemSet::new().before(foo.as_system_label()) /*…*/

is currently necessary instead of

    /*…*/ SystemSet::new().before(foo) /*…*/

## Solution

Use `AsSystemLabel` for `SystemSet`
2022-04-23 06:03:50 +00:00
TheRawMeatball
0fdb45ce90 Remove EntityMut::get_unchecked (#4547)
The only way to soundly use this API is already encapsulated within `EntityMut::get`, so this api is removed.

# Migration guide

Replace calls to `EntityMut::get_unchecked` with calls to `EntityMut::get`.
2022-04-22 20:06:41 +00:00
François
18c6a7b40e do not impl Component for Task (#4113)
# Objective

- `Task` are `Component`.
- They should not.

## Solution

- Remove the impl, and update the example to show a wrapper.

#4052 for reference
2022-04-22 06:29:38 +00:00
bjorn3
e65f28d8d7 Remove parking_lot dependency from bevy_ecs (#4543)
It is only used in some tests so any potential performance regressions don't matter.
2022-04-20 11:26:38 +00:00
Charles
afbce46ade improve Commands doc comment (#4490)
# Objective

- The current API docs of `Commands` is very short and is very opaque to newcomers.

## Solution

- Try to explain what it is without requiring knowledge of other parts of `bevy_ecs` like `World` or `SystemParam`.


Co-authored-by: Charles <IceSentry@users.noreply.github.com>
2022-04-17 18:17:49 +00:00
Daniel McNab
639fec20d6 Remove .system() (#4499)
Free at last!

# Objective

- Using `.system()` is no longer needed anywhere, and anyone using it will have already gotten a deprecation warning.
- https://github.com/bevyengine/bevy/pull/3302 was a super special case for `.system()`, since it was so prevelant. However, that's no reason.
- Despite it being deprecated, another couple of uses of it have already landed, including in the deprecating PR.
   - These have all been because of doc examples having warnings not breaking CI - 🎟️?

## Solution

- Remove it.
- It's gone

---

## Changelog

- You can no longer use `.system()`

## Migration Guide

- You can no longer use `.system()`. It was deprecated in 0.7.0, and you should have followed the deprecation warning then. You can just remove the method call.

![image](https://user-images.githubusercontent.com/36049421/163688197-3e774a04-6f8f-40a6-b7a4-1330e0b7acf0.png)

- Thanks to the @TheRawMeatball  for producing
2022-04-16 21:33:51 +00:00
François
8630b194dc add more logs when despawning entities (#3851)
# Objective

- Provide more information when despawning an entity

## Solution

- Add a debug log when despawning an entity
- Add spans to the recursive ways of despawning an entity

```sh
RUST_LOG=debug cargo run --example panic --features trace
# RUST_LOG=debug needed to show debug logs from bevy_ecs
# --features trace needed to have the extra spans
...

DEBUG bevy_app:frame:stage{name=Update}:system_commands{name="panic::despawn_parent"}:command{name="DespawnRecursive" entity=0v0}: bevy_ecs::world: Despawning entity 1v0
DEBUG bevy_app:frame:stage{name=Update}:system_commands{name="panic::despawn_parent"}:command{name="DespawnRecursive" entity=0v0}: bevy_ecs::world: Despawning entity 0v0
```
2022-04-13 23:35:28 +00:00
Carter Anderson
8783fae7de Use "many" instead of "multiple" consistently (#4463)
We missed a couple of these renames in #4384
2022-04-13 00:35:47 +00:00
harudagondi
64d217823d Allow iter combinations on queries with filters (#3656)
# Objective

- Previously, `iter_combinations()` does not work on queries that have filters.
- Fixes #3651

## Solution

- Derived Copy on all `*Fetch<T>` structs, and manually implemented `Clone` to allow the test to pass (`.count()` does not work on `QueryCombinationIter` when `Clone` is derived)


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-04-08 00:21:24 +00:00
Torne Wuff
b1afe2dcca Make System responsible for updating its own archetypes (#4115)
# Objective

- Make it possible to use `System`s outside of the scheduler/executor without having to define logic to track new archetypes and call `System::add_archetype()` for each.

## Solution

- Replace `System::add_archetype(&Archetype)` with `System::update_archetypes(&World)`, making systems responsible for tracking their own most recent archetype generation the way that `SystemState` already does.

This has minimal (or simplifying) effect on most of the code with the exception of `FunctionSystem`, which must now track the latest `ArchetypeGeneration` it saw instead of relying on the executor to do it.

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-04-07 20:50:43 +00:00
Daniel McNab
21a875d67b Some small changes related to run criteria piping (#3923)
Remove the 'chaining' api, as it's peculiar

~~Implement the label traits for `Box<dyn ThatTrait>` (n.b. I'm not confident about this change, but it was the quickest path to not regressing)~~

Remove the need for '`.system`' when using run criteria piping
2022-04-07 19:08:08 +00:00
TheRawMeatball
73edb11db6 Add more FromWorld implementations (#3945)
# Objective

Make `FromWorld` more useful for abstractions with a form similar to
```rs
trait FancyAbstraction {
  type PreInitializedData: FromWorld;
}
```

## Solution

Add a `FromWorld` implementation for `SystemState` as well as a way to group together multiple `FromWorld` implementing types as one.

Note: I plan to follow up this PR with another to add `Local` support to exclusive systems, which should get a fair amount of use from the `FromWorld` implementation on `SystemState`.
2022-04-05 20:04:34 +00:00
Boxy
dba7790012 REMOVE unsound lifetime annotations on EntityMut (#4096)
Fixes #3408
#3001 also solves this but I dont see it getting merged any time soon so...
# Objective
make bevy ecs a lil bit less unsound

## Solution
make `EntityMut::get_component_mut` return borrows from self instead of `'w`
2022-04-04 21:33:33 +00:00
Alice Cecile
b33dae31ec Rename get_multiple APIs to get_many (#4384)
# Objective

-  std's new APIs do the same thing as `Query::get_multiple_mut`, but are called `get_many`: https://github.com/rust-lang/rust/pull/83608

## Solution

- Find and replace `get_multiple` with `get_many`
2022-03-31 20:59:26 +00:00
Daniel McNab
aca7fc1854 Remove outdated perf comments (#4374)
# Objective

- The perf comments, added (by me) in https://github.com/bevyengine/bevy/pull/1349, became outdated once the initialisation call started to take an exclusive reference, (presumably in https://github.com/bevyengine/bevy/pull/1525).
- They have been naïvely transferred along ever since

## Solution

- Remove them
2022-03-31 20:43:00 +00:00
SecretPocketCat
3af90b67a6 Update RemovedComponents doc comment (#4373)
# Objective

- Clarify `RemovedComponents` are flushed in `CoreStage::Last` and systems relying on that should run before that stage

## Solution

- Update `RemovedComponents` doc comment
2022-03-31 20:24:32 +00:00
Boxy
637a149910 unsafeify World::entities_mut (#4093)
# Objective
make bevy ecs a lil bit less unsound

## Solution
make unsound API unsafe so that there is an unsafe block to blame:

```rust
use bevy_ecs::prelude::*;

#[derive(Debug, Component)]
struct Foo(u8);

fn main() {
    let mut world = World::new();
    let e1 = world.spawn().id();
    let e2 = world.spawn().insert(Foo(2)).id();
    world.entities_mut().meta[0] = world.entities_mut().meta[1].clone();
    let foo = world.entity(e1).get::<Foo>().unwrap();
    // whoo i love having components i dont have
    dbg!(foo);
}
```

This is not _strictly_ speaking UB, however: 
- `Query::get_multiple` cannot work if this is allowed
- bevy_ecs is a pile of unsafe code whose soundness generally depends on the world being in a "correct" state with "no funny business" so it seems best to disallow this
- it is trivial to get bevy to panic inside of functions with safety invariants that have been violated (the entity location is not valid)
- it seems to violate what the safety invariant on `Entities::flush` is trying to ensure
2022-03-30 23:52:45 +00:00
Alice Cecile
509548190b Add get_multiple and get_multiple_mut APIs for Query and QueryState (#4298)
# Objective

- The inability to have multiple active mutable borrows into a query is a common source of borrow-checker pain for users.
- This is a pointless restriction if and only if we can guarantee that the entities they are accessing are unique.
- This could already by bypassed with get_unchecked, but that is an extremely unsafe API.
- Closes https://github.com/bevyengine/bevy/issues/2042.

## Solution

- Add `get_multiple`, `get_multiple_mut` and their unchecked equivalents (`multiple` and `multiple_mut`) to `Query` and `QueryState`.
- Improve the `QueryEntityError` type to provide more useful error information.

## Changelog

- Added `get_multiple`, `get_multiple_mut` and their unchecked equivalents (`multiple` and `multiple_mut`) to Query and QueryState.

## Migration Guide

- The `QueryEntityError` enum now has a `AliasedMutability variant, and returns the offending entity.

## Context

This is a fresh attempt at #3333; rebasing was behaving very badly and it was important to rebase on top of the recent query soundness fixes. Many thanks to all the reviewers in that thread, especially @BoxyUwU for the help with lifetimes.

## To-do

- [x] Add compile fail tests
- [x] Successfully deduplicate code
- [x] Decide what to do about failing doc tests
- [x] Get some reviews for lifetime soundness
2022-03-30 19:16:48 +00:00
bilsen
63fee2572b ParamSet for conflicting SystemParam:s (#2765)
# Objective
Add a system parameter `ParamSet` to be used as container for conflicting parameters.

## Solution
Added two methods to the SystemParamState trait, which gives the access used by the parameter. Did the implementation. Added some convenience methods to FilteredAccessSet. Changed `get_conflicts` to return every conflicting component instead of breaking on the first conflicting `FilteredAccess`.


Co-authored-by: bilsen <40690317+bilsen@users.noreply.github.com>
2022-03-29 23:39:38 +00:00
Boxy
28ba87e6c8 CI runs cargo miri test -p bevy_ecs (#4310)
# Objective

Fixes #1529
Run bevy_ecs in miri

## Solution

- Don't set thread names when running in miri rust-lang/miri/issues/1717
- Update `event-listener` to `2.5.2` as previous versions have UB that is detected by miri: [event-listener commit](1fa31c553e)
- Ignore memory leaks when running in miri as they are impossible to track down rust-lang/miri/issues/1481
- Make `table_add_remove_many` test less "many" because miri is really quite slow :)
- Make CI run `RUSTFLAGS="-Zrandomize-layout" MIRIFLAGS="-Zmiri-ignore-leaks -Zmiri-tag-raw-pointers -Zmiri-disable-isolation" cargo +nightly miri test -p bevy_ecs`
2022-03-25 00:26:07 +00:00
Carter Anderson
b1c3e9862d Auto-label function systems with SystemTypeIdLabel (#4224)
This adds the concept of "default labels" for systems (currently scoped to "parallel systems", but this could just as easily be implemented for "exclusive systems"). Function systems now include their function's `SystemTypeIdLabel` by default.

This enables the following patterns:

```rust
// ordering two systems without manually defining labels
app
  .add_system(update_velocity)
  .add_system(movement.after(update_velocity))

// ordering sets of systems without manually defining labels
app
  .add_system(foo)
  .add_system_set(
    SystemSet::new()
      .after(foo)
      .with_system(bar)
      .with_system(baz)
  )
```

Fixes: #4219
Related to: #4220 

Credit to @aevyrie @alice-i-cecile @DJMcNab (and probably others) for proposing (and supporting) this idea about a year ago. I was a big dummy that both shut down this (very good) idea and then forgot I did that. Sorry. You all were right!
2022-03-23 22:53:56 +00:00
Boxy
024d98457c yeet unsound lifetime annotations on Query methods (#4243)
# 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>
2022-03-22 02:49:41 +00:00
Boxy
050d2b7f00 yeet World::components_mut >:( (#4092)
# Objective
make bevy ecs a lil bit less unsound
## Solution
yeet unsound API `World::components_mut`:
```rust
use bevy_ecs::prelude::*;

#[derive(Component)]
struct Foo(u8);

#[derive(Debug, Component)]
struct Bar([u8; 100]);

fn main() {
    let mut world = World::new();
    let e = world.spawn().insert(Foo(0)).id();
    *world.components_mut() = Default::default();
    let bar = world.entity_mut(e).remove::<Bar>().unwrap();
    // oopsies reading memory copied from outside allocation
    dbg!(bar);
}
```
2022-03-21 23:43:08 +00:00
James Liu
4c1678c78d Hide docs for concrete impls of Fetch, FetchState, and SystemParamState (#4250)
# Objective
 The following pages in the docs are rather noisy, and the types they point to are not particularly useful by themselves:

 - http://dev-docs.bevyengine.org/bevy/ecs/query/index.html
 - http://dev-docs.bevyengine.org/bevy/ecs/system/index.html

## Solution
 
- Replace docs on these types with `#[doc(hidden)]`.
- Hide `InputMarker`  too.
2022-03-21 05:23:36 +00:00
Boxy
e7a9420443 Change Cow<[ComponentId]> to Box<[ComponentId]> (#4185)
`Cow::Borrowed` was never used
2022-03-19 04:14:27 +00:00
Carter Anderson
de677dbfc9 Use more ergonomic span syntax (#4246)
Tracing added support for "inline span entering", which cuts down on a lot of complexity:

```rust
let span = info_span!("my_span").entered();
```

This adapts our code to use this pattern where possible, and updates our docs to recommend it.

This produces equivalent tracing behavior. Here is a side by side profile of "before" and "after" these changes.
![image](https://user-images.githubusercontent.com/2694663/158912137-b0aa6dc8-c603-425f-880f-6ccf5ad1b7ef.png)
2022-03-18 04:19:21 +00:00
Daniel McNab
6e61fef67d Obviate the need for RunSystem, and remove it (#3817)
# Objective

- Fixes #3300
- `RunSystem` is messy

## Solution

- Adds the trick theorised in https://github.com/bevyengine/bevy/issues/3300#issuecomment-991791234

P.S. I also want this for an experimental refactoring of `Assets`, to remove the duplication of `Events<AssetEvent<T>>`


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-03-15 02:16:55 +00:00
Harry Barber
cf46baa172 Add clear_schedule (#3941)
# Objective

Adds `clear_schedule` method to `State`.

Closes #3932
2022-03-05 21:53:17 +00:00
Alice Cecile
557ab9897a Make get_resource (and friends) infallible (#4047)
# Objective

- In the large majority of cases, users were calling `.unwrap()` immediately after `.get_resource`.
- Attempting to add more helpful error messages here resulted in endless manual boilerplate (see #3899 and the linked PRs).

## Solution

- Add an infallible variant named `.resource` and so on.
- Use these infallible variants over `.get_resource().unwrap()` across the code base.

## Notes

I did not provide equivalent methods on `WorldCell`, in favor of removing it entirely in #3939.

## Migration Guide

Infallible variants of `.get_resource` have been added that implicitly panic, rather than needing to be unwrapped.

Replace `world.get_resource::<Foo>().unwrap()` with `world.resource::<Foo>()`.

## Impact

- `.unwrap` search results before: 1084
- `.unwrap` search results after: 942
- internal `unwrap_or_else` calls added: 4
- trivial unwrap calls removed from tests and code: 146
- uses of the new `try_get_resource` API: 11
- percentage of the time the unwrapping API was used internally: 93%
2022-02-27 22:37:18 +00:00
Jupp56
b697e73c3d Enhanced par_for_each and par_for_each_mut docs (#4039)
# Objective
Continuation of  #2663 due to git problems - better documentation for Query::par_for_each and par_for_each_mut

## Solution
Going into more detail about the function parameters
2022-02-25 23:57:01 +00:00
Daniel McNab
c1a4a2f6c5 Remove the config api (#3633)
# Objective

- Fix the ugliness of the `config` api. 
- Supercedes #2440, #2463, #2491

## Solution

- Since #2398, capturing closure systems have worked.
- Use those instead where we needed config before
- Remove the rest of the config api. 
- Related: #2777
2022-02-25 03:10:59 +00:00
Vladyslav Batyrenko
ba6b74ba20 Implement WorldQuery derive macro (#2713)
# Objective

- Closes #786
- Closes #2252
- Closes #2588

This PR implements a derive macro that allows users to define their queries as structs with named fields.

## Example

```rust
#[derive(WorldQuery)]
#[world_query(derive(Debug))]
struct NumQuery<'w, T: Component, P: Component> {
    entity: Entity,
    u: UNumQuery<'w>,
    generic: GenericQuery<'w, T, P>,
}

#[derive(WorldQuery)]
#[world_query(derive(Debug))]
struct UNumQuery<'w> {
    u_16: &'w u16,
    u_32_opt: Option<&'w u32>,
}

#[derive(WorldQuery)]
#[world_query(derive(Debug))]
struct GenericQuery<'w, T: Component, P: Component> {
    generic: (&'w T, &'w P),
}

#[derive(WorldQuery)]
#[world_query(filter)]
struct NumQueryFilter<T: Component, P: Component> {
    _u_16: With<u16>,
    _u_32: With<u32>,
    _or: Or<(With<i16>, Changed<u16>, Added<u32>)>,
    _generic_tuple: (With<T>, With<P>),
    _without: Without<Option<u16>>,
    _tp: PhantomData<(T, P)>,
}

fn print_nums_readonly(query: Query<NumQuery<u64, i64>, NumQueryFilter<u64, i64>>) {
    for num in query.iter() {
        println!("{:#?}", num);
    }
}

#[derive(WorldQuery)]
#[world_query(mutable, derive(Debug))]
struct MutNumQuery<'w, T: Component, P: Component> {
    i_16: &'w mut i16,
    i_32_opt: Option<&'w mut i32>,
}

fn print_nums(mut query: Query<MutNumQuery, NumQueryFilter<u64, i64>>) {
    for num in query.iter_mut() {
        println!("{:#?}", num);
    }
}
```

## TODOs:
- [x] Add support for `&T` and `&mut T`
  - [x] Test
- [x] Add support for optional types
  - [x] Test
- [x] Add support for `Entity`
  - [x] Test
- [x] Add support for nested `WorldQuery`
  - [x] Test
- [x] Add support for tuples
  - [x] Test
- [x] Add support for generics
  - [x] Test
- [x] Add support for query filters
  - [x] Test
- [x] Add support for `PhantomData`
  - [x] Test
- [x] Refactor `read_world_query_field_type_info`
- [x] Properly document `readonly` attribute for nested queries and the static assertions that guarantee safety
  - [x] Test that we never implement `ReadOnlyFetch` for types that need mutable access
  - [x] Test that we insert static assertions for nested `WorldQuery` that a user marked as readonly
2022-02-24 00:19:49 +00:00
Carter Anderson
b3a1db60f2 Proper prehashing (#3963)
For some keys, it is too expensive to hash them on every lookup. Historically in Bevy, we have regrettably done the "wrong" thing in these cases (pre-computing hashes, then re-hashing them) because Rust's built in hashed collections don't give us the tools we need to do otherwise. Doing this is "wrong" because two different values can result in the same hash. Hashed collections generally get around this by falling back to equality checks on hash collisions. You can't do that if the key _is_ the hash. Additionally, re-hashing a hash increase the odds of collision!
 
#3959 needs pre-hashing to be viable, so I decided to finally properly solve the problem. The solution involves two different changes:

1. A new generalized "pre-hashing" solution in bevy_utils: `Hashed<T>` types, which store a value alongside a pre-computed hash. And `PreHashMap<K, V>` (which uses `Hashed<T>` internally) . `PreHashMap` is just an alias for a normal HashMap that uses `Hashed<T>` as the key and a new `PassHash` implementation as the Hasher. 
2. Replacing the `std::collections` re-exports in `bevy_utils` with equivalent `hashbrown` impls. Avoiding re-hashes requires the `raw_entry_mut` api, which isn't stabilized yet (and may never be ... `entry_ref` has favor now, but also isn't available yet). If std's HashMap ever provides the tools we need, we can move back to that. The latest version of `hashbrown` adds support for the `entity_ref` api, so we can move to that in preparation for an std migration, if thats the direction they seem to be going in. Note that adding hashbrown doesn't increase our dependency count because it was already in our tree.

In addition to providing these core tools, I also ported the "table identity hashing" in `bevy_ecs` to `raw_entry_mut`, which was a particularly egregious case.

The biggest outstanding case is `AssetPathId`, which stores a pre-hash. We need AssetPathId to be cheaply clone-able (and ideally Copy), but `Hashed<AssetPath>` requires ownership of the AssetPath, which makes cloning ids way more expensive. We could consider doing `Hashed<Arc<AssetPath>>`, but cloning an arc is still a non-trivial expensive that needs to be considered. I would like to handle this in a separate PR. And given that we will be re-evaluating the Bevy Assets implementation in the very near future, I'd prefer to hold off until after that conversation is concluded.
2022-02-18 03:26:01 +00:00
Alice Cecile
330160cf14 SystemState usage docs (#3783)
# Objective

- `SystemStates` rock for dealing with exclusive world access, but are hard to figure out how to use.
- Fixes #3341.

## Solution

- Clearly document how to use `SystemState`, and why they're useful as an end-user.
2022-02-15 21:53:52 +00:00
danieleades
d8974e7c3d small and mostly pointless refactoring (#2934)
What is says on the tin.

This has got more to do with making `clippy` slightly more *quiet* than it does with changing anything that might greatly impact readability or performance.

that said, deriving `Default` for a couple of structs is a nice easy win
2022-02-13 22:33:55 +00:00
Alice Cecile
bdbf626341 Implement init_resource for Commands and World (#3079)
# Objective

- Fixes #3078
- Fixes #1397

## Solution

- Implement Commands::init_resource.
- Also implement for World, for consistency and to simplify internal structure.
- While we're here, clean up some of the docs for Command and World resource modification.
2022-02-08 23:04:19 +00:00
Daniel McNab
6615b7bf64 Deprecate .system (#3302)
# Objective

- Using `.system()` is no longer idiomatic.

## Solution

- Give a warning when using it
2022-02-08 04:00:58 +00:00
Gingeh
2f11c9dca8 Add Query::contains (#3090)
# Objective

- Fixes #3089
2022-02-08 03:37:34 +00:00
François
1468211e2b fix unreachable macro calls for rust 2021 (#3889)
# Objective

- It was decided in Rust 2021 to make macro like `panic` require a string literal to format instead of directly an object
- `unreachable` was missed during the first pass but it was decided to go for it anyway now: https://github.com/rust-lang/rust/issues/92137#issuecomment-1019519285
- this is making Bevy CI fail now: https://github.com/bevyengine/bevy/runs/5102586734?check_suite_focus=true

## Solution

- Fix calls to `unreachable`
2022-02-08 02:59:54 +00:00
Delphine
b13f238fc7 allow Entity to be deserialized with serde_json (#3873)
# Objective

- `serde_json` assumes that numbers being deserialized are either u64 or i64.
- `Entity` serializes and deserializes as a u32.
- Deserializing an `Entity` with `serde_json` fails with: `Error("invalid type: integer 10947, expected expected Entity"`

## Solution

- Implemented a visitor for u64 that allows an `Entity` to be deserialized in this case.
- While I was here, also fixed the redundant "expected expected Entity" in the error message
- Tested the change in a local project which now correctly deserializes `Entity` structs with `serde_json` when it couldn't before
2022-02-06 04:16:16 +00:00
TheRawMeatball
7604665880 Implement AnyOf queries (#2889)
Implements a new Queryable called AnyOf, which will return an item as long as at least one of it's requested Queryables returns something. For example, a `Query<AnyOf<(&A, &B, &C)>>` will return items with type `(Option<&A>, Option<&B>, Option<&C>)`, and will guarantee that for every element at least one of the option s is Some. This is a shorthand for queries like `Query<(Option<&A>, Option<&B>, Option<&C>), Or<(With<A>, With<B>, With&C>)>>`.


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-02-06 00:52:47 +00:00
Jakob Hellermann
3431335ee9 add missing into_inner to ReflectMut (#3841)
`Mut<T>`, `ResMut<T>` etc. have `.into_inner()` methods, but `ReflectMut` doesn't for some reason.
2022-02-04 03:37:45 +00:00
TheRawMeatball
142e7f3c50 Backport soundness fix (#3685)
#3001 discovered a soundness bug in World::resource_scope, this PR backports the fix with a smaller PR to patch out the bug sooner.

Fixes #3147
2022-02-04 03:21:31 +00:00
Daniel Bearden
fe4a42a648 Mut to immut impls (#3621)
# Objective
- Provide impls for mutable types to relevant immutable types. 
- Closes #2005 

## Solution

- impl From<ResMut> for Res
- impl From<NonSendMut> for NonSend
- Mut to &/&mut already impl'd in change_detection_impl! macro
2022-02-04 03:07:21 +00:00
MrGVSV
f00aec2454 Added method to restart the current state (#3328)
# Objective

It would be useful to be able to restart a state (such as if an operation fails and needs to be retried from `on_enter`). Currently, it seems the way to restart a state is to transition to a dummy state and then transition back.

## Solution

The solution is to add a `restart` method on `State<T>` that allows for transitioning to the already-active state.

## Context

Based on [this](https://discord.com/channels/691052431525675048/742884593551802431/920335041756815441) question from the Discord.

Closes #2385


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-02-04 03:07:18 +00:00
Charles
7d712406fe Simplify sending empty events (#2935)
# Objective

When using empty events, it can feel redundant to have to specify the type of the event when sending it.

## Solution

Add a new `fire()` function that sends the default value of the event. This requires that the event derives Default.


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-02-04 01:24:47 +00:00
bilsen
1f99363de9 Add &World as SystemParam (#2923)
# Objective
Make it possible to use `&World` as a system parameter

## Solution
It seems like all the pieces were already in place, very simple impl


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-02-03 23:43:25 +00:00
Garett Cooper
c216738b33 Implement len and is_empty for EventReaders (#2969)
# Objective

Provide a non-consuming method of checking if there are events in an `EventReader`.

Fixes #2967

## Solution

Implements the `len` and `is_empty` functions for `EventReader` and `ManualEventReader`, giving users the ability to check for the presence of new events without consuming any.


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-02-03 23:22:08 +00:00
bjorn3
af22cc1dc3 Use ManuallyDrop instead of forget in insert_resource_with_id (#2947)
# Objective

Calling forget would invalidate the data pointer before it is used.

## Solution

Use `ManuallyDrop` to prevent the value from being dropped without moving it.
2022-02-03 22:34:31 +00:00
Stefan Seemayer
21ac4bc0ae impl Command for <impl FnOnce(&mut World)> (#2996)
This is my first contribution to this exciting project! Thanks so much for your wonderful work. If there is anything that I can improve about this PR, please let me know :)

# Objective

- Fixes #2899
- If a simple one-off command is needed to be added within a System, this simplifies that process so that we can simply do `commands.add(|world: &mut World| { /* code here */ })` instead of defining a custom type implementing `Command`.

## Solution

- This is achieved by `impl Command for F where F: FnOnce(&mut World) + Send + Sync + 'static` as just calling the function.

I am not sure if the bounds can be further relaxed but needed the whole `Send`, `Sync`, and `'static` to get it to compile.
2022-02-03 04:11:19 +00:00
MinerSebas
69e9a47d92 SystemParam Derive fixes (#2838)
# Objective

A user on Discord couldn't derive SystemParam for this Struct:

```rs
#[derive(SystemParam)]
pub struct SpatialQuery<'w, 's, Q: WorldQuery + Send + Sync + 'static, F: WorldQuery + Send + Sync + 'static = ()>
where
    F::Fetch: FilterFetch,
{
    query: Query<'w, 's, (C, &'static Transform), F>,
}
```

## Solution

1. The `where`-clause is now also copied to the `SystemParamFetch` impl Block.
2. The `SystemParamState` impl Block no longer gets any defaults for generics


Co-authored-by: MinerSebas <66798382+MinerSebas@users.noreply.github.com>
2022-02-03 03:32:02 +00:00
KDecay
506642744c docs: Fix private doc links and enable CI test (#3743)
# Objective

Fixes #3566

## Solution

- [x] Fix broken links in private docs.
- [x] Add the `--document-private-items` flag to the CI.

## Note

The following was said by @killercup in #3566:

> I don't have time to confirm this but I assume that linking to private items throws an error/warning when just running cargo doc, and --document-private-item might actually hide that warning. So to test this, you'd have to run it twice.

I tested this and this is thankfully not the case. If you are linking to a private item you will get a warning no matter if you run `cargo doc` or `cargo doc --document-private-items`.

### Example

I added `struct Test;` to `bevy_core/src/name.rs` and linked to it inside of a doc comment using ``[`Test`]``. After that I ran `cargo doc -p bevy_core --document-private-items` using `RUSTDOCFLAGS="-D warnings"` and got the following output (note the last sentence):

```rust
error: public documentation for `Name` links to private item `Test`
  --> crates/bevy_core/src/name.rs:11:82
   |
11 | /// Component used to identify an entity. Stores a hash for faster comparisons [`Test`]
   |                                                                                  ^^^^ this item is private
   |
   = note: `-D rustdoc::private-intra-doc-links` implied by `-D warnings`
   = note: this link resolves only because you passed `--document-private-items`, but will break without
```
2022-02-02 21:47:29 +00:00
TheRawMeatball
ce752d2522 Increment last event count on next instead of iter (#2382)
# Objective

Currently, simply calling `iter` on an event reader will mark all of it's events as read, even if the returned iterator is never used

## Solution

With this, the cursor will simply move to the last unread, but available event when iter is called, and incremented by one per `next` call.


Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-02-02 02:29:33 +00:00
Alice Cecile
f5039a476d Mark .id() methods which return an Entity as must_use (#3750)
# Objective

- Calling .id() has no purpose unless you use the Entity returned
- This is an easy source of confusion for beginners.
- This is easily missed during refactors.

## Solution

- Mark the appropriate methods as #[must_use]
2022-01-23 14:24:37 +00:00