9666a7e688
11 Commits
Author | SHA1 | Message | Date | |
---|---|---|---|---|
![]() |
9666a7e688 |
Rename bevy_platform_support to bevy_platform (#18813)
The goal of `bevy_platform_support` is to provide a set of platform agnostic APIs, alongside platform-specific functionality. This is a high traffic crate (providing things like HashMap and Instant). Especially in light of https://github.com/bevyengine/bevy/discussions/18799, it deserves a friendlier / shorter name. Given that it hasn't had a full release yet, getting this change in before Bevy 0.16 makes sense. - Rename `bevy_platform_support` to `bevy_platform`. |
||
![]() |
c9fb956058 |
use entity set collections type aliases instead of defaults (#18695)
# Objective Newest installment of the #16547 series. In #18319 we introduced `Entity` defaults to accomodate the most common use case for these types, however that resulted in the switch of the `T` and `N` generics of `UniqueEntityArray`. Swapping generics might be somewhat acceptable for `UniqueEntityArray`, it is not at all acceptable for map and set types, which we would make generic over `T: EntityEquivalent` in #18408. Leaving these defaults in place would result in a glaring inconsistency between these set collections and the others. Additionally, the current standard in the engine is for "entity" to mean `Entity`. APIs could be changed to accept `EntityEquivalent`, however that is a separate and contentious discussion. ## Solution Name these set collections `UniqueEntityEquivalent*`, and retain the `UniqueEntity*` name for an alias of the `Entity` case. While more verbose, this allows for all generics to be in proper order, full consistency between all set types*, and the "entity" name to be restricted to `Entity`. On top of that, `UniqueEntity*` now always have 1 generic less, when previously this was not enforced for the default case. *`UniqueEntityIter<I: Iterator<T: EntityEquivalent>>` is the sole exception to this. Aliases are unable to enforce bounds (`lazy_type_alias` is needed for this), so for this type, doing this split would be a mere suggestion, and in no way enforced. Iterator types are rarely ever named, and this specific one is intended to be aliased when it sees more use, like we do for the corresponding set collection iterators. Furthermore, the `EntityEquivalent` precursor `Borrow<Entity>` was used exactly because of such iterator bounds! Because of that, we leave it as is. While no migration guide for 0.15 users, for those that upgrade from main: `UniqueEntityVec<T>` -> `UniqueEntityEquivalentVec<T>` `UniqueEntitySlice<T>` -> `UniqueEntityEquivalentSlice<T>` `UniqueEntityArray<N, T>` -> `UniqueEntityEquivalentArray<T, N>` |
||
![]() |
10da4dc9ae |
Rename EntityBorrow/TrustedEntityBorrow to ContainsEntity/EntityEquivalent (#18470)
# Objective Fixes #9367. Yet another follow-up to #16547. These traits were initially based on `Borrow<Entity>` because that trait was what they were replacing, and it felt close enough in meaning. However, they ultimately don't quite match: `borrow` always returns references, whereas `EntityBorrow` always returns a plain `Entity`. Additionally, `EntityBorrow` can imply that we are borrowing an `Entity` from the ECS, which is not what it does. Due to its safety contract, `TrustedEntityBorrow` is important an important and widely used trait for `EntitySet` functionality. In contrast, the safe `EntityBorrow` does not see much use, because even outside of `EntitySet`-related functionality, it is a better idea to accept `TrustedEntityBorrow` over `EntityBorrow`. Furthermore, as #9367 points out, abstracting over returning `Entity` from pointers/structs that contain it can skip some ergonomic friction. On top of that, there are aspects of #18319 and #18408 that are relevant to naming: We've run into the issue that relying on a type default can switch generic order. This is livable in some contexts, but unacceptable in others. To remedy that, we'd need to switch to a type alias approach: The "defaulted" `Entity` case becomes a `UniqueEntity*`/`Entity*Map`/`Entity*Set` alias, and the base type receives a more general name. `TrustedEntityBorrow` does not mesh clearly with sensible base type names. ## Solution Replace any `EntityBorrow` bounds with `TrustedEntityBorrow`. + Rename them as such: `EntityBorrow` -> `ContainsEntity` `TrustedEntityBorrow` -> `EntityEquivalent` For `EntityBorrow` we produce a change in meaning; We designate it for types that aren't necessarily strict wrappers around `Entity` or some pointer to `Entity`, but rather any of the myriad of types that contain a single associated `Entity`. This pattern can already be seen in the common `entity`/`id` methods across the engine. We do not mean for `ContainsEntity` to be a trait that abstracts input API (like how `AsRef<T>` is often used, f.e.), because eliding `entity()` would be too implicit in the general case. We prefix "Contains" to match the intuition of a struct with an `Entity` field, like some contain a `length` or `capacity`. It gives the impression of structure, which avoids the implication of a relationship to the `ECS`. `HasEntity` f.e. could be interpreted as "a currently live entity", As an input trait for APIs like #9367 envisioned, `TrustedEntityBorrow` is a better fit, because it *does* restrict itself to strict wrappers and pointers. Which is why we replace any `EntityBorrow`/`ContainsEntity` bounds with `TrustedEntityBorrow`/`EntityEquivalent`. Here, the name `EntityEquivalent` is a lot closer to its actual meaning, which is "A type that is both equivalent to an `Entity`, and forms the same total order when compared". Prior art for this is the [`Equivalent`](https://docs.rs/hashbrown/latest/hashbrown/trait.Equivalent.html) trait in `hashbrown`, which utilizes both `Borrow` and `Eq` for its one blanket impl! Given that we lose the `Borrow` moniker, and `Equivalent` can carry various meanings, we expand on the safety comment of `EntityEquivalent` somewhat. That should help prevent the confusion we saw in [#18408](https://github.com/bevyengine/bevy/pull/18408#issuecomment-2742094176). The new name meshes a lot better with the type aliasing approach in #18408, by aligning with the base name `EntityEquivalentHashMap`. For a consistent scheme among all set types, we can use this scheme for the `UniqueEntity*` wrapper types as well! This allows us to undo the switched generic order that was introduced to `UniqueEntityArray` by its `Entity` default. Even without the type aliases, I think these renames are worth doing! ## Migration Guide Any use of `EntityBorrow` becomes `ContainsEntity`. Any use of `TrustedEntityBorrow` becomes `EntityEquivalent`. |
||
![]() |
8723096d57 |
reexport entity set collections in entity module (#18413)
# Objective Unlike for their helper typers, the import paths for `unique_array::UniqueEntityArray`, `unique_slice::UniqueEntitySlice`, `unique_vec::UniqueEntityVec`, `hash_set::EntityHashSet`, `hash_map::EntityHashMap`, `index_set::EntityIndexSet`, `index_map::EntityIndexMap` are quite redundant. When looking at the structure of `hashbrown`, we can also see that while both `HashSet` and `HashMap` have their own modules, the main types themselves are re-exported to the crate level. ## Solution Re-export the types in their shared `entity` parent module, and simplify the imports where they're used. |
||
![]() |
b462f47864
|
add Entity default to the entity set wrappers (#18319)
# Objective Installment of the #16547 series. The vast majority of uses for these types will be the `Entity` case, so it makes sense for it to be the default. ## Solution `UniqueEntityVec`, `UniqueEntitySlice`, `UniqueEntityArray` and their helper iterator aliases now have `Entity` as a default. Unfortunately, this means the the `T` parameter for `UniqueEntityArray` now has to be ordered after the `N` constant, which breaks the consistency to `[T; N]`. Same with about a dozen iterator aliases that take some `P`/`F` predicate/function parameter. This should however be an ergonomic improvement in most cases, so we'll just have to live with this inconsistency. ## Migration Guide Switch type parameter order for the relevant wrapper types/aliases. |
||
![]() |
32d53e7bd3
|
make various entity wrapper type modules public (#18248)
# Objective Part of the #16547 series. The entity wrapper types often have some associated types an aliases with them that cannot be re-exported into an outer module together. Some helper types are best used with part of their path: `bevy::ecs::entity::index_set::Slice` as `index_set::Slice`. This has already been done for `entity::hash_set` and `entity::hash_map`. ## Solution Publicize the `index_set`, `index_map`, `unique_vec`, `unique_slice`, and `unique_array` modules. ## Migration Guide Any mention or import of types in the affected modules have to add the respective module name to the import path. F.e.: `bevy::ecs::entity::EntityIndexSet` -> `bevy::ecs::entity::index_set::EntityIndexSet` |
||
![]() |
cc69fdd0c6
|
Add no_std support to bevy (#17955)
# Objective - Fixes #15460 (will open new issues for further `no_std` efforts) - Supersedes #17715 ## Solution - Threaded in new features as required - Made certain crates optional but default enabled - Removed `compile-check-no-std` from internal `ci` tool since GitHub CI can now simply check `bevy` itself now - Added CI task to check `bevy` on `thumbv6m-none-eabi` to ensure `portable-atomic` support is still valid [^1] [^1]: This may be controversial, since it could be interpreted as implying Bevy will maintain support for `thumbv6m-none-eabi` going forward. In reality, just like `x86_64-unknown-none`, this is a [canary](https://en.wiktionary.org/wiki/canary_in_a_coal_mine) target to make it clear when `portable-atomic` no longer works as intended (fixing atomic support on atomically challenged platforms). If a PR comes through and makes supporting this class of platforms impossible, then this CI task can be removed. I however wager this won't be a problem. ## Testing - CI --- ## Release Notes Bevy now has support for `no_std` directly from the `bevy` crate. Users can disable default features and enable a new `default_no_std` feature instead, allowing `bevy` to be used in `no_std` applications and libraries. ```toml # Bevy for `no_std` platforms bevy = { version = "0.16", default-features = false, features = ["default_no_std"] } ``` `default_no_std` enables certain required features, such as `libm` and `critical-section`, and as many optional crates as possible (currently just `bevy_state`). For atomically-challenged platforms such as the Raspberry Pi Pico, `portable-atomic` will be used automatically. For library authors, we recommend depending on `bevy` with `default-features = false` to allow `std` and `no_std` users to both depend on your crate. Here are some recommended features a library crate may want to expose: ```toml [features] # Most users will be on a platform which has `std` and can use the more-powerful `async_executor`. default = ["std", "async_executor"] # Features for typical platforms. std = ["bevy/std"] async_executor = ["bevy/async_executor"] # Features for `no_std` platforms. libm = ["bevy/libm"] critical-section = ["bevy/critical-section"] [dependencies] # We disable default features to ensure we don't accidentally enable `std` on `no_std` targets, for example. bevy = { version = "0.16", default-features = false } ``` While this is verbose, it gives the maximum control to end-users to decide how they wish to use Bevy on their platform. We encourage library authors to experiment with `no_std` support. For libraries relying exclusively on `bevy` and no other dependencies, it may be as simple as adding `#![no_std]` to your `lib.rs` and exposing features as above! Bevy can also provide many `std` types, such as `HashMap`, `Mutex`, and `Instant` on all platforms. See `bevy::platform_support` for details on what's available out of the box! ## Migration Guide - If you were previously relying on `bevy` with default features disabled, you may need to enable the `std` and `async_executor` features. - `bevy_reflect` has had its `bevy` feature removed. If you were relying on this feature, simply enable `smallvec` and `smol_str` instead. --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> |
||
![]() |
a1717331e4
|
implement UniqueEntityArray (#17954)
# Objective Continuation of #17589 and #16547. `get_many` is last of the `many` methods with a missing `unique` counterpart. It both takes and returns arrays, thus necessitates a matching `UniqueEntityArray` type! Plus, some slice methods involve returning arrays, which are currently missing from `UniqueEntitySlice`. ## Solution Add the type, the related methods and trait impls. Note that for this PR, we abstain from some methods/trait impls that create `&mut UniqueEntityArray`, because it can be successfully mem-swapped. This can potentially invalidate a larger slice, which is the same reason we punted on some mutable slice methods in #17589. We can follow-up on all of these together in a following PR. The new `unique_array` module is not glob-exported, because the trait alias `unique_array::IntoIter` would conflict with `unique_vec::IntoIter`. The solution for this is to make the various `unique_*` modules public, which I intend to do in yet another PR. |
||
![]() |
5241e09671
|
Upgrade to Rust Edition 2024 (#17967)
# Objective - Fixes #17960 ## Solution - Followed the [edition upgrade guide](https://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html) ## Testing - CI --- ## Summary of Changes ### Documentation Indentation When using lists in documentation, proper indentation is now linted for. This means subsequent lines within the same list item must start at the same indentation level as the item. ```rust /* Valid */ /// - Item 1 /// Run-on sentence. /// - Item 2 struct Foo; /* Invalid */ /// - Item 1 /// Run-on sentence. /// - Item 2 struct Foo; ``` ### Implicit `!` to `()` Conversion `!` (the never return type, returned by `panic!`, etc.) no longer implicitly converts to `()`. This is particularly painful for systems with `todo!` or `panic!` statements, as they will no longer be functions returning `()` (or `Result<()>`), making them invalid systems for functions like `add_systems`. The ideal fix would be to accept functions returning `!` (or rather, _not_ returning), but this is blocked on the [stabilisation of the `!` type itself](https://doc.rust-lang.org/std/primitive.never.html), which is not done. The "simple" fix would be to add an explicit `-> ()` to system signatures (e.g., `|| { todo!() }` becomes `|| -> () { todo!() }`). However, this is _also_ banned, as there is an existing lint which (IMO, incorrectly) marks this as an unnecessary annotation. So, the "fix" (read: workaround) is to put these kinds of `|| -> ! { ... }` closuers into variables and give the variable an explicit type (e.g., `fn()`). ```rust // Valid let system: fn() = || todo!("Not implemented yet!"); app.add_systems(..., system); // Invalid app.add_systems(..., || todo!("Not implemented yet!")); ``` ### Temporary Variable Lifetimes The order in which temporary variables are dropped has changed. The simple fix here is _usually_ to just assign temporaries to a named variable before use. ### `gen` is a keyword We can no longer use the name `gen` as it is reserved for a future generator syntax. This involved replacing uses of the name `gen` with `r#gen` (the raw-identifier syntax). ### Formatting has changed Use statements have had the order of imports changed, causing a substantial +/-3,000 diff when applied. For now, I have opted-out of this change by amending `rustfmt.toml` ```toml style_edition = "2021" ``` This preserves the original formatting for now, reducing the size of this PR. It would be a simple followup to update this to 2024 and run `cargo fmt`. ### New `use<>` Opt-Out Syntax Lifetimes are now implicitly included in RPIT types. There was a handful of instances where it needed to be added to satisfy the borrow checker, but there may be more cases where it _should_ be added to avoid breakages in user code. ### `MyUnitStruct { .. }` is an invalid pattern Previously, you could match against unit structs (and unit enum variants) with a `{ .. }` destructuring. This is no longer valid. ### Pretty much every use of `ref` and `mut` are gone Pattern binding has changed to the point where these terms are largely unused now. They still serve a purpose, but it is far more niche now. ### `iter::repeat(...).take(...)` is bad New lint recommends using the more explicit `iter::repeat_n(..., ...)` instead. ## Migration Guide The lifetimes of functions using return-position impl-trait (RPIT) are likely _more_ conservative than they had been previously. If you encounter lifetime issues with such a function, please create an issue to investigate the addition of `+ use<...>`. ## Notes - Check the individual commits for a clearer breakdown for what _actually_ changed. --------- Co-authored-by: François Mockers <francois.mockers@vleue.com> |
||
![]() |
be9b38e372
|
implement UniqueEntitySlice (#17589)
# Objective Follow-up to #17549 and #16547. A large part of `Vec`s usefulness is behind its ability to be sliced, like sorting f.e., so we want the same to be possible for `UniqueEntityVec`. ## Solution Add a `UniqueEntitySlice` type. It is a wrapper around `[T]`, and itself a DST. Because `mem::swap` has a `Sized` bound, DSTs cannot be swapped, and we can freely hand out mutable subslices without worrying about the uniqueness invariant of the backing collection! `UniqueEntityVec` and the relevant `UniqueEntityIter`s now have methods and trait impls that return `UniqueEntitySlice`s. `UniqueEntitySlice` itself can deref into normal slices, which means we can avoid implementing the vast majority of immutable slice methods. Most of the remaining methods: - split a slice/collection in further unique subsections/slices - reorder the slice: `sort`, `rotate_*`, `swap` - construct/deconstruct/convert pointer-like types: `Box`, `Arc`, `Rc`, `Cow` - are comparison trait impls As this PR is already larger than I'd like, we leave several things to follow-ups: - `UniqueEntityArray` and the related slice methods that would return it - denoted by "chunk", "array_*" for iterators - Methods that return iterators with `UniqueEntitySlice` as their item - `windows`, `chunks` and `split` families - All methods that are capable of actively mutating individual elements. While they could be offered unsafely, subslicing makes their safety contract weird enough to warrant its own discussion. - `fill_with`, `swap_with_slice`, `iter_mut`, `split_first/last_mut`, `select_nth_unstable_*` Note that `Arc`, `Rc` and `Cow` are not fundamental types, so even if they contain `UniqueEntitySlice`, we cannot write direct trait impls for them. On top of that, `Cow` is not a receiver (like `self: Arc<Self>` is) so we cannot write inherent methods for it either. |
||
![]() |
b039bf6768
|
implement UniqueEntityVec (#17549)
# Objective In #16547, we added `EntitySet`s/`EntitySetIterator`s. We can know whenever an iterator only contains unique entities, however we do not yet have the ability to collect and reuse these without either the unsafe `UniqueEntityIter::from_iterator_unchecked`, or the expensive `HashSet::from_iter`. An important piece for being able to do this is a `Vec` that maintains the uniqueness property, can be collected into, and is itself `EntitySet`. A lot of entity collections are already intended to be "unique", but have no way of expressing that when stored, other than using an aforementioned `HashSet`. Such a type helps by limiting or even removing the need for unsafe on the user side when not using a validated `Set` type, and makes it easier to interface with other infrastructure like f.e. `RelationshipSourceCollection`s. ## Solution We implement `UniqueEntityVec`. This is a wrapper around `Vec`, that only ever contains unique elements. It mirrors the API of `Vec`, however restricts any mutation as to not violate the uniqueness guarantee. Meaning: - Any inherent method which can introduce new elements or mutate existing ones is now unsafe, f.e.: `insert`, `retain_mut` - Methods that are impossible to use safely are omitted, f.e.: `fill`, `extend_from_within` A handful of the unsafe methods can do element-wise mutation (`retain_mut`, `dedup_by`), which can be an unwind safety hazard were the element-wise operation to panic. For those methods, we require that each individual execution of the operation upholds uniqueness, not just the entire method as a whole. To be safe for mutable usage, slicing and the associated slice methods require a matching `UniqueEntitySlice` type , which we leave for a follow-up PR. Because this type will deref into the `UniqueEntitySlice` type, we also offer the immutable `Vec` methods on this type (which only amount to a handful). "as inner" functionality is covered by additional `as_vec`/`as_mut_vec` methods + `AsRef`/`Borrow` trait impls. Like `UniqueEntityIter::from_iterator_unchecked`, this type has a `from_vec_unchecked` method as well. The canonical way to safely obtain this type however is via `EntitySetIterator::collect_set` or `UniqueEntityVec::from_entity_set_iter`. Like mentioned in #17513, these are named suboptimally until supertrait item shadowing arrives, since a normal `collect` will still run equality checks. |