Skip to content

Commit fd329c0

Browse files
bas-ieBD103benfrankelchompaa
authored
Allow to expect (adopted) (#15301)
# Objective > Rust 1.81 released the #[expect(...)] attribute, which works like #[allow(...)] but throws a warning if the lint isn't raised. This is preferred to #[allow(...)] because it tells us when it can be removed. - Adopts the parts of #15118 that are complete, and updates the branch so it can be merged. - There were a few conflicts, let me know if I misjudged any of 'em. Alice's [recommendation](#15059 (comment)) seems well-taken, let's do this crate by crate now that @BD103 has done the lion's share of this! (Relates to, but doesn't yet completely finish #15059.) Crates this _doesn't_ cover: - bevy_input - bevy_gilrs - bevy_window - bevy_winit - bevy_state - bevy_render - bevy_picking - bevy_core_pipeline - bevy_sprite - bevy_text - bevy_pbr - bevy_ui - bevy_gltf - bevy_gizmos - bevy_dev_tools - bevy_internal - bevy_dylib --------- Co-authored-by: BD103 <[email protected]> Co-authored-by: Ben Frankel <[email protected]> Co-authored-by: Antony <[email protected]>
1 parent ebb57c5 commit fd329c0

File tree

44 files changed

+182
-100
lines changed

Some content is hidden

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

44 files changed

+182
-100
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
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.80.0"
13+
rust-version = "1.81.0"
1414

1515
[workspace]
1616
exclude = [

crates/bevy_app/src/app.rs

Lines changed: 0 additions & 1 deletion
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
///

crates/bevy_app/src/plugin.rs

Lines changed: 3 additions & 1 deletion
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

Lines changed: 4 additions & 1 deletion
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 22 additions & 5 deletions
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/source.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ use thiserror::Error;
1111

1212
use super::{ErasedAssetReader, ErasedAssetWriter};
1313

14-
// Needed for doc strings.
15-
#[allow(unused_imports)]
14+
#[allow(unused_imports, reason = "Needed for documentation links.")]
1615
use crate::io::{AssetReader, AssetWriter};
1716

1817
/// A reference to an "asset source", which maps to an [`AssetReader`] and/or [`AssetWriter`].
@@ -508,7 +507,17 @@ impl AssetSource {
508507
/// `file_debounce_time` is the amount of time to wait (and debounce duplicate events) before returning an event.
509508
/// Higher durations reduce duplicates but increase the amount of time before a change event is processed. If the
510509
/// duration is set too low, some systems might surface events _before_ their filesystem has the changes.
511-
#[allow(unused)]
510+
#[cfg_attr(
511+
any(
512+
not(feature = "file_watcher"),
513+
target_arch = "wasm32",
514+
target_os = "android"
515+
),
516+
expect(
517+
unused_variables,
518+
reason = "The `path` and `file_debounce_wait_time` arguments are unused when on WASM, Android, or if the `file_watcher` feature is disabled."
519+
)
520+
)]
512521
pub fn get_default_watcher(
513522
path: String,
514523
file_debounce_wait_time: Duration,

crates/bevy_asset/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@
139139
//! This trait mirrors [`AssetLoader`] in structure, and works in tandem with [`AssetWriter`](io::AssetWriter), which mirrors [`AssetReader`](io::AssetReader).
140140
141141
// FIXME(3492): remove once docs are ready
142-
#![allow(missing_docs)]
142+
// FIXME(15321): solve CI failures, then replace with `#![expect()]`.
143+
#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")]
143144
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
144145
#![doc(
145146
html_logo_url = "https://bevyengine.org/assets/icon.png",

crates/bevy_asset/src/loader.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ impl ErasedLoadedAsset {
256256

257257
/// Cast this loaded asset as the given type. If the type does not match,
258258
/// the original type-erased asset is returned.
259-
#[allow(clippy::result_large_err)]
259+
#[expect(clippy::result_large_err, reason = "Function returns `Self` on error.")]
260260
pub fn downcast<A: Asset>(mut self) -> Result<LoadedAsset<A>, ErasedLoadedAsset> {
261261
match self.value.downcast::<A>() {
262262
Ok(value) => Ok(LoadedAsset {

crates/bevy_asset/src/processor/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ use std::{
7676
use thiserror::Error;
7777

7878
// Needed for doc strings
79-
#[allow(unused_imports)]
79+
#[allow(unused_imports, reason = "Needed for documentation links.")]
8080
use crate::io::{AssetReader, AssetWriter};
8181

8282
/// A "background" asset processor that reads asset values from a source [`AssetSource`] (which corresponds to an [`AssetReader`] / [`AssetWriter`] pair),
@@ -557,7 +557,13 @@ impl AssetProcessor {
557557
/// This info will later be used to determine whether or not to re-process an asset
558558
///
559559
/// This will validate transactions and recover failed transactions when necessary.
560-
#[allow(unused)]
560+
#[cfg_attr(
561+
any(target_arch = "wasm32", not(feature = "multi_threaded")),
562+
expect(
563+
dead_code,
564+
reason = "This function is only used when the `multi_threaded` feature is enabled, and when not on WASM."
565+
)
566+
)]
561567
async fn initialize(&self) -> Result<(), InitializeError> {
562568
self.validate_transaction_log_and_recover().await;
563569
let mut asset_infos = self.data.asset_infos.write().await;

crates/bevy_asset/src/reflect.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,19 @@ impl ReflectAsset {
4646
}
4747

4848
/// Equivalent of [`Assets::get_mut`]
49-
#[allow(unsafe_code)]
5049
pub fn get_mut<'w>(
5150
&self,
5251
world: &'w mut World,
5352
handle: UntypedHandle,
5453
) -> Option<&'w mut dyn Reflect> {
5554
// SAFETY: unique world access
56-
unsafe { (self.get_unchecked_mut)(world.as_unsafe_world_cell(), handle) }
55+
#[expect(
56+
unsafe_code,
57+
reason = "Use of unsafe `Self::get_unchecked_mut()` function."
58+
)]
59+
unsafe {
60+
(self.get_unchecked_mut)(world.as_unsafe_world_cell(), handle)
61+
}
5762
}
5863

5964
/// Equivalent of [`Assets::get_mut`], but works with an [`UnsafeWorldCell`].
@@ -83,7 +88,10 @@ impl ReflectAsset {
8388
/// violating Rust's aliasing rules. To avoid this:
8489
/// * Only call this method if you know that the [`UnsafeWorldCell`] may be used to access the corresponding `Assets<T>`
8590
/// * Don't call this method more than once in the same scope.
86-
#[allow(unsafe_code)]
91+
#[expect(
92+
unsafe_code,
93+
reason = "This function calls unsafe code and has safety requirements."
94+
)]
8795
pub unsafe fn get_unchecked_mut<'w>(
8896
&self,
8997
world: UnsafeWorldCell<'w>,
@@ -108,7 +116,6 @@ impl ReflectAsset {
108116
}
109117

110118
/// Equivalent of [`Assets::len`]
111-
#[allow(clippy::len_without_is_empty)] // clippy expects the `is_empty` method to have the signature `(&self) -> bool`
112119
pub fn len(&self, world: &World) -> usize {
113120
(self.len)(world)
114121
}
@@ -137,7 +144,7 @@ impl<A: Asset + FromReflect> FromType<A> for ReflectAsset {
137144
get_unchecked_mut: |world, handle| {
138145
// SAFETY: `get_unchecked_mut` must be called with `UnsafeWorldCell` having access to `Assets<A>`,
139146
// and must ensure to only have at most one reference to it live at all times.
140-
#[allow(unsafe_code)]
147+
#[expect(unsafe_code, reason = "Uses `UnsafeWorldCell::get_resource_mut()`.")]
141148
let assets = unsafe { world.get_resource_mut::<Assets<A>>().unwrap().into_inner() };
142149
let asset = assets.get_mut(&handle.typed_debug_checked());
143150
asset.map(|asset| asset as &mut dyn Reflect)

crates/bevy_asset/src/server/info.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,10 @@ impl AssetInfos {
111111
.unwrap()
112112
}
113113

114-
#[allow(clippy::too_many_arguments)]
114+
#[expect(
115+
clippy::too_many_arguments,
116+
reason = "Arguments needed so that both `create_loading_handle_untyped()` and `get_or_create_path_handle_internal()` may share code."
117+
)]
115118
fn create_handle_internal(
116119
infos: &mut HashMap<UntypedAssetId, AssetInfo>,
117120
handle_providers: &TypeIdMap<AssetHandleProvider>,

crates/bevy_asset/src/server/mod.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ use std::{any::TypeId, path::Path, sync::Arc};
3232
use std::{future::Future, panic::AssertUnwindSafe};
3333
use thiserror::Error;
3434

35-
// Needed for doc string
36-
#[allow(unused_imports)]
35+
#[allow(unused_imports, reason = "Needed for documentation links.")]
3736
use crate::io::{AssetReader, AssetWriter};
3837

3938
/// Loads and tracks the state of [`Asset`] values from a configured [`AssetReader`]. This can be used to kick off new asset loads and
@@ -1395,7 +1394,6 @@ pub fn handle_internal_asset_events(world: &mut World) {
13951394
}
13961395

13971396
/// Internal events for asset load results
1398-
#[allow(clippy::large_enum_variant)]
13991397
pub(crate) enum InternalAssetEvent {
14001398
Loaded {
14011399
id: UntypedAssetId,

crates/bevy_core_pipeline/src/lib.rs

Lines changed: 2 additions & 2 deletions
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
#![forbid(unsafe_code)]
44
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
55
#![doc(

crates/bevy_core_pipeline/src/skybox/prepass.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![warn(missing_docs)]
2-
31
//! Adds motion vector support to skyboxes. See [`SkyboxPrepassPipeline`] for details.
42
53
use bevy_asset::Handle;

crates/bevy_derive/src/lib.rs

Lines changed: 2 additions & 2 deletions
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
#![forbid(unsafe_code)]
44
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
55
#![doc(

crates/bevy_diagnostic/src/lib.rs

Lines changed: 2 additions & 2 deletions
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
#![forbid(unsafe_code)]
55
#![doc(

crates/bevy_ecs/macros/src/lib.rs

Lines changed: 2 additions & 2 deletions
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
extern crate proc_macro;

crates/bevy_ecs/macros/src/query_data.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,13 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
104104
let read_only_struct_name = if attributes.is_mutable {
105105
Ident::new(&format!("{struct_name}ReadOnly"), Span::call_site())
106106
} else {
107-
#[allow(clippy::redundant_clone)]
108107
struct_name.clone()
109108
};
110109

111110
let item_struct_name = Ident::new(&format!("{struct_name}Item"), Span::call_site());
112111
let read_only_item_struct_name = if attributes.is_mutable {
113112
Ident::new(&format!("{struct_name}ReadOnlyItem"), Span::call_site())
114113
} else {
115-
#[allow(clippy::redundant_clone)]
116114
item_struct_name.clone()
117115
};
118116

@@ -122,7 +120,6 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
122120
let new_ident = Ident::new(&format!("{struct_name}ReadOnlyFetch"), Span::call_site());
123121
ensure_no_collision(new_ident, tokens.clone())
124122
} else {
125-
#[allow(clippy::redundant_clone)]
126123
fetch_struct_name.clone()
127124
};
128125

crates/bevy_ecs/macros/src/world_query.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ use proc_macro2::Ident;
22
use quote::quote;
33
use syn::{Attribute, Fields, ImplGenerics, TypeGenerics, Visibility, WhereClause};
44

5-
#[allow(clippy::too_many_arguments)]
5+
#[expect(
6+
clippy::too_many_arguments,
7+
reason = "Required to generate the entire item structure."
8+
)]
69
pub(crate) fn item_struct(
710
path: &syn::Path,
811
fields: &Fields,
@@ -52,7 +55,10 @@ pub(crate) fn item_struct(
5255
}
5356
}
5457

55-
#[allow(clippy::too_many_arguments)]
58+
#[expect(
59+
clippy::too_many_arguments,
60+
reason = "Required to generate the entire world query implementation."
61+
)]
5662
pub(crate) fn world_query_impl(
5763
path: &syn::Path,
5864
struct_name: &Ident,

crates/bevy_ecs/src/schedule/schedule.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1893,7 +1893,7 @@ impl ScheduleGraph {
18931893
&'a self,
18941894
ambiguities: &'a [(NodeId, NodeId, Vec<ComponentId>)],
18951895
components: &'a Components,
1896-
) -> impl Iterator<Item = (String, String, Vec<&str>)> + 'a {
1896+
) -> impl Iterator<Item = (String, String, Vec<&'a str>)> + 'a {
18971897
ambiguities
18981898
.iter()
18991899
.map(move |(system_a, system_b, conflicts)| {

crates/bevy_encase_derive/src/lib.rs

Lines changed: 2 additions & 2 deletions
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
#![forbid(unsafe_code)]
44
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
55
#![doc(

crates/bevy_log/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@ use {bevy_ecs::system::Resource, bevy_utils::synccell::SyncCell};
6767
/// Wrapper resource for `tracing-chrome`'s flush guard.
6868
/// When the guard is dropped the chrome log is written to file.
6969
#[cfg(feature = "tracing-chrome")]
70-
#[allow(dead_code)]
70+
#[expect(
71+
dead_code,
72+
reason = "`FlushGuard` never needs to be read, it just needs to be kept alive for the `App`'s lifetime."
73+
)]
7174
#[derive(Resource)]
7275
pub(crate) struct FlushGuard(SyncCell<tracing_chrome::FlushGuard>);
7376

@@ -187,7 +190,6 @@ impl Default for LogPlugin {
187190
}
188191

189192
impl Plugin for LogPlugin {
190-
#[cfg_attr(not(feature = "tracing-chrome"), allow(unused_variables))]
191193
fn build(&self, app: &mut App) {
192194
#[cfg(feature = "trace")]
193195
{

crates/bevy_mikktspace/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
unsafe_op_in_unsafe_fn,
33
clippy::all,
44
clippy::undocumented_unsafe_blocks,
5-
clippy::ptr_cast_constness
5+
clippy::ptr_cast_constness,
6+
// FIXME(15321): solve CI failures, then replace with `#![expect()]`.
7+
missing_docs
68
)]
7-
// FIXME(3492): remove once docs are ready
8-
#![allow(missing_docs)]
99
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
1010
#![doc(
1111
html_logo_url = "https://bevyengine.org/assets/icon.png",

crates/bevy_pbr/src/lib.rs

Lines changed: 2 additions & 2 deletions
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
#![deny(unsafe_code)]
55
#![doc(

0 commit comments

Comments
 (0)