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>
This commit is contained in:
Zachary Harrold 2025-02-24 14:54:47 +11:00 committed by GitHub
parent 2953db7f8f
commit 5241e09671
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
187 changed files with 596 additions and 592 deletions

View File

@ -335,6 +335,7 @@ jobs:
timeout-minutes: 30 timeout-minutes: 30
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: check for missing metadata - name: check for missing metadata
id: missing-metadata id: missing-metadata
run: cargo run -p build-templated-pages -- check-missing examples run: cargo run -p build-templated-pages -- check-missing examples
@ -369,6 +370,7 @@ jobs:
needs: check-missing-examples-in-docs needs: check-missing-examples-in-docs
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: check for missing features - name: check for missing features
id: missing-features id: missing-features
run: cargo run -p build-templated-pages -- check-missing features run: cargo run -p build-templated-pages -- check-missing features
@ -412,6 +414,7 @@ jobs:
~/.cargo/git/db/ ~/.cargo/git/db/
target/ target/
key: ${{ runner.os }}-cargo-msrv-${{ hashFiles('**/Cargo.toml') }} key: ${{ runner.os }}-cargo-msrv-${{ hashFiles('**/Cargo.toml') }}
- uses: dtolnay/rust-toolchain@stable
- name: get MSRV - name: get MSRV
id: msrv id: msrv
run: | run: |

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy" name = "bevy"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
categories = ["game-engines", "graphics", "gui", "rendering"] categories = ["game-engines", "graphics", "gui", "rendering"]
description = "A refreshingly simple data-driven game engine and app framework" description = "A refreshingly simple data-driven game engine and app framework"
exclude = ["assets/", "tools/", ".github/", "crates/", "examples/wasm/assets/"] exclude = ["assets/", "tools/", ".github/", "crates/", "examples/wasm/assets/"]
@ -10,7 +10,7 @@ keywords = ["game", "engine", "gamedev", "graphics", "bevy"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"
documentation = "https://docs.rs/bevy" documentation = "https://docs.rs/bevy"
rust-version = "1.83.0" rust-version = "1.85.0"
[workspace] [workspace]
resolver = "2" resolver = "2"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "benches" name = "benches"
edition = "2021" edition = "2024"
description = "Benchmarks that test Bevy's performance" description = "Benchmarks that test Bevy's performance"
publish = false publish = false
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"

View File

@ -95,7 +95,7 @@ fn all_added_detection_generic<T: Component + Default>(group: &mut BenchGroup, e
let query = generic_filter_query::<Added<T>>(&mut world); let query = generic_filter_query::<Added<T>>(&mut world);
(world, query) (world, query)
}, },
|(ref mut world, ref mut query)| { |(world, query)| {
let mut count = 0; let mut count = 0;
for entity in query.iter(world) { for entity in query.iter(world) {
black_box(entity); black_box(entity);
@ -143,7 +143,7 @@ fn all_changed_detection_generic<T: Component<Mutability = Mutable> + Default +
let query = generic_filter_query::<Changed<T>>(&mut world); let query = generic_filter_query::<Changed<T>>(&mut world);
(world, query) (world, query)
}, },
|(ref mut world, ref mut query)| { |(world, query)| {
let mut count = 0; let mut count = 0;
for entity in query.iter(world) { for entity in query.iter(world) {
black_box(entity); black_box(entity);
@ -196,7 +196,7 @@ fn few_changed_detection_generic<T: Component<Mutability = Mutable> + Default +
let query = generic_filter_query::<Changed<T>>(&mut world); let query = generic_filter_query::<Changed<T>>(&mut world);
(world, query) (world, query)
}, },
|(ref mut world, ref mut query)| { |(world, query)| {
for entity in query.iter(world) { for entity in query.iter(world) {
black_box(entity); black_box(entity);
} }
@ -237,7 +237,7 @@ fn none_changed_detection_generic<T: Component<Mutability = Mutable> + Default>(
let query = generic_filter_query::<Changed<T>>(&mut world); let query = generic_filter_query::<Changed<T>>(&mut world);
(world, query) (world, query)
}, },
|(ref mut world, ref mut query)| { |(world, query)| {
let mut count = 0; let mut count = 0;
for entity in query.iter(world) { for entity in query.iter(world) {
black_box(entity); black_box(entity);
@ -343,7 +343,7 @@ fn multiple_archetype_none_changed_detection_generic<
let query = generic_filter_query::<Changed<T>>(&mut world); let query = generic_filter_query::<Changed<T>>(&mut world);
(world, query) (world, query)
}, },
|(ref mut world, ref mut query)| { |(world, query)| {
let mut count = 0; let mut count = 0;
for entity in query.iter(world) { for entity in query.iter(world) {
black_box(entity); black_box(entity);

View File

@ -12,7 +12,7 @@ impl Benchmark {
let mut world = World::default(); let mut world = World::default();
let entities = world let entities = world
.spawn_batch(core::iter::repeat(A(0.)).take(10000)) .spawn_batch(core::iter::repeat_n(A(0.), 10_000))
.collect(); .collect();
Self(world, entities) Self(world, entities)
} }

View File

@ -19,15 +19,15 @@ impl<'w> Benchmark<'w> {
pub fn new() -> Self { pub fn new() -> Self {
let mut world = World::new(); let mut world = World::new();
world.spawn_batch( world.spawn_batch(core::iter::repeat_n(
core::iter::repeat(( (
Transform(Mat4::from_scale(Vec3::ONE)), Transform(Mat4::from_scale(Vec3::ONE)),
Position(Vec3::X), Position(Vec3::X),
Rotation(Vec3::X), Rotation(Vec3::X),
Velocity(Vec3::X), Velocity(Vec3::X),
)) ),
.take(10_000), 10_000,
); ));
let query = world.query::<(&Velocity, &mut Position)>(); let query = world.query::<(&Velocity, &mut Position)>();
Self(world, query) Self(world, query)

View File

@ -19,15 +19,15 @@ impl<'w> Benchmark<'w> {
pub fn new() -> Self { pub fn new() -> Self {
let mut world = World::new(); let mut world = World::new();
world.spawn_batch( world.spawn_batch(core::iter::repeat_n(
core::iter::repeat(( (
Transform(Mat4::from_scale(Vec3::ONE)), Transform(Mat4::from_scale(Vec3::ONE)),
Position(Vec3::X), Position(Vec3::X),
Rotation(Vec3::X), Rotation(Vec3::X),
Velocity(Vec3::X), Velocity(Vec3::X),
)) ),
.take(10_000), 10_000,
); ));
let query = world.query::<(&Velocity, &mut Position)>(); let query = world.query::<(&Velocity, &mut Position)>();
Self(world, query) Self(world, query)

View File

@ -21,15 +21,15 @@ impl<'w> Benchmark<'w> {
pub fn new() -> Self { pub fn new() -> Self {
let mut world = World::new(); let mut world = World::new();
world.spawn_batch( world.spawn_batch(core::iter::repeat_n(
core::iter::repeat(( (
Transform(Mat4::from_scale(Vec3::ONE)), Transform(Mat4::from_scale(Vec3::ONE)),
Position(Vec3::X), Position(Vec3::X),
Rotation(Vec3::X), Rotation(Vec3::X),
Velocity(Vec3::X), Velocity(Vec3::X),
)) ),
.take(10_000), 10_000,
); ));
let query = world.query::<(&Velocity, &mut Position)>(); let query = world.query::<(&Velocity, &mut Position)>();
Self(world, query) Self(world, query)

View File

@ -33,8 +33,8 @@ impl<'w> Benchmark<'w> {
pub fn new() -> Self { pub fn new() -> Self {
let mut world = World::new(); let mut world = World::new();
world.spawn_batch( world.spawn_batch(core::iter::repeat_n(
core::iter::repeat(( (
Transform(Mat4::from_scale(Vec3::ONE)), Transform(Mat4::from_scale(Vec3::ONE)),
Rotation(Vec3::X), Rotation(Vec3::X),
Position::<0>(Vec3::X), Position::<0>(Vec3::X),
@ -47,9 +47,9 @@ impl<'w> Benchmark<'w> {
Velocity::<3>(Vec3::X), Velocity::<3>(Vec3::X),
Position::<4>(Vec3::X), Position::<4>(Vec3::X),
Velocity::<4>(Vec3::X), Velocity::<4>(Vec3::X),
)) ),
.take(10_000), 10_000,
); ));
let query = world.query(); let query = world.query();
Self(world, query) Self(world, query)

View File

@ -35,8 +35,8 @@ impl<'w> Benchmark<'w> {
pub fn new() -> Self { pub fn new() -> Self {
let mut world = World::new(); let mut world = World::new();
world.spawn_batch( world.spawn_batch(core::iter::repeat_n(
core::iter::repeat(( (
Transform(Mat4::from_scale(Vec3::ONE)), Transform(Mat4::from_scale(Vec3::ONE)),
Rotation(Vec3::X), Rotation(Vec3::X),
Position::<0>(Vec3::X), Position::<0>(Vec3::X),
@ -49,9 +49,9 @@ impl<'w> Benchmark<'w> {
Velocity::<3>(Vec3::X), Velocity::<3>(Vec3::X),
Position::<4>(Vec3::X), Position::<4>(Vec3::X),
Velocity::<4>(Vec3::X), Velocity::<4>(Vec3::X),
)) ),
.take(10_000), 10_000,
); ));
let query = world.query(); let query = world.query();
Self(world, query) Self(world, query)

View File

@ -21,15 +21,15 @@ impl<'w> Benchmark<'w> {
pub fn new() -> Self { pub fn new() -> Self {
let mut world = World::new(); let mut world = World::new();
world.spawn_batch( world.spawn_batch(core::iter::repeat_n(
core::iter::repeat(( (
Transform(Mat4::from_scale(Vec3::ONE)), Transform(Mat4::from_scale(Vec3::ONE)),
Position(Vec3::X), Position(Vec3::X),
Rotation(Vec3::X), Rotation(Vec3::X),
Velocity(Vec3::X), Velocity(Vec3::X),
)) ),
.take(10_000), 10_000,
); ));
let query = world.query::<(&Velocity, &mut Position)>(); let query = world.query::<(&Velocity, &mut Position)>();
Self(world, query) Self(world, query)

View File

@ -19,15 +19,15 @@ impl Benchmark {
pub fn new() -> Self { pub fn new() -> Self {
let mut world = World::new(); let mut world = World::new();
world.spawn_batch( world.spawn_batch(core::iter::repeat_n(
core::iter::repeat(( (
Transform(Mat4::from_scale(Vec3::ONE)), Transform(Mat4::from_scale(Vec3::ONE)),
Position(Vec3::X), Position(Vec3::X),
Rotation(Vec3::X), Rotation(Vec3::X),
Velocity(Vec3::X), Velocity(Vec3::X),
)) ),
.take(10_000), 10_000,
); ));
fn query_system(mut query: Query<(&Velocity, &mut Position)>) { fn query_system(mut query: Query<(&Velocity, &mut Position)>) {
for (velocity, mut position) in &mut query { for (velocity, mut position) in &mut query {

View File

@ -33,8 +33,8 @@ impl<'w> Benchmark<'w> {
pub fn new() -> Self { pub fn new() -> Self {
let mut world = World::new(); let mut world = World::new();
world.spawn_batch( world.spawn_batch(core::iter::repeat_n(
core::iter::repeat(( (
Transform(Mat4::from_scale(Vec3::ONE)), Transform(Mat4::from_scale(Vec3::ONE)),
Rotation(Vec3::X), Rotation(Vec3::X),
Position::<0>(Vec3::X), Position::<0>(Vec3::X),
@ -47,9 +47,9 @@ impl<'w> Benchmark<'w> {
Velocity::<3>(Vec3::X), Velocity::<3>(Vec3::X),
Position::<4>(Vec3::X), Position::<4>(Vec3::X),
Velocity::<4>(Vec3::X), Velocity::<4>(Vec3::X),
)) ),
.take(10_000), 10_000,
); ));
let query = world.query(); let query = world.query();
Self(world, query) Self(world, query)

View File

@ -35,8 +35,8 @@ impl<'w> Benchmark<'w> {
pub fn new() -> Self { pub fn new() -> Self {
let mut world = World::new(); let mut world = World::new();
world.spawn_batch( world.spawn_batch(core::iter::repeat_n(
core::iter::repeat(( (
Transform(Mat4::from_scale(Vec3::ONE)), Transform(Mat4::from_scale(Vec3::ONE)),
Rotation(Vec3::X), Rotation(Vec3::X),
Position::<0>(Vec3::X), Position::<0>(Vec3::X),
@ -49,9 +49,9 @@ impl<'w> Benchmark<'w> {
Velocity::<3>(Vec3::X), Velocity::<3>(Vec3::X),
Position::<4>(Vec3::X), Position::<4>(Vec3::X),
Velocity::<4>(Vec3::X), Velocity::<4>(Vec3::X),
)) ),
.take(10_000), 10_000,
); ));
let query = world.query(); let query = world.query();
Self(world, query) Self(world, query)

View File

@ -30,15 +30,15 @@ impl<'w> Benchmark<'w> {
let mut world = World::new(); let mut world = World::new();
let iter = world.spawn_batch( let iter = world.spawn_batch(core::iter::repeat_n(
core::iter::repeat(( (
Transform(Mat4::from_scale(Vec3::ONE)), Transform(Mat4::from_scale(Vec3::ONE)),
Position(Vec3::X), Position(Vec3::X),
Rotation(Vec3::X), Rotation(Vec3::X),
Velocity(Vec3::X), Velocity(Vec3::X),
)) ),
.take(100_000), 100_000,
); ));
let entities = iter.into_iter().collect::<Vec<Entity>>(); let entities = iter.into_iter().collect::<Vec<Entity>>();
for i in 0..fragment { for i in 0..fragment {
let mut e = world.entity_mut(entities[i as usize]); let mut e = world.entity_mut(entities[i as usize]);

View File

@ -11,16 +11,16 @@ fn make_entity(rng: &mut impl Rng, size: usize) -> Entity {
// * For ids, half are in [0, size), half are unboundedly larger. // * For ids, half are in [0, size), half are unboundedly larger.
// * For generations, half are in [1, 3), half are unboundedly larger. // * For generations, half are in [1, 3), half are unboundedly larger.
let x: f64 = rng.gen(); let x: f64 = rng.r#gen();
let id = -(1.0 - x).log2() * (size as f64); let id = -(1.0 - x).log2() * (size as f64);
let x: f64 = rng.gen(); let x: f64 = rng.r#gen();
let gen = 1.0 + -(1.0 - x).log2() * 2.0; let generation = 1.0 + -(1.0 - x).log2() * 2.0;
// this is not reliable, but we're internal so a hack is ok // this is not reliable, but we're internal so a hack is ok
let bits = ((gen as u64) << 32) | (id as u64); let bits = ((generation as u64) << 32) | (id as u64);
let e = Entity::from_bits(bits); let e = Entity::from_bits(bits);
assert_eq!(e.index(), id as u32); assert_eq!(e.index(), id as u32);
assert_eq!(e.generation(), gen as u32); assert_eq!(e.generation(), generation as u32);
e e
} }

View File

@ -75,8 +75,8 @@ fn concrete_list_apply(criterion: &mut Criterion) {
let mut group = create_group(criterion, bench!("concrete_list_apply")); let mut group = create_group(criterion, bench!("concrete_list_apply"));
let empty_base = |_: usize| Vec::<u64>::new; let empty_base = |_: usize| Vec::<u64>::new;
let full_base = |size: usize| move || iter::repeat(0).take(size).collect::<Vec<u64>>(); let full_base = |size: usize| move || iter::repeat_n(0, size).collect::<Vec<u64>>();
let patch = |size: usize| iter::repeat(1).take(size).collect::<Vec<u64>>(); let patch = |size: usize| iter::repeat_n(1, size).collect::<Vec<u64>>();
list_apply(&mut group, "empty_base_concrete_patch", empty_base, patch); list_apply(&mut group, "empty_base_concrete_patch", empty_base, patch);
@ -103,7 +103,7 @@ fn concrete_list_clone_dynamic(criterion: &mut Criterion) {
BenchmarkId::from_parameter(size), BenchmarkId::from_parameter(size),
&size, &size,
|bencher, &size| { |bencher, &size| {
let v = iter::repeat(0).take(size).collect::<Vec<_>>(); let v = iter::repeat_n(0, size).collect::<Vec<_>>();
bencher.iter(|| black_box(&v).clone_dynamic()); bencher.iter(|| black_box(&v).clone_dynamic());
}, },
@ -123,7 +123,7 @@ fn dynamic_list_push(criterion: &mut Criterion) {
BenchmarkId::from_parameter(size), BenchmarkId::from_parameter(size),
&size, &size,
|bencher, &size| { |bencher, &size| {
let src = iter::repeat(()).take(size).collect::<Vec<_>>(); let src = iter::repeat_n((), size).collect::<Vec<_>>();
let dst = DynamicList::default(); let dst = DynamicList::default();
bencher.iter_batched( bencher.iter_batched(
@ -146,8 +146,8 @@ fn dynamic_list_apply(criterion: &mut Criterion) {
let mut group = create_group(criterion, bench!("dynamic_list_apply")); let mut group = create_group(criterion, bench!("dynamic_list_apply"));
let empty_base = |_: usize| || Vec::<u64>::new().clone_dynamic(); let empty_base = |_: usize| || Vec::<u64>::new().clone_dynamic();
let full_base = |size: usize| move || iter::repeat(0).take(size).collect::<Vec<u64>>(); let full_base = |size: usize| move || iter::repeat_n(0, size).collect::<Vec<u64>>();
let patch = |size: usize| iter::repeat(1).take(size).collect::<Vec<u64>>(); let patch = |size: usize| iter::repeat_n(1, size).collect::<Vec<u64>>();
list_apply(&mut group, "empty_base_concrete_patch", empty_base, patch); list_apply(&mut group, "empty_base_concrete_patch", empty_base, patch);

View File

@ -145,7 +145,7 @@ fn u64_to_n_byte_key(k: u64, n: usize) -> String {
write!(&mut key, "{}", k).unwrap(); write!(&mut key, "{}", k).unwrap();
// Pad key to n bytes. // Pad key to n bytes.
key.extend(iter::repeat('\0').take(n - key.len())); key.extend(iter::repeat_n('\0', n - key.len()));
key key
} }

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_a11y" name = "bevy_a11y"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Provides accessibility support for Bevy Engine" description = "Provides accessibility support for Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_animation" name = "bevy_animation"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Provides animation functionality for Bevy Engine" description = "Provides animation functionality for Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -884,10 +884,10 @@ impl ThreadedAnimationGraph {
self.sorted_edge_ranges.clear(); self.sorted_edge_ranges.clear();
self.sorted_edge_ranges self.sorted_edge_ranges
.extend(iter::repeat(0..0).take(node_count)); .extend(iter::repeat_n(0..0, node_count));
self.computed_masks.clear(); self.computed_masks.clear();
self.computed_masks.extend(iter::repeat(0).take(node_count)); self.computed_masks.extend(iter::repeat_n(0, node_count));
} }
/// Recursively constructs the [`ThreadedAnimationGraph`] for the subtree /// Recursively constructs the [`ThreadedAnimationGraph`] for the subtree

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_app" name = "bevy_app"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Provides core App functionality for Bevy Engine" description = "Provides core App functionality for Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -1435,7 +1435,7 @@ impl Termination for AppExit {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use core::{iter, marker::PhantomData}; use core::marker::PhantomData;
use std::sync::Mutex; use std::sync::Mutex;
use bevy_ecs::{ use bevy_ecs::{
@ -1659,7 +1659,7 @@ mod tests {
struct Foo; struct Foo;
let mut app = App::new(); let mut app = App::new();
app.world_mut().spawn_batch(iter::repeat(Foo).take(5)); app.world_mut().spawn_batch(core::iter::repeat_n(Foo, 5));
fn despawn_one_foo(mut commands: Commands, foos: Query<Entity, With<Foo>>) { fn despawn_one_foo(mut commands: Commands, foos: Query<Entity, With<Foo>>) {
if let Some(e) = foos.iter().next() { if let Some(e) = foos.iter().next() {

View File

@ -11,7 +11,7 @@ use crate::{App, Plugin};
/// Adds sensible panic handlers to Apps. This plugin is part of the `DefaultPlugins`. Adding /// Adds sensible panic handlers to Apps. This plugin is part of the `DefaultPlugins`. Adding
/// this plugin will setup a panic hook appropriate to your target platform: /// this plugin will setup a panic hook appropriate to your target platform:
/// * On Wasm, uses [`console_error_panic_hook`](https://crates.io/crates/console_error_panic_hook), logging /// * On Wasm, uses [`console_error_panic_hook`](https://crates.io/crates/console_error_panic_hook), logging
/// to the browser console. /// to the browser console.
/// * Other platforms are currently not setup. /// * Other platforms are currently not setup.
/// ///
/// ```no_run /// ```no_run

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_asset" name = "bevy_asset"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Provides asset functionality for Bevy Engine" description = "Provides asset functionality for Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_asset_macros" name = "bevy_asset_macros"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Derive implementations for bevy_asset" description = "Derive implementations for bevy_asset"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -499,8 +499,8 @@ pub trait AssetApp {
/// * Initializing the [`AssetEvent`] resource for the [`Asset`] /// * Initializing the [`AssetEvent`] resource for the [`Asset`]
/// * Adding other relevant systems and resources for the [`Asset`] /// * Adding other relevant systems and resources for the [`Asset`]
/// * Ignoring schedule ambiguities in [`Assets`] resource. Any time a system takes /// * Ignoring schedule ambiguities in [`Assets`] resource. Any time a system takes
/// mutable access to this resource this causes a conflict, but they rarely actually /// mutable access to this resource this causes a conflict, but they rarely actually
/// modify the same underlying asset. /// modify the same underlying asset.
fn init_asset<A: Asset>(&mut self) -> &mut Self; fn init_asset<A: Asset>(&mut self) -> &mut Self;
/// Registers the asset type `T` using `[App::register]`, /// Registers the asset type `T` using `[App::register]`,
/// and adds [`ReflectAsset`] type data to `T` and [`ReflectHandle`] type data to [`Handle<T>`] in the type registry. /// and adds [`ReflectAsset`] type data to `T` and [`ReflectHandle`] type data to [`Handle<T>`] in the type registry.

View File

@ -552,8 +552,8 @@ impl<'a> LoadContext<'a> {
let path = path.into(); let path = path.into();
let source = self.asset_server.get_source(path.source())?; let source = self.asset_server.get_source(path.source())?;
let asset_reader = match self.asset_server.mode() { let asset_reader = match self.asset_server.mode() {
AssetServerMode::Unprocessed { .. } => source.reader(), AssetServerMode::Unprocessed => source.reader(),
AssetServerMode::Processed { .. } => source.processed_reader()?, AssetServerMode::Processed => source.processed_reader()?,
}; };
let mut reader = asset_reader.read(path.path()).await?; let mut reader = asset_reader.read(path.path()).await?;
let hash = if self.populate_hashes { let hash = if self.populate_hashes {

View File

@ -18,10 +18,10 @@ use thiserror::Error;
/// ///
/// Asset paths consist of three main parts: /// Asset paths consist of three main parts:
/// * [`AssetPath::source`]: The name of the [`AssetSource`](crate::io::AssetSource) to load the asset from. /// * [`AssetPath::source`]: The name of the [`AssetSource`](crate::io::AssetSource) to load the asset from.
/// This is optional. If one is not set the default source will be used (which is the `assets` folder by default). /// This is optional. If one is not set the default source will be used (which is the `assets` folder by default).
/// * [`AssetPath::path`]: The "virtual filesystem path" pointing to an asset source file. /// * [`AssetPath::path`]: The "virtual filesystem path" pointing to an asset source file.
/// * [`AssetPath::label`]: An optional "named sub asset". When assets are loaded, they are /// * [`AssetPath::label`]: An optional "named sub asset". When assets are loaded, they are
/// allowed to load "sub assets" of any type, which are identified by a named "label". /// allowed to load "sub assets" of any type, which are identified by a named "label".
/// ///
/// Asset paths are generally constructed (and visualized) as strings: /// Asset paths are generally constructed (and visualized) as strings:
/// ///

View File

@ -207,10 +207,13 @@ impl AssetProcessor {
/// Processes all assets. This will: /// Processes all assets. This will:
/// * For each "processed [`AssetSource`]: /// * For each "processed [`AssetSource`]:
/// * Scan the [`ProcessorTransactionLog`] and recover from any failures detected /// * Scan the [`ProcessorTransactionLog`] and recover from any failures detected
/// * Scan the processed [`AssetReader`](crate::io::AssetReader) to build the current view of already processed assets. /// * Scan the processed [`AssetReader`](crate::io::AssetReader) to build the current view of
/// * Scan the unprocessed [`AssetReader`](crate::io::AssetReader) and remove any final processed assets that are invalid or no longer exist. /// already processed assets.
/// * For each asset in the unprocessed [`AssetReader`](crate::io::AssetReader), kick off a new "process job", which will process the asset /// * Scan the unprocessed [`AssetReader`](crate::io::AssetReader) and remove any final
/// (if the latest version of the asset has not been processed). /// processed assets that are invalid or no longer exist.
/// * For each asset in the unprocessed [`AssetReader`](crate::io::AssetReader), kick off a new
/// "process job", which will process the asset
/// (if the latest version of the asset has not been processed).
#[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))] #[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))]
pub fn process_assets(&self) { pub fn process_assets(&self) {
let start_time = std::time::Instant::now(); let start_time = std::time::Instant::now();

View File

@ -38,12 +38,13 @@ use std::path::{Path, PathBuf};
use thiserror::Error; use thiserror::Error;
use tracing::{error, info}; use tracing::{error, info};
/// Loads and tracks the state of [`Asset`] values from a configured [`AssetReader`](crate::io::AssetReader). This can be used to kick off new asset loads and /// Loads and tracks the state of [`Asset`] values from a configured [`AssetReader`](crate::io::AssetReader).
/// retrieve their current load states. /// This can be used to kick off new asset loads and retrieve their current load states.
/// ///
/// The general process to load an asset is: /// The general process to load an asset is:
/// 1. Initialize a new [`Asset`] type with the [`AssetServer`] via [`AssetApp::init_asset`], which will internally call [`AssetServer::register_asset`] /// 1. Initialize a new [`Asset`] type with the [`AssetServer`] via [`AssetApp::init_asset`], which
/// and set up related ECS [`Assets`] storage and systems. /// will internally call [`AssetServer::register_asset`] and set up related ECS [`Assets`]
/// storage and systems.
/// 2. Register one or more [`AssetLoader`]s for that asset with [`AssetApp::init_asset_loader`] /// 2. Register one or more [`AssetLoader`]s for that asset with [`AssetApp::init_asset_loader`]
/// 3. Add the asset to your asset folder (defaults to `assets`). /// 3. Add the asset to your asset folder (defaults to `assets`).
/// 4. Call [`AssetServer::load`] with a path to your asset. /// 4. Call [`AssetServer::load`] with a path to your asset.
@ -923,8 +924,8 @@ impl AssetServer {
}; };
let asset_reader = match server.data.mode { let asset_reader = match server.data.mode {
AssetServerMode::Unprocessed { .. } => source.reader(), AssetServerMode::Unprocessed => source.reader(),
AssetServerMode::Processed { .. } => match source.processed_reader() { AssetServerMode::Processed => match source.processed_reader() {
Ok(reader) => reader, Ok(reader) => reader,
Err(_) => { Err(_) => {
error!( error!(
@ -1235,8 +1236,8 @@ impl AssetServer {
// Then the meta reader, if meta exists, will correspond to the meta for the current "version" of the asset. // Then the meta reader, if meta exists, will correspond to the meta for the current "version" of the asset.
// See ProcessedAssetInfo::file_transaction_lock for more context // See ProcessedAssetInfo::file_transaction_lock for more context
let asset_reader = match self.data.mode { let asset_reader = match self.data.mode {
AssetServerMode::Unprocessed { .. } => source.reader(), AssetServerMode::Unprocessed => source.reader(),
AssetServerMode::Processed { .. } => source.processed_reader()?, AssetServerMode::Processed => source.processed_reader()?,
}; };
let reader = asset_reader.read(asset_path.path()).await?; let reader = asset_reader.read(asset_path.path()).await?;
let read_meta = match &self.data.meta_check { let read_meta = match &self.data.meta_check {
@ -1584,14 +1585,14 @@ pub fn handle_internal_asset_events(world: &mut World) {
for source in server.data.sources.iter() { for source in server.data.sources.iter() {
match server.data.mode { match server.data.mode {
AssetServerMode::Unprocessed { .. } => { AssetServerMode::Unprocessed => {
if let Some(receiver) = source.event_receiver() { if let Some(receiver) = source.event_receiver() {
for event in receiver.try_iter() { for event in receiver.try_iter() {
handle_event(source.id(), event); handle_event(source.id(), event);
} }
} }
} }
AssetServerMode::Processed { .. } => { AssetServerMode::Processed => {
if let Some(receiver) = source.processed_event_receiver() { if let Some(receiver) = source.processed_event_receiver() {
for event in receiver.try_iter() { for event in receiver.try_iter() {
handle_event(source.id(), event); handle_event(source.id(), event);

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_audio" name = "bevy_audio"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Provides audio functionality for Bevy Engine" description = "Provides audio functionality for Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -1,13 +1,13 @@
[package] [package]
name = "bevy_color" name = "bevy_color"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Types for representing and manipulating color values" description = "Types for representing and manipulating color values"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
keywords = ["bevy", "color"] keywords = ["bevy", "color"]
rust-version = "1.83.0" rust-version = "1.85.0"
[dependencies] [dependencies]
bevy_math = { path = "../bevy_math", version = "0.16.0-dev", default-features = false, features = [ bevy_math = { path = "../bevy_math", version = "0.16.0-dev", default-features = false, features = [

View File

@ -1,7 +1,7 @@
[package] [package]
name = "gen_tests" name = "gen_tests"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2024"
publish = false publish = false
[workspace] [workspace]

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_core_pipeline" name = "bevy_core_pipeline"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
authors = [ authors = [
"Bevy Contributors <bevyengine@gmail.com>", "Bevy Contributors <bevyengine@gmail.com>",
"Carter Anderson <mcanders1@gmail.com>", "Carter Anderson <mcanders1@gmail.com>",

View File

@ -152,7 +152,8 @@ impl ViewNode for BloomNode {
render_context.command_encoder().push_debug_group("bloom"); render_context.command_encoder().push_debug_group("bloom");
let diagnostics = render_context.diagnostic_recorder(); let diagnostics = render_context.diagnostic_recorder();
let time_span = diagnostics.time_span(render_context.command_encoder(), "bloom"); let command_encoder = render_context.command_encoder();
let time_span = diagnostics.time_span(command_encoder, "bloom");
// First downsample pass // First downsample pass
{ {

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_derive" name = "bevy_derive"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Provides derive implementations for Bevy Engine" description = "Provides derive implementations for Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "bevy_derive_compile_fail" name = "bevy_derive_compile_fail"
edition = "2021" edition = "2024"
description = "Compile fail tests for Bevy Engine's various macros" description = "Compile fail tests for Bevy Engine's various macros"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -10,14 +10,20 @@ pub fn bevy_main(_attr: TokenStream, item: TokenStream) -> TokenStream {
); );
TokenStream::from(quote! { TokenStream::from(quote! {
#[no_mangle] // SAFETY: `#[bevy_main]` should only be placed on a single `main` function
// TODO: Potentially make `bevy_main` and unsafe attribute as there is a safety
// guarantee required from the caller.
#[unsafe(no_mangle)]
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
fn android_main(android_app: bevy::window::android_activity::AndroidApp) { fn android_main(android_app: bevy::window::android_activity::AndroidApp) {
let _ = bevy::window::ANDROID_APP.set(android_app); let _ = bevy::window::ANDROID_APP.set(android_app);
main(); main();
} }
#[no_mangle] // SAFETY: `#[bevy_main]` should only be placed on a single `main` function
// TODO: Potentially make `bevy_main` and unsafe attribute as there is a safety
// guarantee required from the caller.
#[unsafe(no_mangle)]
#[cfg(target_os = "ios")] #[cfg(target_os = "ios")]
extern "C" fn main_rs() { extern "C" fn main_rs() {
main(); main();

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_dev_tools" name = "bevy_dev_tools"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Collection of developer tools for the Bevy Engine" description = "Collection of developer tools for the Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -29,7 +29,7 @@ pub mod states;
/// To enable developer tools, you can either: /// To enable developer tools, you can either:
/// ///
/// - Create a custom crate feature (e.g "`dev_mode`"), which enables the `bevy_dev_tools` feature /// - Create a custom crate feature (e.g "`dev_mode`"), which enables the `bevy_dev_tools` feature
/// along with any other development tools you might be using: /// along with any other development tools you might be using:
/// ///
/// ```toml /// ```toml
/// [feature] /// [feature]

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_diagnostic" name = "bevy_diagnostic"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Provides diagnostic functionality for Bevy Engine" description = "Provides diagnostic functionality for Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_dylib" name = "bevy_dylib"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Force the Bevy Engine to be dynamically linked for faster linking" description = "Force the Bevy Engine to be dynamically linked for faster linking"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -1,14 +1,14 @@
[package] [package]
name = "bevy_ecs" name = "bevy_ecs"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Bevy Engine's entity component system" description = "Bevy Engine's entity component system"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
keywords = ["ecs", "game", "bevy"] keywords = ["ecs", "game", "bevy"]
categories = ["game-engines", "data-structures"] categories = ["game-engines", "data-structures"]
rust-version = "1.83.0" rust-version = "1.85.0"
[features] [features]
default = ["std", "bevy_reflect", "async_executor"] default = ["std", "bevy_reflect", "async_executor"]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "bevy_ecs_compile_fail" name = "bevy_ecs_compile_fail"
edition = "2021" edition = "2024"
description = "Compile fail tests for Bevy Engine's entity component system" description = "Compile fail tests for Bevy Engine's entity component system"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -2,7 +2,7 @@
name = "bevy_ecs_macros" name = "bevy_ecs_macros"
version = "0.16.0-dev" version = "0.16.0-dev"
description = "Bevy ECS Macros" description = "Bevy ECS Macros"
edition = "2021" edition = "2024"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
[lib] [lib]

View File

@ -257,7 +257,7 @@ pub fn derive_component(input: TokenStream) -> TokenStream {
fn visit_entities(data: &Data, bevy_ecs_path: &Path, is_relationship: bool) -> TokenStream2 { fn visit_entities(data: &Data, bevy_ecs_path: &Path, is_relationship: bool) -> TokenStream2 {
match data { match data {
Data::Struct(DataStruct { ref fields, .. }) => { Data::Struct(DataStruct { fields, .. }) => {
let mut visited_fields = Vec::new(); let mut visited_fields = Vec::new();
let mut visited_indices = Vec::new(); let mut visited_indices = Vec::new();
match fields { match fields {
@ -343,8 +343,8 @@ fn visit_entities(data: &Data, bevy_ecs_path: &Path, is_relationship: bool) -> T
let field_member = ident_or_index(field.ident.as_ref(), index); let field_member = ident_or_index(field.ident.as_ref(), index);
let field_ident = format_ident!("field_{}", field_member); let field_ident = format_ident!("field_{}", field_member);
variant_fields.push(quote!(#field_member: ref #field_ident)); variant_fields.push(quote!(#field_member: #field_ident));
variant_fields_mut.push(quote!(#field_member: ref mut #field_ident)); variant_fields_mut.push(quote!(#field_member: #field_ident));
visit_variant_fields.push(quote!(#field_ident.visit_entities(&mut func);)); visit_variant_fields.push(quote!(#field_ident.visit_entities(&mut func);));
visit_variant_fields_mut visit_variant_fields_mut

View File

@ -811,7 +811,7 @@ impl<'w, T: ?Sized> Ref<'w, T> {
/// - `added` - A [`Tick`] that stores the tick when the wrapped value was created. /// - `added` - A [`Tick`] that stores the tick when the wrapped value was created.
/// - `changed` - A [`Tick`] that stores the last time the wrapped value was changed. /// - `changed` - A [`Tick`] that stores the last time the wrapped value was changed.
/// - `last_run` - A [`Tick`], occurring before `this_run`, which is used /// - `last_run` - A [`Tick`], occurring before `this_run`, which is used
/// as a reference to determine whether the wrapped value is newly added or changed. /// as a reference to determine whether the wrapped value is newly added or changed.
/// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now". /// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".
pub fn new( pub fn new(
value: &'w T, value: &'w T,

View File

@ -1280,7 +1280,6 @@ impl<T: TrustedEntityBorrow> IndexMut<RangeToInclusive<usize>> for UniqueEntityS
/// the [`IntoIterator`] impls on it and [`UniqueEntityVec`]. /// the [`IntoIterator`] impls on it and [`UniqueEntityVec`].
/// ///
/// [`iter`]: `UniqueEntitySlice::iter` /// [`iter`]: `UniqueEntitySlice::iter`
/// [`into_iter`]: UniqueEntitySlice::into_iter
pub type Iter<'a, T> = UniqueEntityIter<slice::Iter<'a, T>>; pub type Iter<'a, T> = UniqueEntityIter<slice::Iter<'a, T>>;
impl<'a, T: TrustedEntityBorrow> UniqueEntityIter<slice::Iter<'a, T>> { impl<'a, T: TrustedEntityBorrow> UniqueEntityIter<slice::Iter<'a, T>> {

View File

@ -809,7 +809,7 @@ impl<T: TrustedEntityBorrow> Extend<T> for UniqueEntityVec<T> {
let reserve = if self.is_empty() { let reserve = if self.is_empty() {
iter.size_hint().0 iter.size_hint().0
} else { } else {
(iter.size_hint().0 + 1) / 2 iter.size_hint().0.div_ceil(2)
}; };
self.reserve(reserve); self.reserve(reserve);
// Internal iteration (fold/for_each) is known to result in better code generation // Internal iteration (fold/for_each) is known to result in better code generation
@ -836,7 +836,7 @@ impl<'a, T: TrustedEntityBorrow + Copy + 'a> Extend<&'a T> for UniqueEntityVec<T
let reserve = if self.is_empty() { let reserve = if self.is_empty() {
iter.size_hint().0 iter.size_hint().0
} else { } else {
(iter.size_hint().0 + 1) / 2 iter.size_hint().0.div_ceil(2)
}; };
self.reserve(reserve); self.reserve(reserve);
// Internal iteration (fold/for_each) is known to result in better code generation // Internal iteration (fold/for_each) is known to result in better code generation

View File

@ -73,7 +73,7 @@ use {
/// - [`EventReader`]s that read at least once per update will never drop events. /// - [`EventReader`]s that read at least once per update will never drop events.
/// - [`EventReader`]s that read once within two updates might still receive some events /// - [`EventReader`]s that read once within two updates might still receive some events
/// - [`EventReader`]s that read after two updates are guaranteed to drop all events that occurred /// - [`EventReader`]s that read after two updates are guaranteed to drop all events that occurred
/// before those updates. /// before those updates.
/// ///
/// The buffers in [`Events`] will grow indefinitely if [`update`](Events::update) is never called. /// The buffers in [`Events`] will grow indefinitely if [`update`](Events::update) is never called.
/// ///

View File

@ -2,13 +2,6 @@
unsafe_op_in_unsafe_fn, unsafe_op_in_unsafe_fn,
reason = "See #11590. To be removed once all applicable unsafe code has an unsafe block with a safety comment." reason = "See #11590. To be removed once all applicable unsafe code has an unsafe block with a safety comment."
)] )]
#![cfg_attr(
test,
expect(
dependency_on_unit_never_type_fallback,
reason = "See #17340. To be removed once Edition 2024 is released"
)
)]
#![doc = include_str!("../README.md")] #![doc = include_str!("../README.md")]
#![cfg_attr( #![cfg_attr(
any(docsrs, docsrs_dep), any(docsrs, docsrs_dep),

View File

@ -1115,11 +1115,10 @@ mod tests {
fn observer_despawn() { fn observer_despawn() {
let mut world = World::new(); let mut world = World::new();
let observer = world let system: fn(Trigger<OnAdd, A>) = |_| {
.add_observer(|_: Trigger<OnAdd, A>| { panic!("Observer triggered after being despawned.");
panic!("Observer triggered after being despawned.") };
}) let observer = world.add_observer(system).id();
.id();
world.despawn(observer); world.despawn(observer);
world.spawn(A).flush(); world.spawn(A).flush();
} }
@ -1136,11 +1135,11 @@ mod tests {
res.observed("remove_a"); res.observed("remove_a");
}); });
let observer = world let system: fn(Trigger<OnRemove, B>) = |_: Trigger<OnRemove, B>| {
.add_observer(|_: Trigger<OnRemove, B>| { panic!("Observer triggered after being despawned.");
panic!("Observer triggered after being despawned.") };
})
.flush(); let observer = world.add_observer(system).flush();
world.despawn(observer); world.despawn(observer);
world.despawn(entity); world.despawn(entity);
@ -1166,9 +1165,10 @@ mod tests {
let mut world = World::new(); let mut world = World::new();
world.init_resource::<Order>(); world.init_resource::<Order>();
world let system: fn(Trigger<EventA>) = |_| {
.spawn_empty() panic!("Trigger routed to non-targeted entity.");
.observe(|_: Trigger<EventA>| panic!("Trigger routed to non-targeted entity.")); };
world.spawn_empty().observe(system);
world.add_observer(move |obs: Trigger<EventA>, mut res: ResMut<Order>| { world.add_observer(move |obs: Trigger<EventA>, mut res: ResMut<Order>| {
assert_eq!(obs.target(), Entity::PLACEHOLDER); assert_eq!(obs.target(), Entity::PLACEHOLDER);
res.observed("event_a"); res.observed("event_a");
@ -1187,9 +1187,11 @@ mod tests {
let mut world = World::new(); let mut world = World::new();
world.init_resource::<Order>(); world.init_resource::<Order>();
world let system: fn(Trigger<EventA>) = |_| {
.spawn_empty() panic!("Trigger routed to non-targeted entity.");
.observe(|_: Trigger<EventA>| panic!("Trigger routed to non-targeted entity.")); };
world.spawn_empty().observe(system);
let entity = world let entity = world
.spawn_empty() .spawn_empty()
.observe(|_: Trigger<EventA>, mut res: ResMut<Order>| res.observed("a_1")) .observe(|_: Trigger<EventA>, mut res: ResMut<Order>| res.observed("a_1"))

View File

@ -819,7 +819,7 @@ impl<T: SparseSetIndex> Access<T> {
/// otherwise would allow for queries to be considered disjoint when they shouldn't: /// otherwise would allow for queries to be considered disjoint when they shouldn't:
/// - `Query<(&mut T, Option<&U>)>` read/write `T`, read `U`, with `U` /// - `Query<(&mut T, Option<&U>)>` read/write `T`, read `U`, with `U`
/// - `Query<&mut T, Without<U>>` read/write `T`, without `U` /// - `Query<&mut T, Without<U>>` read/write `T`, without `U`
/// from this we could reasonably conclude that the queries are disjoint but they aren't. /// from this we could reasonably conclude that the queries are disjoint but they aren't.
/// ///
/// In order to solve this the actual access that `Query<(&mut T, Option<&U>)>` has /// In order to solve this the actual access that `Query<(&mut T, Option<&U>)>` has
/// is read/write `T`, read `U`. It must still have a read `U` access otherwise the following /// is read/write `T`, read `U`. It must still have a read `U` access otherwise the following

View File

@ -66,9 +66,7 @@ use variadics_please::all_tuples;
/// # bevy_ecs::system::assert_is_system(my_system); /// # bevy_ecs::system::assert_is_system(my_system);
/// ``` /// ```
/// ///
/// [`matches_component_set`]: Self::matches_component_set
/// [`Query`]: crate::system::Query /// [`Query`]: crate::system::Query
/// [`State`]: Self::State
/// ///
/// # Safety /// # Safety
/// ///

View File

@ -51,9 +51,9 @@ pub(super) union StorageId {
/// ///
/// This data is cached between system runs, and is used to: /// This data is cached between system runs, and is used to:
/// - store metadata about which [`Table`] or [`Archetype`] are matched by the query. "Matched" means /// - store metadata about which [`Table`] or [`Archetype`] are matched by the query. "Matched" means
/// that the query will iterate over the data in the matched table/archetype. /// that the query will iterate over the data in the matched table/archetype.
/// - cache the [`State`] needed to compute the [`Fetch`] struct used to retrieve data /// - cache the [`State`] needed to compute the [`Fetch`] struct used to retrieve data
/// from a specific [`Table`] or [`Archetype`] /// from a specific [`Table`] or [`Archetype`]
/// - build iterators that can iterate over the query results /// - build iterators that can iterate over the query results
/// ///
/// [`State`]: crate::query::world_query::WorldQuery::State /// [`State`]: crate::query::world_query::WorldQuery::State

View File

@ -20,7 +20,7 @@ pub trait ReflectCommandExt {
/// ///
/// - If the entity doesn't exist. /// - If the entity doesn't exist.
/// - If [`AppTypeRegistry`] does not have the reflection data for the given /// - If [`AppTypeRegistry`] does not have the reflection data for the given
/// [`Component`](crate::component::Component) or [`Bundle`](crate::bundle::Bundle). /// [`Component`](crate::component::Component) or [`Bundle`](crate::bundle::Bundle).
/// - If the component or bundle data is invalid. See [`PartialReflect::apply`] for further details. /// - If the component or bundle data is invalid. See [`PartialReflect::apply`] for further details.
/// - If [`AppTypeRegistry`] is not present in the [`World`]. /// - If [`AppTypeRegistry`] is not present in the [`World`].
/// ///
@ -212,7 +212,7 @@ impl<'w> EntityWorldMut<'w> {
/// ///
/// - If the entity has been despawned while this `EntityWorldMut` is still alive. /// - If the entity has been despawned while this `EntityWorldMut` is still alive.
/// - If [`AppTypeRegistry`] does not have the reflection data for the given /// - If [`AppTypeRegistry`] does not have the reflection data for the given
/// [`Component`](crate::component::Component) or [`Bundle`](crate::bundle::Bundle). /// [`Component`](crate::component::Component) or [`Bundle`](crate::bundle::Bundle).
/// - If the component or bundle data is invalid. See [`PartialReflect::apply`] for further details. /// - If the component or bundle data is invalid. See [`PartialReflect::apply`] for further details.
/// - If [`AppTypeRegistry`] is not present in the [`World`]. /// - If [`AppTypeRegistry`] is not present in the [`World`].
/// ///
@ -243,7 +243,7 @@ impl<'w> EntityWorldMut<'w> {
/// ///
/// - If the entity has been despawned while this `EntityWorldMut` is still alive. /// - If the entity has been despawned while this `EntityWorldMut` is still alive.
/// - If the given [`Resource`] does not have the reflection data for the given /// - If the given [`Resource`] does not have the reflection data for the given
/// [`Component`](crate::component::Component) or [`Bundle`](crate::bundle::Bundle). /// [`Component`](crate::component::Component) or [`Bundle`](crate::bundle::Bundle).
/// - If the component or bundle data is invalid. See [`PartialReflect::apply`] for further details. /// - If the component or bundle data is invalid. See [`PartialReflect::apply`] for further details.
/// - If the given [`Resource`] is not present in the [`World`]. /// - If the given [`Resource`] is not present in the [`World`].
pub fn insert_reflect_with_registry<T: Resource + AsRef<TypeRegistry>>( pub fn insert_reflect_with_registry<T: Resource + AsRef<TypeRegistry>>(

View File

@ -276,7 +276,7 @@ pub fn simple_cycles_in_component(graph: &DiGraph, scc: &[NodeId]) -> Vec<Vec<No
stack.clear(); stack.clear();
stack.push((root, subgraph.neighbors(root))); stack.push((root, subgraph.neighbors(root)));
while !stack.is_empty() { while !stack.is_empty() {
let (ref node, successors) = stack.last_mut().unwrap(); let &mut (ref node, ref mut successors) = stack.last_mut().unwrap();
if let Some(next) = successors.next() { if let Some(next) = successors.next() {
if next == root { if next == root {
// found a cycle // found a cycle

View File

@ -1192,7 +1192,7 @@ mod tests {
let mut schedule = Schedule::new(TestSchedule); let mut schedule = Schedule::new(TestSchedule);
schedule schedule
.set_executor_kind($executor) .set_executor_kind($executor)
.add_systems(|| panic!("Executor ignored Stepping")); .add_systems(|| -> () { panic!("Executor ignored Stepping") });
// Add our schedule to stepping & and enable stepping; this should // Add our schedule to stepping & and enable stepping; this should
// prevent any systems in the schedule from running // prevent any systems in the schedule from running

View File

@ -2062,12 +2062,12 @@ mod tests {
let mut world = World::new(); let mut world = World::new();
let mut schedule = Schedule::default(); let mut schedule = Schedule::default();
let system: fn() = || {
panic!("This system must not run");
};
schedule.configure_sets(Set.run_if(|| false)); schedule.configure_sets(Set.run_if(|| false));
schedule.add_systems( schedule.add_systems(system.ambiguous_with(|| ()).in_set(Set));
(|| panic!("This system must not run"))
.ambiguous_with(|| ())
.in_set(Set),
);
schedule.run(&mut world); schedule.run(&mut world);
} }

View File

@ -1348,7 +1348,9 @@ mod tests {
// //
// first system will be configured as `run_if(|| false)`, so it can // first system will be configured as `run_if(|| false)`, so it can
// just panic if called // just panic if called
let first_system = move || panic!("first_system should not be run"); let first_system: fn() = move || {
panic!("first_system should not be run");
};
// The second system, we need to know when it has been called, so we'll // The second system, we need to know when it has been called, so we'll
// add a resource for tracking if it has been run. The system will // add a resource for tracking if it has been run. The system will

View File

@ -76,7 +76,7 @@ impl BlobArray {
/// ///
/// # Safety /// # Safety
/// - The element at index `index` is safe to access. /// - The element at index `index` is safe to access.
/// (If the safety requirements of every method that has been used on `Self` have been fulfilled, the caller just needs to ensure that `index` < `len`) /// (If the safety requirements of every method that has been used on `Self` have been fulfilled, the caller just needs to ensure that `index` < `len`)
/// ///
/// [`Vec::len`]: alloc::vec::Vec::len /// [`Vec::len`]: alloc::vec::Vec::len
#[inline] #[inline]
@ -99,7 +99,7 @@ impl BlobArray {
/// ///
/// # Safety /// # Safety
/// - The element with at index `index` is safe to access. /// - The element with at index `index` is safe to access.
/// (If the safety requirements of every method that has been used on `Self` have been fulfilled, the caller just needs to ensure that `index` < `len`) /// (If the safety requirements of every method that has been used on `Self` have been fulfilled, the caller just needs to ensure that `index` < `len`)
/// ///
/// [`Vec::len`]: alloc::vec::Vec::len /// [`Vec::len`]: alloc::vec::Vec::len
#[inline] #[inline]
@ -156,7 +156,7 @@ impl BlobArray {
/// ///
/// # Safety /// # Safety
/// - For every element with index `i`, if `i` < `len`: It must be safe to call [`Self::get_unchecked_mut`] with `i`. /// - For every element with index `i`, if `i` < `len`: It must be safe to call [`Self::get_unchecked_mut`] with `i`.
/// (If the safety requirements of every method that has been used on `Self` have been fulfilled, the caller just needs to ensure that `len` is correct.) /// (If the safety requirements of every method that has been used on `Self` have been fulfilled, the caller just needs to ensure that `len` is correct.)
/// ///
/// [`Vec::clear`]: alloc::vec::Vec::clear /// [`Vec::clear`]: alloc::vec::Vec::clear
pub unsafe fn clear(&mut self, len: usize) { pub unsafe fn clear(&mut self, len: usize) {
@ -289,7 +289,7 @@ impl BlobArray {
/// # Safety /// # Safety
/// - `index` must be in bounds (`index` < capacity) /// - `index` must be in bounds (`index` < capacity)
/// - The [`Layout`] of the value must match the layout of the blobs stored in this array, /// - The [`Layout`] of the value must match the layout of the blobs stored in this array,
/// and it must be safe to use the `drop` function of this [`BlobArray`] to drop `value`. /// and it must be safe to use the `drop` function of this [`BlobArray`] to drop `value`.
/// - `value` must not point to the same value that is being initialized. /// - `value` must not point to the same value that is being initialized.
#[inline] #[inline]
pub unsafe fn initialize_unchecked(&mut self, index: usize, value: OwningPtr<'_>) { pub unsafe fn initialize_unchecked(&mut self, index: usize, value: OwningPtr<'_>) {
@ -305,7 +305,7 @@ impl BlobArray {
/// # Safety /// # Safety
/// - Index must be in-bounds (`index` < `len`) /// - Index must be in-bounds (`index` < `len`)
/// - `value`'s [`Layout`] must match this [`BlobArray`]'s `item_layout`, /// - `value`'s [`Layout`] must match this [`BlobArray`]'s `item_layout`,
/// and it must be safe to use the `drop` function of this [`BlobArray`] to drop `value`. /// and it must be safe to use the `drop` function of this [`BlobArray`] to drop `value`.
/// - `value` must not point to the same value that is being replaced. /// - `value` must not point to the same value that is being replaced.
pub unsafe fn replace_unchecked(&mut self, index: usize, value: OwningPtr<'_>) { pub unsafe fn replace_unchecked(&mut self, index: usize, value: OwningPtr<'_>) {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]

View File

@ -176,7 +176,7 @@ impl BlobVec {
/// # Safety /// # Safety
/// - index must be in bounds /// - index must be in bounds
/// - the memory in the [`BlobVec`] starting at index `index`, of a size matching this [`BlobVec`]'s /// - the memory in the [`BlobVec`] starting at index `index`, of a size matching this [`BlobVec`]'s
/// `item_layout`, must have been previously allocated. /// `item_layout`, must have been previously allocated.
#[inline] #[inline]
pub unsafe fn initialize_unchecked(&mut self, index: usize, value: OwningPtr<'_>) { pub unsafe fn initialize_unchecked(&mut self, index: usize, value: OwningPtr<'_>) {
debug_assert!(index < self.len()); debug_assert!(index < self.len());
@ -189,10 +189,10 @@ impl BlobVec {
/// # Safety /// # Safety
/// - index must be in-bounds /// - index must be in-bounds
/// - the memory in the [`BlobVec`] starting at index `index`, of a size matching this /// - the memory in the [`BlobVec`] starting at index `index`, of a size matching this
/// [`BlobVec`]'s `item_layout`, must have been previously initialized with an item matching /// [`BlobVec`]'s `item_layout`, must have been previously initialized with an item matching
/// this [`BlobVec`]'s `item_layout` /// this [`BlobVec`]'s `item_layout`
/// - the memory at `*value` must also be previously initialized with an item matching this /// - the memory at `*value` must also be previously initialized with an item matching this
/// [`BlobVec`]'s `item_layout` /// [`BlobVec`]'s `item_layout`
pub unsafe fn replace_unchecked(&mut self, index: usize, value: OwningPtr<'_>) { pub unsafe fn replace_unchecked(&mut self, index: usize, value: OwningPtr<'_>) {
debug_assert!(index < self.len()); debug_assert!(index < self.len());

View File

@ -82,7 +82,6 @@ use crate::{
/// // NOTE: type inference fails here, so annotations are required on the closure. /// // NOTE: type inference fails here, so annotations are required on the closure.
/// commands.queue(|w: &mut World| { /// commands.queue(|w: &mut World| {
/// // Mutate the world however you want... /// // Mutate the world however you want...
/// # todo!();
/// }); /// });
/// # } /// # }
/// ``` /// ```

View File

@ -1648,7 +1648,10 @@ mod tests {
#[should_panic] #[should_panic]
fn panic_inside_system() { fn panic_inside_system() {
let mut world = World::new(); let mut world = World::new();
run_system(&mut world, || panic!("this system panics")); let system: fn() = || {
panic!("this system panics");
};
run_system(&mut world, system);
} }
#[test] #[test]

View File

@ -105,7 +105,7 @@ impl<'w> EntityRef<'w> {
/// ///
/// - If you know the concrete type of the component, you should prefer [`Self::contains`]. /// - If you know the concrete type of the component, you should prefer [`Self::contains`].
/// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using
/// [`Self::contains_type_id`]. /// [`Self::contains_type_id`].
#[inline] #[inline]
pub fn contains_id(&self, component_id: ComponentId) -> bool { pub fn contains_id(&self, component_id: ComponentId) -> bool {
self.cell.contains_id(component_id) self.cell.contains_id(component_id)
@ -510,7 +510,7 @@ impl<'w> EntityMut<'w> {
/// ///
/// - If you know the concrete type of the component, you should prefer [`Self::contains`]. /// - If you know the concrete type of the component, you should prefer [`Self::contains`].
/// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using
/// [`Self::contains_type_id`]. /// [`Self::contains_type_id`].
#[inline] #[inline]
pub fn contains_id(&self, component_id: ComponentId) -> bool { pub fn contains_id(&self, component_id: ComponentId) -> bool {
self.cell.contains_id(component_id) self.cell.contains_id(component_id)
@ -1134,7 +1134,7 @@ impl<'w> EntityWorldMut<'w> {
/// ///
/// - If you know the concrete type of the component, you should prefer [`Self::contains`]. /// - If you know the concrete type of the component, you should prefer [`Self::contains`].
/// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using
/// [`Self::contains_type_id`]. /// [`Self::contains_type_id`].
/// ///
/// # Panics /// # Panics
/// ///
@ -3052,7 +3052,7 @@ impl<'w> FilteredEntityRef<'w> {
/// # Safety /// # Safety
/// - No `&mut World` can exist from the underlying `UnsafeWorldCell` /// - No `&mut World` can exist from the underlying `UnsafeWorldCell`
/// - If `access` takes read access to a component no mutable reference to that /// - If `access` takes read access to a component no mutable reference to that
/// component can exist at the same time as the returned [`FilteredEntityMut`] /// component can exist at the same time as the returned [`FilteredEntityMut`]
/// - If `access` takes any access for a component `entity` must have that component. /// - If `access` takes any access for a component `entity` must have that component.
#[inline] #[inline]
pub(crate) unsafe fn new(entity: UnsafeEntityCell<'w>, access: Access<ComponentId>) -> Self { pub(crate) unsafe fn new(entity: UnsafeEntityCell<'w>, access: Access<ComponentId>) -> Self {
@ -3103,7 +3103,7 @@ impl<'w> FilteredEntityRef<'w> {
/// ///
/// - If you know the concrete type of the component, you should prefer [`Self::contains`]. /// - If you know the concrete type of the component, you should prefer [`Self::contains`].
/// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using
/// [`Self::contains_type_id`]. /// [`Self::contains_type_id`].
#[inline] #[inline]
pub fn contains_id(&self, component_id: ComponentId) -> bool { pub fn contains_id(&self, component_id: ComponentId) -> bool {
self.entity.contains_id(component_id) self.entity.contains_id(component_id)
@ -3382,9 +3382,9 @@ impl<'w> FilteredEntityMut<'w> {
/// # Safety /// # Safety
/// - No `&mut World` can exist from the underlying `UnsafeWorldCell` /// - No `&mut World` can exist from the underlying `UnsafeWorldCell`
/// - If `access` takes read access to a component no mutable reference to that /// - If `access` takes read access to a component no mutable reference to that
/// component can exist at the same time as the returned [`FilteredEntityMut`] /// component can exist at the same time as the returned [`FilteredEntityMut`]
/// - If `access` takes write access to a component, no reference to that component /// - If `access` takes write access to a component, no reference to that component
/// may exist at the same time as the returned [`FilteredEntityMut`] /// may exist at the same time as the returned [`FilteredEntityMut`]
/// - If `access` takes any access for a component `entity` must have that component. /// - If `access` takes any access for a component `entity` must have that component.
#[inline] #[inline]
pub(crate) unsafe fn new(entity: UnsafeEntityCell<'w>, access: Access<ComponentId>) -> Self { pub(crate) unsafe fn new(entity: UnsafeEntityCell<'w>, access: Access<ComponentId>) -> Self {
@ -3448,7 +3448,7 @@ impl<'w> FilteredEntityMut<'w> {
/// ///
/// - If you know the concrete type of the component, you should prefer [`Self::contains`]. /// - If you know the concrete type of the component, you should prefer [`Self::contains`].
/// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using
/// [`Self::contains_type_id`]. /// [`Self::contains_type_id`].
#[inline] #[inline]
pub fn contains_id(&self, component_id: ComponentId) -> bool { pub fn contains_id(&self, component_id: ComponentId) -> bool {
self.entity.contains_id(component_id) self.entity.contains_id(component_id)
@ -3812,7 +3812,7 @@ where
/// ///
/// - If you know the concrete type of the component, you should prefer [`Self::contains`]. /// - If you know the concrete type of the component, you should prefer [`Self::contains`].
/// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using
/// [`Self::contains_type_id`]. /// [`Self::contains_type_id`].
#[inline] #[inline]
pub fn contains_id(&self, component_id: ComponentId) -> bool { pub fn contains_id(&self, component_id: ComponentId) -> bool {
self.entity.contains_id(component_id) self.entity.contains_id(component_id)
@ -4037,7 +4037,7 @@ where
/// ///
/// - If you know the concrete type of the component, you should prefer [`Self::contains`]. /// - If you know the concrete type of the component, you should prefer [`Self::contains`].
/// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using
/// [`Self::contains_type_id`]. /// [`Self::contains_type_id`].
#[inline] #[inline]
pub fn contains_id(&self, component_id: ComponentId) -> bool { pub fn contains_id(&self, component_id: ComponentId) -> bool {
self.entity.contains_id(component_id) self.entity.contains_id(component_id)
@ -4146,7 +4146,7 @@ where
/// # Safety /// # Safety
/// ///
/// - [`OwningPtr`] and [`StorageType`] iterators must correspond to the /// - [`OwningPtr`] and [`StorageType`] iterators must correspond to the
/// [`BundleInfo`] used to construct [`BundleInserter`] /// [`BundleInfo`] used to construct [`BundleInserter`]
/// - [`Entity`] must correspond to [`EntityLocation`] /// - [`Entity`] must correspond to [`EntityLocation`]
unsafe fn insert_dynamic_bundle< unsafe fn insert_dynamic_bundle<
'a, 'a,

View File

@ -748,7 +748,7 @@ impl<'w> UnsafeEntityCell<'w> {
/// ///
/// - If you know the concrete type of the component, you should prefer [`Self::contains`]. /// - If you know the concrete type of the component, you should prefer [`Self::contains`].
/// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using
/// [`Self::contains_type_id`]. /// [`Self::contains_type_id`].
#[inline] #[inline]
pub fn contains_id(self, component_id: ComponentId) -> bool { pub fn contains_id(self, component_id: ComponentId) -> bool {
self.archetype().contains(component_id) self.archetype().contains(component_id)
@ -1125,7 +1125,7 @@ impl<'w> UnsafeWorldCell<'w> {
/// ///
/// # Safety /// # Safety
/// - `location` must refer to an archetype that contains `entity` /// - `location` must refer to an archetype that contains `entity`
/// the archetype /// the archetype
/// - `component_id` must be valid /// - `component_id` must be valid
/// - `storage_type` must accurately reflect where the components for `component_id` are stored. /// - `storage_type` must accurately reflect where the components for `component_id` are stored.
/// - the caller must ensure that no aliasing rules are violated /// - the caller must ensure that no aliasing rules are violated
@ -1195,7 +1195,7 @@ unsafe fn get_component_and_ticks(
/// ///
/// # Safety /// # Safety
/// - `location` must refer to an archetype that contains `entity` /// - `location` must refer to an archetype that contains `entity`
/// the archetype /// the archetype
/// - `component_id` must be valid /// - `component_id` must be valid
/// - `storage_type` must accurately reflect where the components for `component_id` are stored. /// - `storage_type` must accurately reflect where the components for `component_id` are stored.
/// - the caller must ensure that no aliasing rules are violated /// - the caller must ensure that no aliasing rules are violated

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_encase_derive" name = "bevy_encase_derive"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Bevy derive macro for encase" description = "Bevy derive macro for encase"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_gilrs" name = "bevy_gilrs"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Gamepad system made using Gilrs for Bevy Engine" description = "Gamepad system made using Gilrs for Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_gizmos" name = "bevy_gizmos"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Provides gizmos for Bevy Engine" description = "Provides gizmos for Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_gizmos_macros" name = "bevy_gizmos_macros"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Derive implementations for bevy_gizmos" description = "Derive implementations for bevy_gizmos"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -136,11 +136,11 @@ where
/// ///
/// # Arguments /// # Arguments
/// - `angle`: sets how much of a circle circumference is passed, e.g. PI is half a circle. This /// - `angle`: sets how much of a circle circumference is passed, e.g. PI is half a circle. This
/// value should be in the range (-2 * PI..=2 * PI) /// value should be in the range (-2 * PI..=2 * PI)
/// - `radius`: distance between the arc and its center point /// - `radius`: distance between the arc and its center point
/// - `isometry` defines the translation and rotation of the arc. /// - `isometry` defines the translation and rotation of the arc.
/// - the translation specifies the center of the arc /// - the translation specifies the center of the arc
/// - the rotation is counter-clockwise starting from `Vec3::Y` /// - the rotation is counter-clockwise starting from `Vec3::Y`
/// - `color`: color of the arc /// - `color`: color of the arc
/// ///
/// # Builder methods /// # Builder methods
@ -219,10 +219,10 @@ where
/// ///
/// # Notes /// # Notes
/// - This method assumes that the points `from` and `to` are distinct from `center`. If one of /// - This method assumes that the points `from` and `to` are distinct from `center`. If one of
/// the points is coincident with `center`, nothing is rendered. /// the points is coincident with `center`, nothing is rendered.
/// - The arc is drawn as a portion of a circle with a radius equal to the distance from the /// - The arc is drawn as a portion of a circle with a radius equal to the distance from the
/// `center` to `from`. If the distance from `center` to `to` is not equal to the radius, then /// `center` to `from`. If the distance from `center` to `to` is not equal to the radius, then
/// the results will behave as if this were the case /// the results will behave as if this were the case
#[inline] #[inline]
pub fn short_arc_3d_between( pub fn short_arc_3d_between(
&mut self, &mut self,
@ -265,10 +265,10 @@ where
/// ///
/// # Notes /// # Notes
/// - This method assumes that the points `from` and `to` are distinct from `center`. If one of /// - This method assumes that the points `from` and `to` are distinct from `center`. If one of
/// the points is coincident with `center`, nothing is rendered. /// the points is coincident with `center`, nothing is rendered.
/// - The arc is drawn as a portion of a circle with a radius equal to the distance from the /// - The arc is drawn as a portion of a circle with a radius equal to the distance from the
/// `center` to `from`. If the distance from `center` to `to` is not equal to the radius, then /// `center` to `from`. If the distance from `center` to `to` is not equal to the radius, then
/// the results will behave as if this were the case. /// the results will behave as if this were the case.
#[inline] #[inline]
pub fn long_arc_3d_between( pub fn long_arc_3d_between(
&mut self, &mut self,
@ -352,10 +352,10 @@ where
/// ///
/// # Notes /// # Notes
/// - This method assumes that the points `from` and `to` are distinct from `center`. If one of /// - This method assumes that the points `from` and `to` are distinct from `center`. If one of
/// the points is coincident with `center`, nothing is rendered. /// the points is coincident with `center`, nothing is rendered.
/// - The arc is drawn as a portion of a circle with a radius equal to the distance from the /// - The arc is drawn as a portion of a circle with a radius equal to the distance from the
/// `center` to `from`. If the distance from `center` to `to` is not equal to the radius, then /// `center` to `from`. If the distance from `center` to `to` is not equal to the radius, then
/// the results will behave as if this were the case /// the results will behave as if this were the case
#[inline] #[inline]
pub fn short_arc_2d_between( pub fn short_arc_2d_between(
&mut self, &mut self,
@ -398,10 +398,10 @@ where
/// ///
/// # Notes /// # Notes
/// - This method assumes that the points `from` and `to` are distinct from `center`. If one of /// - This method assumes that the points `from` and `to` are distinct from `center`. If one of
/// the points is coincident with `center`, nothing is rendered. /// the points is coincident with `center`, nothing is rendered.
/// - The arc is drawn as a portion of a circle with a radius equal to the distance from the /// - The arc is drawn as a portion of a circle with a radius equal to the distance from the
/// `center` to `from`. If the distance from `center` to `to` is not equal to the radius, then /// `center` to `from`. If the distance from `center` to `to` is not equal to the radius, then
/// the results will behave as if this were the case. /// the results will behave as if this were the case.
#[inline] #[inline]
pub fn long_arc_2d_between( pub fn long_arc_2d_between(
&mut self, &mut self,

View File

@ -820,8 +820,7 @@ where
let polymorphic_color: Color = color.into(); let polymorphic_color: Color = color.into();
let linear_color = LinearRgba::from(polymorphic_color); let linear_color = LinearRgba::from(polymorphic_color);
self.list_colors self.list_colors.extend(iter::repeat_n(linear_color, count));
.extend(iter::repeat(linear_color).take(count));
} }
#[inline] #[inline]

View File

@ -186,10 +186,9 @@ where
/// # Arguments /// # Arguments
/// ///
/// - `isometry` defines the translation and rotation of the grid. /// - `isometry` defines the translation and rotation of the grid.
/// - the translation specifies the center of the grid /// - the translation specifies the center of the grid
/// - defines the orientation of the grid, by default /// - defines the orientation of the grid, by default we assume the grid is contained in a
/// we assume the grid is contained in a plane parallel /// plane parallel to the XY plane
/// to the XY plane
/// - `cell_count`: defines the amount of cells in the x and y axes /// - `cell_count`: defines the amount of cells in the x and y axes
/// - `spacing`: defines the distance between cells along the x and y axes /// - `spacing`: defines the distance between cells along the x and y axes
/// - `color`: color of the grid /// - `color`: color of the grid
@ -241,9 +240,8 @@ where
/// # Arguments /// # Arguments
/// ///
/// - `isometry` defines the translation and rotation of the grid. /// - `isometry` defines the translation and rotation of the grid.
/// - the translation specifies the center of the grid /// - the translation specifies the center of the grid
/// - defines the orientation of the grid, by default /// - defines the orientation of the grid, by default we assume the grid is aligned with all axes
/// we assume the grid is aligned with all axes
/// - `cell_count`: defines the amount of cells in the x, y and z axes /// - `cell_count`: defines the amount of cells in the x, y and z axes
/// - `spacing`: defines the distance between cells along the x, y and z axes /// - `spacing`: defines the distance between cells along the x, y and z axes
/// - `color`: color of the grid /// - `color`: color of the grid
@ -295,9 +293,8 @@ where
/// # Arguments /// # Arguments
/// ///
/// - `isometry` defines the translation and rotation of the grid. /// - `isometry` defines the translation and rotation of the grid.
/// - the translation specifies the center of the grid /// - the translation specifies the center of the grid
/// - defines the orientation of the grid, by default /// - defines the orientation of the grid, by default we assume the grid is aligned with all axes
/// we assume the grid is aligned with all axes
/// - `cell_count`: defines the amount of cells in the x and y axes /// - `cell_count`: defines the amount of cells in the x and y axes
/// - `spacing`: defines the distance between cells along the x and y axes /// - `spacing`: defines the distance between cells along the x and y axes
/// - `color`: color of the grid /// - `color`: color of the grid

View File

@ -238,10 +238,9 @@ where
/// # Arguments /// # Arguments
/// ///
/// - `isometry` defines the translation and rotation of the rectangle. /// - `isometry` defines the translation and rotation of the rectangle.
/// - the translation specifies the center of the rectangle /// - the translation specifies the center of the rectangle
/// - defines orientation of the rectangle, by default we /// - defines orientation of the rectangle, by default we assume the rectangle is contained in
/// assume the rectangle is contained in a plane parallel /// a plane parallel to the XY plane.
/// to the XY plane.
/// - `size`: defines the size of the rectangle. This refers to the 'outer size', similar to a bounding box. /// - `size`: defines the size of the rectangle. This refers to the 'outer size', similar to a bounding box.
/// - `color`: color of the rectangle /// - `color`: color of the rectangle
/// ///
@ -249,7 +248,7 @@ where
/// ///
/// - The corner radius can be adjusted with the `.corner_radius(...)` method. /// - The corner radius can be adjusted with the `.corner_radius(...)` method.
/// - The resolution of the arcs at each corner (i.e. the level of detail) can be adjusted with the /// - The resolution of the arcs at each corner (i.e. the level of detail) can be adjusted with the
/// `.arc_resolution(...)` method. /// `.arc_resolution(...)` method.
/// ///
/// # Example /// # Example
/// ``` /// ```
@ -293,9 +292,8 @@ where
/// # Arguments /// # Arguments
/// ///
/// - `isometry` defines the translation and rotation of the rectangle. /// - `isometry` defines the translation and rotation of the rectangle.
/// - the translation specifies the center of the rectangle /// - the translation specifies the center of the rectangle
/// - defines orientation of the rectangle, by default we /// - defines orientation of the rectangle, by default we assume the rectangle aligned with all axes.
/// assume the rectangle aligned with all axes.
/// - `size`: defines the size of the rectangle. This refers to the 'outer size', similar to a bounding box. /// - `size`: defines the size of the rectangle. This refers to the 'outer size', similar to a bounding box.
/// - `color`: color of the rectangle /// - `color`: color of the rectangle
/// ///
@ -303,7 +301,7 @@ where
/// ///
/// - The corner radius can be adjusted with the `.corner_radius(...)` method. /// - The corner radius can be adjusted with the `.corner_radius(...)` method.
/// - The resolution of the arcs at each corner (i.e. the level of detail) can be adjusted with the /// - The resolution of the arcs at each corner (i.e. the level of detail) can be adjusted with the
/// `.arc_resolution(...)` method. /// `.arc_resolution(...)` method.
/// ///
/// # Example /// # Example
/// ``` /// ```
@ -351,9 +349,8 @@ where
/// # Arguments /// # Arguments
/// ///
/// - `isometry` defines the translation and rotation of the cuboid. /// - `isometry` defines the translation and rotation of the cuboid.
/// - the translation specifies the center of the cuboid /// - the translation specifies the center of the cuboid
/// - defines orientation of the cuboid, by default we /// - defines orientation of the cuboid, by default we assume the cuboid aligned with all axes.
/// assume the cuboid aligned with all axes.
/// - `size`: defines the size of the cuboid. This refers to the 'outer size', similar to a bounding box. /// - `size`: defines the size of the cuboid. This refers to the 'outer size', similar to a bounding box.
/// - `color`: color of the cuboid /// - `color`: color of the cuboid
/// ///
@ -361,7 +358,7 @@ where
/// ///
/// - The edge radius can be adjusted with the `.edge_radius(...)` method. /// - The edge radius can be adjusted with the `.edge_radius(...)` method.
/// - The resolution of the arcs at each edge (i.e. the level of detail) can be adjusted with the /// - The resolution of the arcs at each edge (i.e. the level of detail) can be adjusted with the
/// `.arc_resolution(...)` method. /// `.arc_resolution(...)` method.
/// ///
/// # Example /// # Example
/// ``` /// ```

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_gltf" name = "bevy_gltf"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Bevy Engine GLTF loading" description = "Bevy Engine GLTF loading"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_image" name = "bevy_image"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Provides image types for Bevy Engine" description = "Provides image types for Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_input" name = "bevy_input"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Provides input functionality for Bevy Engine" description = "Provides input functionality for Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -1,13 +1,13 @@
[package] [package]
name = "bevy_input_focus" name = "bevy_input_focus"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Keyboard focus management" description = "Keyboard focus management"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
keywords = ["bevy"] keywords = ["bevy"]
rust-version = "1.83.0" rust-version = "1.85.0"
[features] [features]
default = ["std", "bevy_reflect", "bevy_ecs/async_executor"] default = ["std", "bevy_reflect", "bevy_ecs/async_executor"]

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_internal" name = "bevy_internal"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "An internal Bevy crate used to facilitate optional dynamic linking via the 'dynamic_linking' feature" description = "An internal Bevy crate used to facilitate optional dynamic linking via the 'dynamic_linking' feature"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_log" name = "bevy_log"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Provides logging for Bevy Engine" description = "Provides logging for Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -80,11 +80,11 @@ pub(crate) struct FlushGuard(SyncCell<tracing_chrome::FlushGuard>);
/// Adds logging to Apps. This plugin is part of the `DefaultPlugins`. Adding /// Adds logging to Apps. This plugin is part of the `DefaultPlugins`. Adding
/// this plugin will setup a collector appropriate to your target platform: /// this plugin will setup a collector appropriate to your target platform:
/// * Using [`tracing-subscriber`](https://crates.io/crates/tracing-subscriber) by default, /// * Using [`tracing-subscriber`](https://crates.io/crates/tracing-subscriber) by default,
/// logging to `stdout`. /// logging to `stdout`.
/// * Using [`android_log-sys`](https://crates.io/crates/android_log-sys) on Android, /// * Using [`android_log-sys`](https://crates.io/crates/android_log-sys) on Android,
/// logging to Android logs. /// logging to Android logs.
/// * Using [`tracing-wasm`](https://crates.io/crates/tracing-wasm) in Wasm, logging /// * Using [`tracing-wasm`](https://crates.io/crates/tracing-wasm) in Wasm, logging
/// to the browser console. /// to the browser console.
/// ///
/// You can configure this plugin. /// You can configure this plugin.
/// ```no_run /// ```no_run
@ -117,7 +117,10 @@ pub(crate) struct FlushGuard(SyncCell<tracing_chrome::FlushGuard>);
/// # use bevy_app::{App, NoopPluginGroup as DefaultPlugins, PluginGroup}; /// # use bevy_app::{App, NoopPluginGroup as DefaultPlugins, PluginGroup};
/// # use bevy_log::LogPlugin; /// # use bevy_log::LogPlugin;
/// fn main() { /// fn main() {
/// # // SAFETY: Single-threaded
/// # unsafe {
/// std::env::set_var("NO_COLOR", "1"); /// std::env::set_var("NO_COLOR", "1");
/// # }
/// App::new() /// App::new()
/// .add_plugins(DefaultPlugins) /// .add_plugins(DefaultPlugins)
/// .run(); /// .run();

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_macro_utils" name = "bevy_macro_utils"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "A collection of utils for Bevy Engine" description = "A collection of utils for Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -1,13 +1,13 @@
[package] [package]
name = "bevy_math" name = "bevy_math"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Provides math functionality for Bevy Engine" description = "Provides math functionality for Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
keywords = ["bevy"] keywords = ["bevy"]
rust-version = "1.83.0" rust-version = "1.85.0"
[dependencies] [dependencies]
glam = { version = "0.29", default-features = false, features = ["bytemuck"] } glam = { version = "0.29", default-features = false, features = ["bytemuck"] }

View File

@ -746,10 +746,9 @@ impl<P: VectorSpace> CubicNurbs<P> {
} }
let last_knots_value = control_points - 3; let last_knots_value = control_points - 3;
Some( Some(
core::iter::repeat(0.0) core::iter::repeat_n(0.0, 4)
.take(4)
.chain((1..last_knots_value).map(|v| v as f32)) .chain((1..last_knots_value).map(|v| v as f32))
.chain(core::iter::repeat(last_knots_value as f32).take(4)) .chain(core::iter::repeat_n(last_knots_value as f32, 4))
.collect(), .collect(),
) )
} }

View File

@ -234,7 +234,7 @@ impl ShapeSample for Rectangle {
fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec2 { fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec2 {
let primary_side = rng.gen_range(-1.0..1.0); let primary_side = rng.gen_range(-1.0..1.0);
let other_side = if rng.gen() { -1.0 } else { 1.0 }; let other_side = if rng.r#gen() { -1.0 } else { 1.0 };
if self.half_size.x + self.half_size.y > 0.0 { if self.half_size.x + self.half_size.y > 0.0 {
if rng.gen_bool((self.half_size.x / (self.half_size.x + self.half_size.y)) as f64) { if rng.gen_bool((self.half_size.x / (self.half_size.x + self.half_size.y)) as f64) {
@ -261,7 +261,7 @@ impl ShapeSample for Cuboid {
fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3 { fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3 {
let primary_side1 = rng.gen_range(-1.0..1.0); let primary_side1 = rng.gen_range(-1.0..1.0);
let primary_side2 = rng.gen_range(-1.0..1.0); let primary_side2 = rng.gen_range(-1.0..1.0);
let other_side = if rng.gen() { -1.0 } else { 1.0 }; let other_side = if rng.r#gen() { -1.0 } else { 1.0 };
if let Ok(dist) = WeightedIndex::new([ if let Ok(dist) = WeightedIndex::new([
self.half_size.y * self.half_size.z, self.half_size.y * self.half_size.z,
@ -425,7 +425,7 @@ impl ShapeSample for Cylinder {
if self.radius + 2.0 * self.half_height > 0.0 { if self.radius + 2.0 * self.half_height > 0.0 {
if rng.gen_bool((self.radius / (self.radius + 2.0 * self.half_height)) as f64) { if rng.gen_bool((self.radius / (self.radius + 2.0 * self.half_height)) as f64) {
let Vec2 { x, y: z } = self.base().sample_interior(rng); let Vec2 { x, y: z } = self.base().sample_interior(rng);
if rng.gen() { if rng.r#gen() {
Vec3::new(x, self.half_height, z) Vec3::new(x, self.half_height, z)
} else { } else {
Vec3::new(x, -self.half_height, z) Vec3::new(x, -self.half_height, z)

View File

@ -12,7 +12,7 @@
//! let random_direction1: Dir3 = random(); //! let random_direction1: Dir3 = random();
//! //!
//! // Random direction using the rng constructed above //! // Random direction using the rng constructed above
//! let random_direction2: Dir3 = rng.gen(); //! let random_direction2: Dir3 = rng.r#gen();
//! //!
//! // The same as the previous but with different syntax //! // The same as the previous but with different syntax
//! let random_direction3 = Dir3::from_rng(&mut rng); //! let random_direction3 = Dir3::from_rng(&mut rng);
@ -49,7 +49,7 @@ where
{ {
/// Construct a value of this type uniformly at random using `rng` as the source of randomness. /// Construct a value of this type uniformly at random using `rng` as the source of randomness.
fn from_rng<R: Rng + ?Sized>(rng: &mut R) -> Self { fn from_rng<R: Rng + ?Sized>(rng: &mut R) -> Self {
rng.gen() rng.r#gen()
} }
} }

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_mesh" name = "bevy_mesh"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Provides mesh types for Bevy Engine" description = "Provides mesh types for Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -85,25 +85,25 @@ pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;
/// ## Common points of confusion /// ## Common points of confusion
/// ///
/// - UV maps in Bevy start at the top-left, see [`ATTRIBUTE_UV_0`](Mesh::ATTRIBUTE_UV_0), /// - UV maps in Bevy start at the top-left, see [`ATTRIBUTE_UV_0`](Mesh::ATTRIBUTE_UV_0),
/// other APIs can have other conventions, `OpenGL` starts at bottom-left. /// other APIs can have other conventions, `OpenGL` starts at bottom-left.
/// - It is possible and sometimes useful for multiple vertices to have the same /// - It is possible and sometimes useful for multiple vertices to have the same
/// [position attribute](Mesh::ATTRIBUTE_POSITION) value, /// [position attribute](Mesh::ATTRIBUTE_POSITION) value,
/// it's a common technique in 3D modeling for complex UV mapping or other calculations. /// it's a common technique in 3D modeling for complex UV mapping or other calculations.
/// - Bevy performs frustum culling based on the `Aabb` of meshes, which is calculated /// - Bevy performs frustum culling based on the `Aabb` of meshes, which is calculated
/// and added automatically for new meshes only. If a mesh is modified, the entity's `Aabb` /// and added automatically for new meshes only. If a mesh is modified, the entity's `Aabb`
/// needs to be updated manually or deleted so that it is re-calculated. /// needs to be updated manually or deleted so that it is re-calculated.
/// ///
/// ## Use with `StandardMaterial` /// ## Use with `StandardMaterial`
/// ///
/// To render correctly with `StandardMaterial`, a mesh needs to have properly defined: /// To render correctly with `StandardMaterial`, a mesh needs to have properly defined:
/// - [`UVs`](Mesh::ATTRIBUTE_UV_0): Bevy needs to know how to map a texture onto the mesh /// - [`UVs`](Mesh::ATTRIBUTE_UV_0): Bevy needs to know how to map a texture onto the mesh
/// (also true for `ColorMaterial`). /// (also true for `ColorMaterial`).
/// - [`Normals`](Mesh::ATTRIBUTE_NORMAL): Bevy needs to know how light interacts with your mesh. /// - [`Normals`](Mesh::ATTRIBUTE_NORMAL): Bevy needs to know how light interacts with your mesh.
/// [0.0, 0.0, 1.0] is very common for simple flat meshes on the XY plane, /// [0.0, 0.0, 1.0] is very common for simple flat meshes on the XY plane,
/// because simple meshes are smooth and they don't require complex light calculations. /// because simple meshes are smooth and they don't require complex light calculations.
/// - Vertex winding order: by default, `StandardMaterial.cull_mode` is `Some(Face::Back)`, /// - Vertex winding order: by default, `StandardMaterial.cull_mode` is `Some(Face::Back)`,
/// which means that Bevy would *only* render the "front" of each triangle, which /// which means that Bevy would *only* render the "front" of each triangle, which
/// is the side of the triangle from where the vertices appear in a *counter-clockwise* order. /// is the side of the triangle from where the vertices appear in a *counter-clockwise* order.
#[derive(Asset, Debug, Clone, Reflect)] #[derive(Asset, Debug, Clone, Reflect)]
pub struct Mesh { pub struct Mesh {
#[reflect(ignore)] #[reflect(ignore)]
@ -881,7 +881,7 @@ impl Mesh {
"mesh transform scale cannot be zero on more than one axis" "mesh transform scale cannot be zero on more than one axis"
); );
if let Some(VertexAttributeValues::Float32x3(ref mut positions)) = if let Some(VertexAttributeValues::Float32x3(positions)) =
self.attribute_mut(Mesh::ATTRIBUTE_POSITION) self.attribute_mut(Mesh::ATTRIBUTE_POSITION)
{ {
// Apply scale, rotation, and translation to vertex positions // Apply scale, rotation, and translation to vertex positions
@ -898,7 +898,7 @@ impl Mesh {
return; return;
} }
if let Some(VertexAttributeValues::Float32x3(ref mut normals)) = if let Some(VertexAttributeValues::Float32x3(normals)) =
self.attribute_mut(Mesh::ATTRIBUTE_NORMAL) self.attribute_mut(Mesh::ATTRIBUTE_NORMAL)
{ {
// Transform normals, taking into account non-uniform scaling and rotation // Transform normals, taking into account non-uniform scaling and rotation
@ -909,7 +909,7 @@ impl Mesh {
}); });
} }
if let Some(VertexAttributeValues::Float32x3(ref mut tangents)) = if let Some(VertexAttributeValues::Float32x3(tangents)) =
self.attribute_mut(Mesh::ATTRIBUTE_TANGENT) self.attribute_mut(Mesh::ATTRIBUTE_TANGENT)
{ {
// Transform tangents, taking into account non-uniform scaling and rotation // Transform tangents, taking into account non-uniform scaling and rotation
@ -936,7 +936,7 @@ impl Mesh {
return; return;
} }
if let Some(VertexAttributeValues::Float32x3(ref mut positions)) = if let Some(VertexAttributeValues::Float32x3(positions)) =
self.attribute_mut(Mesh::ATTRIBUTE_POSITION) self.attribute_mut(Mesh::ATTRIBUTE_POSITION)
{ {
// Apply translation to vertex positions // Apply translation to vertex positions
@ -958,7 +958,7 @@ impl Mesh {
/// ///
/// `Aabb` of entities with modified mesh are not updated automatically. /// `Aabb` of entities with modified mesh are not updated automatically.
pub fn rotate_by(&mut self, rotation: Quat) { pub fn rotate_by(&mut self, rotation: Quat) {
if let Some(VertexAttributeValues::Float32x3(ref mut positions)) = if let Some(VertexAttributeValues::Float32x3(positions)) =
self.attribute_mut(Mesh::ATTRIBUTE_POSITION) self.attribute_mut(Mesh::ATTRIBUTE_POSITION)
{ {
// Apply rotation to vertex positions // Apply rotation to vertex positions
@ -972,7 +972,7 @@ impl Mesh {
return; return;
} }
if let Some(VertexAttributeValues::Float32x3(ref mut normals)) = if let Some(VertexAttributeValues::Float32x3(normals)) =
self.attribute_mut(Mesh::ATTRIBUTE_NORMAL) self.attribute_mut(Mesh::ATTRIBUTE_NORMAL)
{ {
// Transform normals // Transform normals
@ -981,7 +981,7 @@ impl Mesh {
}); });
} }
if let Some(VertexAttributeValues::Float32x3(ref mut tangents)) = if let Some(VertexAttributeValues::Float32x3(tangents)) =
self.attribute_mut(Mesh::ATTRIBUTE_TANGENT) self.attribute_mut(Mesh::ATTRIBUTE_TANGENT)
{ {
// Transform tangents // Transform tangents
@ -1010,7 +1010,7 @@ impl Mesh {
"mesh transform scale cannot be zero on more than one axis" "mesh transform scale cannot be zero on more than one axis"
); );
if let Some(VertexAttributeValues::Float32x3(ref mut positions)) = if let Some(VertexAttributeValues::Float32x3(positions)) =
self.attribute_mut(Mesh::ATTRIBUTE_POSITION) self.attribute_mut(Mesh::ATTRIBUTE_POSITION)
{ {
// Apply scale to vertex positions // Apply scale to vertex positions
@ -1024,7 +1024,7 @@ impl Mesh {
return; return;
} }
if let Some(VertexAttributeValues::Float32x3(ref mut normals)) = if let Some(VertexAttributeValues::Float32x3(normals)) =
self.attribute_mut(Mesh::ATTRIBUTE_NORMAL) self.attribute_mut(Mesh::ATTRIBUTE_NORMAL)
{ {
// Transform normals, taking into account non-uniform scaling // Transform normals, taking into account non-uniform scaling
@ -1033,7 +1033,7 @@ impl Mesh {
}); });
} }
if let Some(VertexAttributeValues::Float32x3(ref mut tangents)) = if let Some(VertexAttributeValues::Float32x3(tangents)) =
self.attribute_mut(Mesh::ATTRIBUTE_TANGENT) self.attribute_mut(Mesh::ATTRIBUTE_TANGENT)
{ {
// Transform tangents, taking into account non-uniform scaling // Transform tangents, taking into account non-uniform scaling
@ -1096,7 +1096,7 @@ impl Mesh {
/// Normalize joint weights so they sum to 1. /// Normalize joint weights so they sum to 1.
pub fn normalize_joint_weights(&mut self) { pub fn normalize_joint_weights(&mut self) {
if let Some(joints) = self.attribute_mut(Self::ATTRIBUTE_JOINT_WEIGHT) { if let Some(joints) = self.attribute_mut(Self::ATTRIBUTE_JOINT_WEIGHT) {
let VertexAttributeValues::Float32x4(ref mut joints) = joints else { let VertexAttributeValues::Float32x4(joints) = joints else {
panic!("unexpected joint weight format"); panic!("unexpected joint weight format");
}; };

View File

@ -5,7 +5,6 @@ use bevy_image::Image;
use bevy_math::Vec3; use bevy_math::Vec3;
use bevy_reflect::prelude::*; use bevy_reflect::prelude::*;
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use core::iter;
use thiserror::Error; use thiserror::Error;
use wgpu_types::{Extent3d, TextureDimension, TextureFormat}; use wgpu_types::{Extent3d, TextureDimension, TextureFormat};
@ -77,7 +76,7 @@ impl MorphTargetImage {
buffer.extend_from_slice(bytemuck::bytes_of(&to_add)); buffer.extend_from_slice(bytemuck::bytes_of(&to_add));
} }
// Pad each layer so that they fit width * height // Pad each layer so that they fit width * height
buffer.extend(iter::repeat(0).take(padding as usize * size_of::<f32>())); buffer.extend(core::iter::repeat_n(0, padding as usize * size_of::<f32>()));
debug_assert_eq!(buffer.len(), layer_byte_count); debug_assert_eq!(buffer.len(), layer_byte_count);
buffer buffer
}) })

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_mikktspace" name = "bevy_mikktspace"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
authors = [ authors = [
"Benjamin Wasty <benny.wasty@gmail.com>", "Benjamin Wasty <benny.wasty@gmail.com>",
"David Harvey-Macaulay <alteous@outlook.com>", "David Harvey-Macaulay <alteous@outlook.com>",
@ -13,7 +13,7 @@ homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"
license = "Zlib AND (MIT OR Apache-2.0)" license = "Zlib AND (MIT OR Apache-2.0)"
keywords = ["bevy", "3D", "graphics", "algorithm", "tangent"] keywords = ["bevy", "3D", "graphics", "algorithm", "tangent"]
rust-version = "1.76.0" rust-version = "1.85.0"
[features] [features]
default = ["std"] default = ["std"]

View File

@ -1,6 +1,10 @@
//! This example demonstrates how to generate a mesh. //! This example demonstrates how to generate a mesh.
#![allow(clippy::bool_assert_comparison, clippy::useless_conversion)] #![allow(
clippy::bool_assert_comparison,
clippy::useless_conversion,
reason = "Crate auto-generated with many non-idiomatic decisions. See #7372 for details."
)]
use glam::{Vec2, Vec3}; use glam::{Vec2, Vec3};

View File

@ -2,7 +2,8 @@
#![expect( #![expect(
clippy::bool_assert_comparison, clippy::bool_assert_comparison,
clippy::semicolon_if_nothing_returned, clippy::semicolon_if_nothing_returned,
clippy::useless_conversion clippy::useless_conversion,
reason = "Crate auto-generated with many non-idiomatic decisions. See #7372 for details."
)] )]
use bevy_mikktspace::{generate_tangents, Geometry}; use bevy_mikktspace::{generate_tangents, Geometry};

View File

@ -1,7 +1,7 @@
[package] [package]
name = "bevy_pbr" name = "bevy_pbr"
version = "0.16.0-dev" version = "0.16.0-dev"
edition = "2021" edition = "2024"
description = "Adds PBR rendering to Bevy Engine" description = "Adds PBR rendering to Bevy Engine"
homepage = "https://bevyengine.org" homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy" repository = "https://github.com/bevyengine/bevy"

View File

@ -496,7 +496,7 @@ pub(crate) fn assign_objects_to_clusters(
// initialize empty cluster bounding spheres // initialize empty cluster bounding spheres
cluster_aabb_spheres.clear(); cluster_aabb_spheres.clear();
cluster_aabb_spheres.extend(core::iter::repeat(None).take(cluster_count)); cluster_aabb_spheres.extend(core::iter::repeat_n(None, cluster_count));
// Calculate the x/y/z cluster frustum planes in view space // Calculate the x/y/z cluster frustum planes in view space
let mut x_planes = Vec::with_capacity(clusters.dimensions.x as usize + 1); let mut x_planes = Vec::with_capacity(clusters.dimensions.x as usize + 1);
@ -845,7 +845,7 @@ pub(crate) fn assign_objects_to_clusters(
} }
} }
ClusterableObjectType::Decal { .. } => { ClusterableObjectType::Decal => {
// Decals currently affect all clusters in their // Decals currently affect all clusters in their
// bounding sphere. // bounding sphere.
// //

View File

@ -141,11 +141,11 @@ pub enum FogFalloff {
/// ## Tips /// ## Tips
/// ///
/// - Use the [`FogFalloff::from_visibility()`] convenience method to create an exponential falloff with the proper /// - Use the [`FogFalloff::from_visibility()`] convenience method to create an exponential falloff with the proper
/// density for a desired visibility distance in world units; /// density for a desired visibility distance in world units;
/// - It's not _unusual_ to have very large or very small values for the density, depending on the scene /// - It's not _unusual_ to have very large or very small values for the density, depending on the scene
/// scale. Typically, for scenes with objects in the scale of thousands of units, you might want density values /// scale. Typically, for scenes with objects in the scale of thousands of units, you might want density values
/// in the ballpark of `0.001`. Conversely, for really small scale scenes you might want really high values of /// in the ballpark of `0.001`. Conversely, for really small scale scenes you might want really high values of
/// density; /// density;
/// - Combine the `density` parameter with the [`DistanceFog`] `color`'s alpha channel for easier artistic control. /// - Combine the `density` parameter with the [`DistanceFog`] `color`'s alpha channel for easier artistic control.
/// ///
/// ## Formula /// ## Formula
@ -193,7 +193,7 @@ pub enum FogFalloff {
/// ## Tips /// ## Tips
/// ///
/// - Use the [`FogFalloff::from_visibility_squared()`] convenience method to create an exponential squared falloff /// - Use the [`FogFalloff::from_visibility_squared()`] convenience method to create an exponential squared falloff
/// with the proper density for a desired visibility distance in world units; /// with the proper density for a desired visibility distance in world units;
/// - Combine the `density` parameter with the [`DistanceFog`] `color`'s alpha channel for easier artistic control. /// - Combine the `density` parameter with the [`DistanceFog`] `color`'s alpha channel for easier artistic control.
/// ///
/// ## Formula /// ## Formula
@ -239,8 +239,8 @@ pub enum FogFalloff {
/// ## Tips /// ## Tips
/// ///
/// - Use the [`FogFalloff::from_visibility_colors()`] or [`FogFalloff::from_visibility_color()`] convenience methods /// - Use the [`FogFalloff::from_visibility_colors()`] or [`FogFalloff::from_visibility_color()`] convenience methods
/// to create an atmospheric falloff with the proper densities for a desired visibility distance in world units and /// to create an atmospheric falloff with the proper densities for a desired visibility distance in world units and
/// extinction and inscattering colors; /// extinction and inscattering colors;
/// - Combine the atmospheric fog parameters with the [`DistanceFog`] `color`'s alpha channel for easier artistic control. /// - Combine the atmospheric fog parameters with the [`DistanceFog`] `color`'s alpha channel for easier artistic control.
/// ///
/// ## Formula /// ## Formula

View File

@ -81,17 +81,17 @@
//! less ideal for this use case: //! less ideal for this use case:
//! //!
//! 1. The level 1 spherical harmonic coefficients can be negative. That //! 1. The level 1 spherical harmonic coefficients can be negative. That
//! prevents the use of the efficient [RGB9E5 texture format], which only //! prevents the use of the efficient [RGB9E5 texture format], which only
//! encodes unsigned floating point numbers, and forces the use of the //! encodes unsigned floating point numbers, and forces the use of the
//! less-efficient [RGBA16F format] if hardware interpolation is desired. //! less-efficient [RGBA16F format] if hardware interpolation is desired.
//! //!
//! 2. As an alternative to RGBA16F, level 1 spherical harmonics can be //! 2. As an alternative to RGBA16F, level 1 spherical harmonics can be
//! normalized and scaled to the SH0 base color, as [Frostbite] does. This //! normalized and scaled to the SH0 base color, as [Frostbite] does. This
//! allows them to be packed in standard LDR RGBA8 textures. However, this //! allows them to be packed in standard LDR RGBA8 textures. However, this
//! prevents the use of hardware trilinear filtering, as the nonuniform scale //! prevents the use of hardware trilinear filtering, as the nonuniform scale
//! factor means that hardware interpolation no longer produces correct results. //! factor means that hardware interpolation no longer produces correct results.
//! The 8 texture fetches needed to interpolate between voxels can be upwards of //! The 8 texture fetches needed to interpolate between voxels can be upwards of
//! twice as slow as the hardware interpolation. //! twice as slow as the hardware interpolation.
//! //!
//! The following chart summarizes the costs and benefits of ambient cubes, //! The following chart summarizes the costs and benefits of ambient cubes,
//! level 1 spherical harmonics, and level 2 spherical harmonics: //! level 1 spherical harmonics, and level 2 spherical harmonics:

View File

@ -769,22 +769,22 @@ pub(crate) fn add_cubemap_texture_view<'a>(
/// (a.k.a. bindless textures). This function checks for these pitfalls: /// (a.k.a. bindless textures). This function checks for these pitfalls:
/// ///
/// 1. If GLSL support is enabled at the feature level, then in debug mode /// 1. If GLSL support is enabled at the feature level, then in debug mode
/// `naga_oil` will attempt to compile all shader modules under GLSL to check /// `naga_oil` will attempt to compile all shader modules under GLSL to check
/// validity of names, even if GLSL isn't actually used. This will cause a crash /// validity of names, even if GLSL isn't actually used. This will cause a crash
/// if binding arrays are enabled, because binding arrays are currently /// if binding arrays are enabled, because binding arrays are currently
/// unimplemented in the GLSL backend of Naga. Therefore, we disable binding /// unimplemented in the GLSL backend of Naga. Therefore, we disable binding
/// arrays if the `shader_format_glsl` feature is present. /// arrays if the `shader_format_glsl` feature is present.
/// ///
/// 2. If there aren't enough texture bindings available to accommodate all the /// 2. If there aren't enough texture bindings available to accommodate all the
/// binding arrays, the driver will panic. So we also bail out if there aren't /// binding arrays, the driver will panic. So we also bail out if there aren't
/// enough texture bindings available in the fragment shader. /// enough texture bindings available in the fragment shader.
/// ///
/// 3. If binding arrays aren't supported on the hardware, then we obviously /// 3. If binding arrays aren't supported on the hardware, then we obviously
/// can't use them. Adreno <= 610 claims to support bindless, but seems to be /// can't use them. Adreno <= 610 claims to support bindless, but seems to be
/// too buggy to be usable. /// too buggy to be usable.
/// ///
/// 4. If binding arrays are supported on the hardware, but they can only be /// 4. If binding arrays are supported on the hardware, but they can only be
/// accessed by uniform indices, that's not good enough, and we bail out. /// accessed by uniform indices, that's not good enough, and we bail out.
/// ///
/// If binding arrays aren't usable, we disable reflection probes and limit the /// If binding arrays aren't usable, we disable reflection probes and limit the
/// number of irradiance volumes in the scene to 1. /// number of irradiance volumes in the scene to 1.

View File

@ -1229,8 +1229,8 @@ impl<M: Material> RenderAsset for PreparedMaterial<M> {
render_device, render_device,
pipeline, pipeline,
default_opaque_render_method, default_opaque_render_method,
ref mut bind_group_allocator, bind_group_allocator,
ref mut render_material_bindings, render_material_bindings,
opaque_draw_functions, opaque_draw_functions,
alpha_mask_draw_functions, alpha_mask_draw_functions,
transmissive_draw_functions, transmissive_draw_functions,
@ -1239,7 +1239,7 @@ impl<M: Material> RenderAsset for PreparedMaterial<M> {
alpha_mask_prepass_draw_functions, alpha_mask_prepass_draw_functions,
opaque_deferred_draw_functions, opaque_deferred_draw_functions,
alpha_mask_deferred_draw_functions, alpha_mask_deferred_draw_functions,
ref mut material_param, material_param,
): &mut SystemParamItem<Self::Param>, ): &mut SystemParamItem<Self::Param>,
) -> Result<Self, PrepareAssetError<Self::SourceAsset>> { ) -> Result<Self, PrepareAssetError<Self::SourceAsset>> {
let draw_opaque_pbr = opaque_draw_functions.read().id::<DrawMaterial<M>>(); let draw_opaque_pbr = opaque_draw_functions.read().id::<DrawMaterial<M>>();
@ -1394,14 +1394,9 @@ impl<M: Material> RenderAsset for PreparedMaterial<M> {
fn unload_asset( fn unload_asset(
source_asset: AssetId<Self::SourceAsset>, source_asset: AssetId<Self::SourceAsset>,
( (_, _, _, bind_group_allocator, render_material_bindings, ..): &mut SystemParamItem<
_, Self::Param,
_, >,
_,
ref mut bind_group_allocator,
ref mut render_material_bindings,
..,
): &mut SystemParamItem<Self::Param>,
) { ) {
let Some(material_binding_id) = render_material_bindings.remove(&source_asset.untyped()) let Some(material_binding_id) = render_material_bindings.remove(&source_asset.untyped())
else { else {

View File

@ -102,11 +102,13 @@ impl MeshletMesh {
}, },
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut simplification_errors = iter::repeat(MeshletSimplificationError { let mut simplification_errors = iter::repeat_n(
group_error: f16::ZERO, MeshletSimplificationError {
parent_group_error: f16::MAX, group_error: f16::ZERO,
}) parent_group_error: f16::MAX,
.take(meshlets.len()) },
meshlets.len(),
)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut vertex_locks = vec![false; vertices.vertex_count]; let mut vertex_locks = vec![false; vertices.vertex_count];
@ -187,13 +189,13 @@ impl MeshletMesh {
}, },
} }
})); }));
simplification_errors.extend( simplification_errors.extend(iter::repeat_n(
iter::repeat(MeshletSimplificationError { MeshletSimplificationError {
group_error, group_error,
parent_group_error: f16::MAX, parent_group_error: f16::MAX,
}) },
.take(new_meshlet_ids.len()), new_meshlet_ids.len(),
); ));
} }
// Set simplification queue to the list of newly created meshlets // Set simplification queue to the list of newly created meshlets

Some files were not shown because too many files have changed in this diff Show More