Skip to content

Commit c9519d4

Browse files
authored
Merge branch 'main' into res-acq
2 parents a1ef231 + 417e6cc commit c9519d4

File tree

79 files changed

+754
-387
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+754
-387
lines changed

.github/workflows/ci.yml

+7-8
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,15 @@ jobs:
9292
components: miri
9393
- name: CI job
9494
# To run the tests one item at a time for troubleshooting, use
95-
# cargo --quiet test --lib -- --list | sed 's/: test$//' | MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-permissive-provenance -Zmiri-disable-weak-memory-emulation" xargs -n1 cargo miri test -p bevy_ecs --lib -- --exact
95+
# cargo --quiet test --lib -- --list | sed 's/: test$//' | MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-disable-weak-memory-emulation" xargs -n1 cargo miri test -p bevy_ecs --lib -- --exact
9696
run: cargo miri test -p bevy_ecs
9797
env:
9898
# -Zrandomize-layout makes sure we dont rely on the layout of anything that might change
9999
RUSTFLAGS: -Zrandomize-layout
100100
# https://github.com/rust-lang/miri#miri--z-flags-and-environment-variables
101101
# -Zmiri-disable-isolation is needed because our executor uses `fastrand` which accesses system time.
102-
# -Zmiri-permissive-provenance disables warnings against int2ptr casts (since those are used by once_cell)
103102
# -Zmiri-ignore-leaks is necessary because a bunch of tests don't join all threads before finishing.
104-
MIRIFLAGS: -Zmiri-ignore-leaks -Zmiri-disable-isolation -Zmiri-permissive-provenance
103+
MIRIFLAGS: -Zmiri-ignore-leaks -Zmiri-disable-isolation
105104

106105
check-compiles:
107106
runs-on: ubuntu-latest
@@ -420,19 +419,19 @@ jobs:
420419
timeout-minutes: 30
421420
steps:
422421
- uses: actions/checkout@v4
423-
- name: Check for bevy_internal imports
422+
- name: Check for internal Bevy imports
424423
shell: bash
425424
run: |
426425
errors=""
427426
for file in $(find examples tests -name '*.rs'); do
428-
if grep -q "use bevy_internal" "$file"; then
429-
errors+="ERROR: Detected 'use bevy_internal' in $file\n"
427+
if grep -q "use bevy_" "$file"; then
428+
errors+="ERROR: Detected internal Bevy import in $file\n"
430429
fi
431430
done
432431
if [ -n "$errors" ]; then
433432
echo -e "$errors"
434-
echo " Avoid importing bevy_internal, it should not be used directly"
435-
echo " Fix the issue by replacing 'bevy_internal' with 'bevy'"
433+
echo " Avoid importing internal Bevy crates, they should not be used directly"
434+
echo " Fix the issue by replacing 'bevy_*' with 'bevy'"
436435
echo " Example: 'use bevy::sprite::MaterialMesh2dBundle;' instead of 'bevy_internal::sprite::MaterialMesh2dBundle;'"
437436
exit 1
438437
fi

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ keywords = ["game", "engine", "gamedev", "graphics", "bevy"]
1010
license = "MIT OR Apache-2.0"
1111
repository = "https://github.com/bevyengine/bevy"
1212
documentation = "https://docs.rs/bevy"
13-
rust-version = "1.79.0"
13+
rust-version = "1.81.0"
1414

1515
[workspace]
1616
exclude = [

benches/benches/bevy_ecs/world/commands.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::mem::size_of;
2-
31
use bevy_ecs::{
42
component::Component,
53
entity::Entity,

crates/bevy_app/src/app.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ pub(crate) enum AppError {
4040
DuplicatePlugin { plugin_name: String },
4141
}
4242

43-
#[allow(clippy::needless_doctest_main)]
4443
/// [`App`] is the primary API for writing user applications. It automates the setup of a
4544
/// [standard lifecycle](Main) and provides interface glue for [plugins](`Plugin`).
4645
///
@@ -1115,7 +1114,7 @@ impl Termination for AppExit {
11151114

11161115
#[cfg(test)]
11171116
mod tests {
1118-
use std::{iter, marker::PhantomData, mem::size_of, sync::Mutex};
1117+
use std::{iter, marker::PhantomData, sync::Mutex};
11191118

11201119
use bevy_ecs::{
11211120
change_detection::{DetectChanges, ResMut},

crates/bevy_app/src/plugin.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,9 @@ mod sealed {
167167
where
168168
$($plugins: Plugins<$param>),*
169169
{
170-
#[allow(non_snake_case, unused_variables)]
170+
// We use `allow` instead of `expect` here because the lint is not generated for all cases.
171+
#[allow(non_snake_case, reason = "`all_tuples!()` generates non-snake-case variable names.")]
172+
#[allow(unused_variables, reason = "`app` is unused when implemented for the unit type `()`.")]
171173
#[track_caller]
172174
fn add_to_app(self, app: &mut App) {
173175
let ($($plugins,)*) = self;

crates/bevy_app/src/plugin_group.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,10 @@ impl PluginGroupBuilder {
279279
/// Adds the plugin [`Plugin`] at the end of this [`PluginGroupBuilder`]. If the plugin was
280280
/// already in the group, it is removed from its previous place.
281281
// This is not confusing, clippy!
282-
#[allow(clippy::should_implement_trait)]
282+
#[expect(
283+
clippy::should_implement_trait,
284+
reason = "This does not emulate the `+` operator, but is more akin to pushing to a stack."
285+
)]
283286
pub fn add<T: Plugin>(mut self, plugin: T) -> Self {
284287
let target_index = self.order.len();
285288
self.order.push(TypeId::of::<T>());

crates/bevy_asset/macros/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// FIXME(3492): remove once docs are ready
2-
#![allow(missing_docs)]
1+
// FIXME(15321): solve CI failures, then replace with `#![expect()]`.
2+
#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")]
33
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
44

55
use bevy_macro_utils::BevyManifest;

crates/bevy_asset/src/io/embedded/mod.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,13 @@ impl EmbeddedAssetRegistry {
3030
/// running in a non-rust file). `asset_path` is the path that will be used to identify the asset in the `embedded`
3131
/// [`AssetSource`]. `value` is the bytes that will be returned for the asset. This can be _either_ a `&'static [u8]`
3232
/// or a [`Vec<u8>`].
33-
#[allow(unused)]
33+
#[cfg_attr(
34+
not(feature = "embedded_watcher"),
35+
expect(
36+
unused_variables,
37+
reason = "The `full_path` argument is not used when `embedded_watcher` is disabled."
38+
)
39+
)]
3440
pub fn insert_asset(&self, full_path: PathBuf, asset_path: &Path, value: impl Into<Value>) {
3541
#[cfg(feature = "embedded_watcher")]
3642
self.root_paths
@@ -43,7 +49,13 @@ impl EmbeddedAssetRegistry {
4349
/// running in a non-rust file). `asset_path` is the path that will be used to identify the asset in the `embedded`
4450
/// [`AssetSource`]. `value` is the bytes that will be returned for the asset. This can be _either_ a `&'static [u8]`
4551
/// or a [`Vec<u8>`].
46-
#[allow(unused)]
52+
#[cfg_attr(
53+
not(feature = "embedded_watcher"),
54+
expect(
55+
unused_variables,
56+
reason = "The `full_path` argument is not used when `embedded_watcher` is disabled."
57+
)
58+
)]
4759
pub fn insert_meta(&self, full_path: &Path, asset_path: &Path, value: impl Into<Value>) {
4860
#[cfg(feature = "embedded_watcher")]
4961
self.root_paths
@@ -59,12 +71,17 @@ impl EmbeddedAssetRegistry {
5971
self.dir.remove_asset(full_path)
6072
}
6173

62-
/// Registers a `embedded` [`AssetSource`] that uses this [`EmbeddedAssetRegistry`].
63-
// NOTE: unused_mut because embedded_watcher feature is the only mutable consumer of `let mut source`
64-
#[allow(unused_mut)]
6574
pub fn register_source(&self, sources: &mut AssetSourceBuilders) {
6675
let dir = self.dir.clone();
6776
let processed_dir = self.dir.clone();
77+
78+
#[cfg_attr(
79+
not(feature = "embedded_watcher"),
80+
expect(
81+
unused_mut,
82+
reason = "Variable is only mutated when `embedded_watcher` feature is enabled."
83+
)
84+
)]
6885
let mut source = AssetSource::build()
6986
.with_reader(move || Box::new(MemoryAssetReader { root: dir.clone() }))
7087
.with_processed_reader(move || {

crates/bevy_asset/src/io/mod.rs

+50-33
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ use futures_io::{AsyncRead, AsyncSeek, AsyncWrite};
2626
use futures_lite::{ready, Stream};
2727
use std::{
2828
io::SeekFrom,
29-
mem::size_of,
3029
path::{Path, PathBuf},
3130
pin::Pin,
3231
sync::Arc,
@@ -191,32 +190,35 @@ pub trait ErasedAssetReader: Send + Sync + 'static {
191190
fn read<'a>(
192191
&'a self,
193192
path: &'a Path,
194-
) -> BoxedFuture<Result<Box<dyn Reader + 'a>, AssetReaderError>>;
193+
) -> BoxedFuture<'a, Result<Box<dyn Reader + 'a>, AssetReaderError>>;
195194
/// Returns a future to load the full file data at the provided path.
196195
fn read_meta<'a>(
197196
&'a self,
198197
path: &'a Path,
199-
) -> BoxedFuture<Result<Box<dyn Reader + 'a>, AssetReaderError>>;
198+
) -> BoxedFuture<'a, Result<Box<dyn Reader + 'a>, AssetReaderError>>;
200199
/// Returns an iterator of directory entry names at the provided path.
201200
fn read_directory<'a>(
202201
&'a self,
203202
path: &'a Path,
204-
) -> BoxedFuture<Result<Box<PathStream>, AssetReaderError>>;
203+
) -> BoxedFuture<'a, Result<Box<PathStream>, AssetReaderError>>;
205204
/// Returns true if the provided path points to a directory.
206-
fn is_directory<'a>(&'a self, path: &'a Path) -> BoxedFuture<Result<bool, AssetReaderError>>;
205+
fn is_directory<'a>(
206+
&'a self,
207+
path: &'a Path,
208+
) -> BoxedFuture<'a, Result<bool, AssetReaderError>>;
207209
/// Reads asset metadata bytes at the given `path` into a [`Vec<u8>`]. This is a convenience
208210
/// function that wraps [`ErasedAssetReader::read_meta`] by default.
209211
fn read_meta_bytes<'a>(
210212
&'a self,
211213
path: &'a Path,
212-
) -> BoxedFuture<Result<Vec<u8>, AssetReaderError>>;
214+
) -> BoxedFuture<'a, Result<Vec<u8>, AssetReaderError>>;
213215
}
214216

215217
impl<T: AssetReader> ErasedAssetReader for T {
216218
fn read<'a>(
217219
&'a self,
218220
path: &'a Path,
219-
) -> BoxedFuture<Result<Box<dyn Reader + 'a>, AssetReaderError>> {
221+
) -> BoxedFuture<'a, Result<Box<dyn Reader + 'a>, AssetReaderError>> {
220222
Box::pin(async {
221223
let reader = Self::read(self, path).await?;
222224
Ok(Box::new(reader) as Box<dyn Reader>)
@@ -225,7 +227,7 @@ impl<T: AssetReader> ErasedAssetReader for T {
225227
fn read_meta<'a>(
226228
&'a self,
227229
path: &'a Path,
228-
) -> BoxedFuture<Result<Box<dyn Reader + 'a>, AssetReaderError>> {
230+
) -> BoxedFuture<'a, Result<Box<dyn Reader + 'a>, AssetReaderError>> {
229231
Box::pin(async {
230232
let reader = Self::read_meta(self, path).await?;
231233
Ok(Box::new(reader) as Box<dyn Reader>)
@@ -234,16 +236,19 @@ impl<T: AssetReader> ErasedAssetReader for T {
234236
fn read_directory<'a>(
235237
&'a self,
236238
path: &'a Path,
237-
) -> BoxedFuture<Result<Box<PathStream>, AssetReaderError>> {
239+
) -> BoxedFuture<'a, Result<Box<PathStream>, AssetReaderError>> {
238240
Box::pin(Self::read_directory(self, path))
239241
}
240-
fn is_directory<'a>(&'a self, path: &'a Path) -> BoxedFuture<Result<bool, AssetReaderError>> {
242+
fn is_directory<'a>(
243+
&'a self,
244+
path: &'a Path,
245+
) -> BoxedFuture<'a, Result<bool, AssetReaderError>> {
241246
Box::pin(Self::is_directory(self, path))
242247
}
243248
fn read_meta_bytes<'a>(
244249
&'a self,
245250
path: &'a Path,
246-
) -> BoxedFuture<Result<Vec<u8>, AssetReaderError>> {
251+
) -> BoxedFuture<'a, Result<Vec<u8>, AssetReaderError>> {
247252
Box::pin(Self::read_meta_bytes(self, path))
248253
}
249254
}
@@ -352,115 +357,127 @@ pub trait AssetWriter: Send + Sync + 'static {
352357
/// as [`AssetWriter`] isn't currently object safe.
353358
pub trait ErasedAssetWriter: Send + Sync + 'static {
354359
/// Writes the full asset bytes at the provided path.
355-
fn write<'a>(&'a self, path: &'a Path) -> BoxedFuture<Result<Box<Writer>, AssetWriterError>>;
360+
fn write<'a>(
361+
&'a self,
362+
path: &'a Path,
363+
) -> BoxedFuture<'a, Result<Box<Writer>, AssetWriterError>>;
356364
/// Writes the full asset meta bytes at the provided path.
357365
/// This _should not_ include storage specific extensions like `.meta`.
358366
fn write_meta<'a>(
359367
&'a self,
360368
path: &'a Path,
361-
) -> BoxedFuture<Result<Box<Writer>, AssetWriterError>>;
369+
) -> BoxedFuture<'a, Result<Box<Writer>, AssetWriterError>>;
362370
/// Removes the asset stored at the given path.
363-
fn remove<'a>(&'a self, path: &'a Path) -> BoxedFuture<Result<(), AssetWriterError>>;
371+
fn remove<'a>(&'a self, path: &'a Path) -> BoxedFuture<'a, Result<(), AssetWriterError>>;
364372
/// Removes the asset meta stored at the given path.
365373
/// This _should not_ include storage specific extensions like `.meta`.
366-
fn remove_meta<'a>(&'a self, path: &'a Path) -> BoxedFuture<Result<(), AssetWriterError>>;
374+
fn remove_meta<'a>(&'a self, path: &'a Path) -> BoxedFuture<'a, Result<(), AssetWriterError>>;
367375
/// Renames the asset at `old_path` to `new_path`
368376
fn rename<'a>(
369377
&'a self,
370378
old_path: &'a Path,
371379
new_path: &'a Path,
372-
) -> BoxedFuture<Result<(), AssetWriterError>>;
380+
) -> BoxedFuture<'a, Result<(), AssetWriterError>>;
373381
/// Renames the asset meta for the asset at `old_path` to `new_path`.
374382
/// This _should not_ include storage specific extensions like `.meta`.
375383
fn rename_meta<'a>(
376384
&'a self,
377385
old_path: &'a Path,
378386
new_path: &'a Path,
379-
) -> BoxedFuture<Result<(), AssetWriterError>>;
387+
) -> BoxedFuture<'a, Result<(), AssetWriterError>>;
380388
/// Removes the directory at the given path, including all assets _and_ directories in that directory.
381-
fn remove_directory<'a>(&'a self, path: &'a Path) -> BoxedFuture<Result<(), AssetWriterError>>;
389+
fn remove_directory<'a>(
390+
&'a self,
391+
path: &'a Path,
392+
) -> BoxedFuture<'a, Result<(), AssetWriterError>>;
382393
/// Removes the directory at the given path, but only if it is completely empty. This will return an error if the
383394
/// directory is not empty.
384395
fn remove_empty_directory<'a>(
385396
&'a self,
386397
path: &'a Path,
387-
) -> BoxedFuture<Result<(), AssetWriterError>>;
398+
) -> BoxedFuture<'a, Result<(), AssetWriterError>>;
388399
/// Removes all assets (and directories) in this directory, resulting in an empty directory.
389400
fn remove_assets_in_directory<'a>(
390401
&'a self,
391402
path: &'a Path,
392-
) -> BoxedFuture<Result<(), AssetWriterError>>;
403+
) -> BoxedFuture<'a, Result<(), AssetWriterError>>;
393404
/// Writes the asset `bytes` to the given `path`.
394405
fn write_bytes<'a>(
395406
&'a self,
396407
path: &'a Path,
397408
bytes: &'a [u8],
398-
) -> BoxedFuture<Result<(), AssetWriterError>>;
409+
) -> BoxedFuture<'a, Result<(), AssetWriterError>>;
399410
/// Writes the asset meta `bytes` to the given `path`.
400411
fn write_meta_bytes<'a>(
401412
&'a self,
402413
path: &'a Path,
403414
bytes: &'a [u8],
404-
) -> BoxedFuture<Result<(), AssetWriterError>>;
415+
) -> BoxedFuture<'a, Result<(), AssetWriterError>>;
405416
}
406417

407418
impl<T: AssetWriter> ErasedAssetWriter for T {
408-
fn write<'a>(&'a self, path: &'a Path) -> BoxedFuture<Result<Box<Writer>, AssetWriterError>> {
419+
fn write<'a>(
420+
&'a self,
421+
path: &'a Path,
422+
) -> BoxedFuture<'a, Result<Box<Writer>, AssetWriterError>> {
409423
Box::pin(Self::write(self, path))
410424
}
411425
fn write_meta<'a>(
412426
&'a self,
413427
path: &'a Path,
414-
) -> BoxedFuture<Result<Box<Writer>, AssetWriterError>> {
428+
) -> BoxedFuture<'a, Result<Box<Writer>, AssetWriterError>> {
415429
Box::pin(Self::write_meta(self, path))
416430
}
417-
fn remove<'a>(&'a self, path: &'a Path) -> BoxedFuture<Result<(), AssetWriterError>> {
431+
fn remove<'a>(&'a self, path: &'a Path) -> BoxedFuture<'a, Result<(), AssetWriterError>> {
418432
Box::pin(Self::remove(self, path))
419433
}
420-
fn remove_meta<'a>(&'a self, path: &'a Path) -> BoxedFuture<Result<(), AssetWriterError>> {
434+
fn remove_meta<'a>(&'a self, path: &'a Path) -> BoxedFuture<'a, Result<(), AssetWriterError>> {
421435
Box::pin(Self::remove_meta(self, path))
422436
}
423437
fn rename<'a>(
424438
&'a self,
425439
old_path: &'a Path,
426440
new_path: &'a Path,
427-
) -> BoxedFuture<Result<(), AssetWriterError>> {
441+
) -> BoxedFuture<'a, Result<(), AssetWriterError>> {
428442
Box::pin(Self::rename(self, old_path, new_path))
429443
}
430444
fn rename_meta<'a>(
431445
&'a self,
432446
old_path: &'a Path,
433447
new_path: &'a Path,
434-
) -> BoxedFuture<Result<(), AssetWriterError>> {
448+
) -> BoxedFuture<'a, Result<(), AssetWriterError>> {
435449
Box::pin(Self::rename_meta(self, old_path, new_path))
436450
}
437-
fn remove_directory<'a>(&'a self, path: &'a Path) -> BoxedFuture<Result<(), AssetWriterError>> {
451+
fn remove_directory<'a>(
452+
&'a self,
453+
path: &'a Path,
454+
) -> BoxedFuture<'a, Result<(), AssetWriterError>> {
438455
Box::pin(Self::remove_directory(self, path))
439456
}
440457
fn remove_empty_directory<'a>(
441458
&'a self,
442459
path: &'a Path,
443-
) -> BoxedFuture<Result<(), AssetWriterError>> {
460+
) -> BoxedFuture<'a, Result<(), AssetWriterError>> {
444461
Box::pin(Self::remove_empty_directory(self, path))
445462
}
446463
fn remove_assets_in_directory<'a>(
447464
&'a self,
448465
path: &'a Path,
449-
) -> BoxedFuture<Result<(), AssetWriterError>> {
466+
) -> BoxedFuture<'a, Result<(), AssetWriterError>> {
450467
Box::pin(Self::remove_assets_in_directory(self, path))
451468
}
452469
fn write_bytes<'a>(
453470
&'a self,
454471
path: &'a Path,
455472
bytes: &'a [u8],
456-
) -> BoxedFuture<Result<(), AssetWriterError>> {
473+
) -> BoxedFuture<'a, Result<(), AssetWriterError>> {
457474
Box::pin(Self::write_bytes(self, path, bytes))
458475
}
459476
fn write_meta_bytes<'a>(
460477
&'a self,
461478
path: &'a Path,
462479
bytes: &'a [u8],
463-
) -> BoxedFuture<Result<(), AssetWriterError>> {
480+
) -> BoxedFuture<'a, Result<(), AssetWriterError>> {
464481
Box::pin(Self::write_meta_bytes(self, path, bytes))
465482
}
466483
}

0 commit comments

Comments
 (0)