From fd329c04267c85bf0f92834352bdabf253ba7a90 Mon Sep 17 00:00:00 2001 From: Rich Churcher Date: Sat, 21 Sep 2024 07:16:42 +1200 Subject: [PATCH] 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](https://github.com/bevyengine/bevy/issues/15059#issuecomment-2349263900) 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 <59022059+BD103@users.noreply.github.com> Co-authored-by: Ben Frankel Co-authored-by: Antony --- Cargo.toml | 2 +- crates/bevy_app/src/app.rs | 1 - crates/bevy_app/src/plugin.rs | 4 +- crates/bevy_app/src/plugin_group.rs | 5 +- crates/bevy_asset/macros/src/lib.rs | 4 +- crates/bevy_asset/src/io/embedded/mod.rs | 27 ++++++++-- crates/bevy_asset/src/io/source.rs | 15 ++++-- crates/bevy_asset/src/lib.rs | 3 +- crates/bevy_asset/src/loader.rs | 2 +- crates/bevy_asset/src/processor/mod.rs | 10 +++- crates/bevy_asset/src/reflect.rs | 17 ++++-- crates/bevy_asset/src/server/info.rs | 5 +- crates/bevy_asset/src/server/mod.rs | 4 +- crates/bevy_core_pipeline/src/lib.rs | 4 +- .../bevy_core_pipeline/src/skybox/prepass.rs | 2 - crates/bevy_derive/src/lib.rs | 4 +- crates/bevy_diagnostic/src/lib.rs | 4 +- crates/bevy_ecs/macros/src/lib.rs | 4 +- crates/bevy_ecs/macros/src/query_data.rs | 3 -- crates/bevy_ecs/macros/src/world_query.rs | 10 +++- crates/bevy_ecs/src/schedule/schedule.rs | 2 +- crates/bevy_encase_derive/src/lib.rs | 4 +- crates/bevy_log/src/lib.rs | 6 ++- crates/bevy_mikktspace/src/lib.rs | 6 +-- crates/bevy_pbr/src/lib.rs | 4 +- crates/bevy_picking/src/backend.rs | 6 ++- crates/bevy_ptr/src/lib.rs | 5 +- .../derive/src/container_attributes.rs | 5 +- crates/bevy_reflect/derive/src/derive_data.rs | 52 +++++++++++++------ .../bevy_reflect/derive/src/reflect_value.rs | 8 ++- .../bevy_reflect/derive/src/registration.rs | 1 - crates/bevy_reflect/src/lib.rs | 4 +- crates/bevy_render/macros/src/lib.rs | 4 +- crates/bevy_render/src/lib.rs | 4 +- crates/bevy_sprite/src/lib.rs | 4 +- crates/bevy_state/macros/src/lib.rs | 4 +- .../src/single_threaded_task_pool.rs | 3 +- crates/bevy_tasks/src/task_pool.rs | 2 +- crates/bevy_time/src/lib.rs | 3 +- crates/bevy_transform/src/systems.rs | 7 ++- crates/bevy_ui/src/lib.rs | 4 +- crates/bevy_utils/macros/src/lib.rs | 4 +- crates/bevy_utils/src/lib.rs | 7 ++- crates/bevy_window/src/event.rs | 3 +- 44 files changed, 182 insertions(+), 100 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5242ee417257a..0c6411301c9b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ keywords = ["game", "engine", "gamedev", "graphics", "bevy"] license = "MIT OR Apache-2.0" repository = "https://github.com/bevyengine/bevy" documentation = "https://docs.rs/bevy" -rust-version = "1.80.0" +rust-version = "1.81.0" [workspace] exclude = [ diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index a6a0243ee3a42..9c6c4d937c76b 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -40,7 +40,6 @@ pub(crate) enum AppError { DuplicatePlugin { plugin_name: String }, } -#[allow(clippy::needless_doctest_main)] /// [`App`] is the primary API for writing user applications. It automates the setup of a /// [standard lifecycle](Main) and provides interface glue for [plugins](`Plugin`). /// diff --git a/crates/bevy_app/src/plugin.rs b/crates/bevy_app/src/plugin.rs index 006b645cbe99d..23b5be13e13d2 100644 --- a/crates/bevy_app/src/plugin.rs +++ b/crates/bevy_app/src/plugin.rs @@ -167,7 +167,9 @@ mod sealed { where $($plugins: Plugins<$param>),* { - #[allow(non_snake_case, unused_variables)] + // We use `allow` instead of `expect` here because the lint is not generated for all cases. + #[allow(non_snake_case, reason = "`all_tuples!()` generates non-snake-case variable names.")] + #[allow(unused_variables, reason = "`app` is unused when implemented for the unit type `()`.")] #[track_caller] fn add_to_app(self, app: &mut App) { let ($($plugins,)*) = self; diff --git a/crates/bevy_app/src/plugin_group.rs b/crates/bevy_app/src/plugin_group.rs index 0190ee762e36a..28c90ff5ef1ca 100644 --- a/crates/bevy_app/src/plugin_group.rs +++ b/crates/bevy_app/src/plugin_group.rs @@ -279,7 +279,10 @@ impl PluginGroupBuilder { /// Adds the plugin [`Plugin`] at the end of this [`PluginGroupBuilder`]. If the plugin was /// already in the group, it is removed from its previous place. // This is not confusing, clippy! - #[allow(clippy::should_implement_trait)] + #[expect( + clippy::should_implement_trait, + reason = "This does not emulate the `+` operator, but is more akin to pushing to a stack." + )] pub fn add(mut self, plugin: T) -> Self { let target_index = self.order.len(); self.order.push(TypeId::of::()); diff --git a/crates/bevy_asset/macros/src/lib.rs b/crates/bevy_asset/macros/src/lib.rs index 6c290367e64f2..49b3070347ce5 100644 --- a/crates/bevy_asset/macros/src/lib.rs +++ b/crates/bevy_asset/macros/src/lib.rs @@ -1,5 +1,5 @@ -// FIXME(3492): remove once docs are ready -#![allow(missing_docs)] +// FIXME(15321): solve CI failures, then replace with `#![expect()]`. +#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] use bevy_macro_utils::BevyManifest; diff --git a/crates/bevy_asset/src/io/embedded/mod.rs b/crates/bevy_asset/src/io/embedded/mod.rs index f97cab0469bbf..b521d3737be5c 100644 --- a/crates/bevy_asset/src/io/embedded/mod.rs +++ b/crates/bevy_asset/src/io/embedded/mod.rs @@ -30,7 +30,13 @@ impl EmbeddedAssetRegistry { /// running in a non-rust file). `asset_path` is the path that will be used to identify the asset in the `embedded` /// [`AssetSource`]. `value` is the bytes that will be returned for the asset. This can be _either_ a `&'static [u8]` /// or a [`Vec`]. - #[allow(unused)] + #[cfg_attr( + not(feature = "embedded_watcher"), + expect( + unused_variables, + reason = "The `full_path` argument is not used when `embedded_watcher` is disabled." + ) + )] pub fn insert_asset(&self, full_path: PathBuf, asset_path: &Path, value: impl Into) { #[cfg(feature = "embedded_watcher")] self.root_paths @@ -43,7 +49,13 @@ impl EmbeddedAssetRegistry { /// running in a non-rust file). `asset_path` is the path that will be used to identify the asset in the `embedded` /// [`AssetSource`]. `value` is the bytes that will be returned for the asset. This can be _either_ a `&'static [u8]` /// or a [`Vec`]. - #[allow(unused)] + #[cfg_attr( + not(feature = "embedded_watcher"), + expect( + unused_variables, + reason = "The `full_path` argument is not used when `embedded_watcher` is disabled." + ) + )] pub fn insert_meta(&self, full_path: &Path, asset_path: &Path, value: impl Into) { #[cfg(feature = "embedded_watcher")] self.root_paths @@ -59,12 +71,17 @@ impl EmbeddedAssetRegistry { self.dir.remove_asset(full_path) } - /// Registers a `embedded` [`AssetSource`] that uses this [`EmbeddedAssetRegistry`]. - // NOTE: unused_mut because embedded_watcher feature is the only mutable consumer of `let mut source` - #[allow(unused_mut)] pub fn register_source(&self, sources: &mut AssetSourceBuilders) { let dir = self.dir.clone(); let processed_dir = self.dir.clone(); + + #[cfg_attr( + not(feature = "embedded_watcher"), + expect( + unused_mut, + reason = "Variable is only mutated when `embedded_watcher` feature is enabled." + ) + )] let mut source = AssetSource::build() .with_reader(move || Box::new(MemoryAssetReader { root: dir.clone() })) .with_processed_reader(move || { diff --git a/crates/bevy_asset/src/io/source.rs b/crates/bevy_asset/src/io/source.rs index ec1947a3fee1e..8a767034d2c9e 100644 --- a/crates/bevy_asset/src/io/source.rs +++ b/crates/bevy_asset/src/io/source.rs @@ -11,8 +11,7 @@ use thiserror::Error; use super::{ErasedAssetReader, ErasedAssetWriter}; -// Needed for doc strings. -#[allow(unused_imports)] +#[allow(unused_imports, reason = "Needed for documentation links.")] use crate::io::{AssetReader, AssetWriter}; /// A reference to an "asset source", which maps to an [`AssetReader`] and/or [`AssetWriter`]. @@ -508,7 +507,17 @@ impl AssetSource { /// `file_debounce_time` is the amount of time to wait (and debounce duplicate events) before returning an event. /// Higher durations reduce duplicates but increase the amount of time before a change event is processed. If the /// duration is set too low, some systems might surface events _before_ their filesystem has the changes. - #[allow(unused)] + #[cfg_attr( + any( + not(feature = "file_watcher"), + target_arch = "wasm32", + target_os = "android" + ), + expect( + unused_variables, + reason = "The `path` and `file_debounce_wait_time` arguments are unused when on WASM, Android, or if the `file_watcher` feature is disabled." + ) + )] pub fn get_default_watcher( path: String, file_debounce_wait_time: Duration, diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index 26092d976f0bf..6220af7c019c2 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -139,7 +139,8 @@ //! This trait mirrors [`AssetLoader`] in structure, and works in tandem with [`AssetWriter`](io::AssetWriter), which mirrors [`AssetReader`](io::AssetReader). // FIXME(3492): remove once docs are ready -#![allow(missing_docs)] +// FIXME(15321): solve CI failures, then replace with `#![expect()]`. +#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", diff --git a/crates/bevy_asset/src/loader.rs b/crates/bevy_asset/src/loader.rs index f8521b4cdabf1..401c7db6097bb 100644 --- a/crates/bevy_asset/src/loader.rs +++ b/crates/bevy_asset/src/loader.rs @@ -256,7 +256,7 @@ impl ErasedLoadedAsset { /// Cast this loaded asset as the given type. If the type does not match, /// the original type-erased asset is returned. - #[allow(clippy::result_large_err)] + #[expect(clippy::result_large_err, reason = "Function returns `Self` on error.")] pub fn downcast(mut self) -> Result, ErasedLoadedAsset> { match self.value.downcast::() { Ok(value) => Ok(LoadedAsset { diff --git a/crates/bevy_asset/src/processor/mod.rs b/crates/bevy_asset/src/processor/mod.rs index 31ddb33b7773f..d842ceec52e93 100644 --- a/crates/bevy_asset/src/processor/mod.rs +++ b/crates/bevy_asset/src/processor/mod.rs @@ -76,7 +76,7 @@ use std::{ use thiserror::Error; // Needed for doc strings -#[allow(unused_imports)] +#[allow(unused_imports, reason = "Needed for documentation links.")] use crate::io::{AssetReader, AssetWriter}; /// 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 { /// This info will later be used to determine whether or not to re-process an asset /// /// This will validate transactions and recover failed transactions when necessary. - #[allow(unused)] + #[cfg_attr( + any(target_arch = "wasm32", not(feature = "multi_threaded")), + expect( + dead_code, + reason = "This function is only used when the `multi_threaded` feature is enabled, and when not on WASM." + ) + )] async fn initialize(&self) -> Result<(), InitializeError> { self.validate_transaction_log_and_recover().await; let mut asset_infos = self.data.asset_infos.write().await; diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs index a74a8b7fa5a0f..21f2a5fa7e2d1 100644 --- a/crates/bevy_asset/src/reflect.rs +++ b/crates/bevy_asset/src/reflect.rs @@ -46,14 +46,19 @@ impl ReflectAsset { } /// Equivalent of [`Assets::get_mut`] - #[allow(unsafe_code)] pub fn get_mut<'w>( &self, world: &'w mut World, handle: UntypedHandle, ) -> Option<&'w mut dyn Reflect> { // SAFETY: unique world access - unsafe { (self.get_unchecked_mut)(world.as_unsafe_world_cell(), handle) } + #[expect( + unsafe_code, + reason = "Use of unsafe `Self::get_unchecked_mut()` function." + )] + unsafe { + (self.get_unchecked_mut)(world.as_unsafe_world_cell(), handle) + } } /// Equivalent of [`Assets::get_mut`], but works with an [`UnsafeWorldCell`]. @@ -83,7 +88,10 @@ impl ReflectAsset { /// violating Rust's aliasing rules. To avoid this: /// * Only call this method if you know that the [`UnsafeWorldCell`] may be used to access the corresponding `Assets` /// * Don't call this method more than once in the same scope. - #[allow(unsafe_code)] + #[expect( + unsafe_code, + reason = "This function calls unsafe code and has safety requirements." + )] pub unsafe fn get_unchecked_mut<'w>( &self, world: UnsafeWorldCell<'w>, @@ -108,7 +116,6 @@ impl ReflectAsset { } /// Equivalent of [`Assets::len`] - #[allow(clippy::len_without_is_empty)] // clippy expects the `is_empty` method to have the signature `(&self) -> bool` pub fn len(&self, world: &World) -> usize { (self.len)(world) } @@ -137,7 +144,7 @@ impl FromType for ReflectAsset { get_unchecked_mut: |world, handle| { // SAFETY: `get_unchecked_mut` must be called with `UnsafeWorldCell` having access to `Assets`, // and must ensure to only have at most one reference to it live at all times. - #[allow(unsafe_code)] + #[expect(unsafe_code, reason = "Uses `UnsafeWorldCell::get_resource_mut()`.")] let assets = unsafe { world.get_resource_mut::>().unwrap().into_inner() }; let asset = assets.get_mut(&handle.typed_debug_checked()); asset.map(|asset| asset as &mut dyn Reflect) diff --git a/crates/bevy_asset/src/server/info.rs b/crates/bevy_asset/src/server/info.rs index 82bc285f21edb..b8e6840c1f0cf 100644 --- a/crates/bevy_asset/src/server/info.rs +++ b/crates/bevy_asset/src/server/info.rs @@ -111,7 +111,10 @@ impl AssetInfos { .unwrap() } - #[allow(clippy::too_many_arguments)] + #[expect( + clippy::too_many_arguments, + reason = "Arguments needed so that both `create_loading_handle_untyped()` and `get_or_create_path_handle_internal()` may share code." + )] fn create_handle_internal( infos: &mut HashMap, handle_providers: &TypeIdMap, diff --git a/crates/bevy_asset/src/server/mod.rs b/crates/bevy_asset/src/server/mod.rs index 1053bd7f955ff..ea25b4d9ef26d 100644 --- a/crates/bevy_asset/src/server/mod.rs +++ b/crates/bevy_asset/src/server/mod.rs @@ -32,8 +32,7 @@ use std::{any::TypeId, path::Path, sync::Arc}; use std::{future::Future, panic::AssertUnwindSafe}; use thiserror::Error; -// Needed for doc string -#[allow(unused_imports)] +#[allow(unused_imports, reason = "Needed for documentation links.")] use crate::io::{AssetReader, AssetWriter}; /// 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) { } /// Internal events for asset load results -#[allow(clippy::large_enum_variant)] pub(crate) enum InternalAssetEvent { Loaded { id: UntypedAssetId, diff --git a/crates/bevy_core_pipeline/src/lib.rs b/crates/bevy_core_pipeline/src/lib.rs index 98c00c0c74732..27b9e9195f2e7 100644 --- a/crates/bevy_core_pipeline/src/lib.rs +++ b/crates/bevy_core_pipeline/src/lib.rs @@ -1,5 +1,5 @@ -// FIXME(3492): remove once docs are ready -#![allow(missing_docs)] +// FIXME(15321): solve CI failures, then replace with `#![expect()]`. +#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] #![forbid(unsafe_code)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![doc( diff --git a/crates/bevy_core_pipeline/src/skybox/prepass.rs b/crates/bevy_core_pipeline/src/skybox/prepass.rs index f6f47d01167bc..fb8df89b4b602 100644 --- a/crates/bevy_core_pipeline/src/skybox/prepass.rs +++ b/crates/bevy_core_pipeline/src/skybox/prepass.rs @@ -1,5 +1,3 @@ -#![warn(missing_docs)] - //! Adds motion vector support to skyboxes. See [`SkyboxPrepassPipeline`] for details. use bevy_asset::Handle; diff --git a/crates/bevy_derive/src/lib.rs b/crates/bevy_derive/src/lib.rs index 2151f4d09fe79..0225a7cb5a386 100644 --- a/crates/bevy_derive/src/lib.rs +++ b/crates/bevy_derive/src/lib.rs @@ -1,5 +1,5 @@ -// FIXME(3492): remove once docs are ready -#![allow(missing_docs)] +// FIXME(15321): solve CI failures, then replace with `#![expect()]`. +#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] #![forbid(unsafe_code)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![doc( diff --git a/crates/bevy_diagnostic/src/lib.rs b/crates/bevy_diagnostic/src/lib.rs index bbb2de4fb10d3..88fdac61035e0 100644 --- a/crates/bevy_diagnostic/src/lib.rs +++ b/crates/bevy_diagnostic/src/lib.rs @@ -1,5 +1,5 @@ -// FIXME(3492): remove once docs are ready -#![allow(missing_docs)] +// FIXME(15321): solve CI failures, then replace with `#![expect()]`. +#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![forbid(unsafe_code)] #![doc( diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index f33659ca148b1..fd7c3e3f9c507 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -1,5 +1,5 @@ -// FIXME(3492): remove once docs are ready -#![allow(missing_docs)] +// FIXME(15321): solve CI failures, then replace with `#![expect()]`. +#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] extern crate proc_macro; diff --git a/crates/bevy_ecs/macros/src/query_data.rs b/crates/bevy_ecs/macros/src/query_data.rs index 9480bfbadf42a..0a78b705a062e 100644 --- a/crates/bevy_ecs/macros/src/query_data.rs +++ b/crates/bevy_ecs/macros/src/query_data.rs @@ -104,7 +104,6 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream { let read_only_struct_name = if attributes.is_mutable { Ident::new(&format!("{struct_name}ReadOnly"), Span::call_site()) } else { - #[allow(clippy::redundant_clone)] struct_name.clone() }; @@ -112,7 +111,6 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream { let read_only_item_struct_name = if attributes.is_mutable { Ident::new(&format!("{struct_name}ReadOnlyItem"), Span::call_site()) } else { - #[allow(clippy::redundant_clone)] item_struct_name.clone() }; @@ -122,7 +120,6 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream { let new_ident = Ident::new(&format!("{struct_name}ReadOnlyFetch"), Span::call_site()); ensure_no_collision(new_ident, tokens.clone()) } else { - #[allow(clippy::redundant_clone)] fetch_struct_name.clone() }; diff --git a/crates/bevy_ecs/macros/src/world_query.rs b/crates/bevy_ecs/macros/src/world_query.rs index 9af4e2b3a148a..9d97f185dede9 100644 --- a/crates/bevy_ecs/macros/src/world_query.rs +++ b/crates/bevy_ecs/macros/src/world_query.rs @@ -2,7 +2,10 @@ use proc_macro2::Ident; use quote::quote; use syn::{Attribute, Fields, ImplGenerics, TypeGenerics, Visibility, WhereClause}; -#[allow(clippy::too_many_arguments)] +#[expect( + clippy::too_many_arguments, + reason = "Required to generate the entire item structure." +)] pub(crate) fn item_struct( path: &syn::Path, fields: &Fields, @@ -52,7 +55,10 @@ pub(crate) fn item_struct( } } -#[allow(clippy::too_many_arguments)] +#[expect( + clippy::too_many_arguments, + reason = "Required to generate the entire world query implementation." +)] pub(crate) fn world_query_impl( path: &syn::Path, struct_name: &Ident, diff --git a/crates/bevy_ecs/src/schedule/schedule.rs b/crates/bevy_ecs/src/schedule/schedule.rs index b9ffa1b9149a0..5b7756ab1369e 100644 --- a/crates/bevy_ecs/src/schedule/schedule.rs +++ b/crates/bevy_ecs/src/schedule/schedule.rs @@ -1893,7 +1893,7 @@ impl ScheduleGraph { &'a self, ambiguities: &'a [(NodeId, NodeId, Vec)], components: &'a Components, - ) -> impl Iterator)> + 'a { + ) -> impl Iterator)> + 'a { ambiguities .iter() .map(move |(system_a, system_b, conflicts)| { diff --git a/crates/bevy_encase_derive/src/lib.rs b/crates/bevy_encase_derive/src/lib.rs index a6d225dff1f8a..b38c657226794 100644 --- a/crates/bevy_encase_derive/src/lib.rs +++ b/crates/bevy_encase_derive/src/lib.rs @@ -1,5 +1,5 @@ -// FIXME(3492): remove once docs are ready -#![allow(missing_docs)] +// FIXME(15321): solve CI failures, then replace with `#![expect()]`. +#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] #![forbid(unsafe_code)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![doc( diff --git a/crates/bevy_log/src/lib.rs b/crates/bevy_log/src/lib.rs index 0cbb6b207d4bf..00e82e64f6667 100644 --- a/crates/bevy_log/src/lib.rs +++ b/crates/bevy_log/src/lib.rs @@ -67,7 +67,10 @@ use {bevy_ecs::system::Resource, bevy_utils::synccell::SyncCell}; /// Wrapper resource for `tracing-chrome`'s flush guard. /// When the guard is dropped the chrome log is written to file. #[cfg(feature = "tracing-chrome")] -#[allow(dead_code)] +#[expect( + dead_code, + reason = "`FlushGuard` never needs to be read, it just needs to be kept alive for the `App`'s lifetime." +)] #[derive(Resource)] pub(crate) struct FlushGuard(SyncCell); @@ -187,7 +190,6 @@ impl Default for LogPlugin { } impl Plugin for LogPlugin { - #[cfg_attr(not(feature = "tracing-chrome"), allow(unused_variables))] fn build(&self, app: &mut App) { #[cfg(feature = "trace")] { diff --git a/crates/bevy_mikktspace/src/lib.rs b/crates/bevy_mikktspace/src/lib.rs index d383f8ad5c447..50526edab2dba 100644 --- a/crates/bevy_mikktspace/src/lib.rs +++ b/crates/bevy_mikktspace/src/lib.rs @@ -2,10 +2,10 @@ unsafe_op_in_unsafe_fn, clippy::all, clippy::undocumented_unsafe_blocks, - clippy::ptr_cast_constness + clippy::ptr_cast_constness, + // FIXME(15321): solve CI failures, then replace with `#![expect()]`. + missing_docs )] -// FIXME(3492): remove once docs are ready -#![allow(missing_docs)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index ed570853630b3..59cdf3e33bb88 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -1,5 +1,5 @@ -// FIXME(3492): remove once docs are ready -#![allow(missing_docs)] +// FIXME(15321): solve CI failures, then replace with `#![expect()]`. +#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![deny(unsafe_code)] #![doc( diff --git a/crates/bevy_picking/src/backend.rs b/crates/bevy_picking/src/backend.rs index 03bb26ee2e489..8f29a5a300323 100644 --- a/crates/bevy_picking/src/backend.rs +++ b/crates/bevy_picking/src/backend.rs @@ -84,7 +84,8 @@ pub struct PointerHits { } impl PointerHits { - #[allow(missing_docs)] + // FIXME(15321): solve CI failures, then replace with `#[expect()]`. + #[allow(missing_docs, reason = "Not all docs are written yet (#3492).")] pub fn new(pointer: prelude::PointerId, picks: Vec<(Entity, HitData)>, order: f32) -> Self { Self { pointer, @@ -112,7 +113,8 @@ pub struct HitData { } impl HitData { - #[allow(missing_docs)] + // FIXME(15321): solve CI failures, then replace with `#[expect()]`. + #[allow(missing_docs, reason = "Not all docs are written yet (#3492).")] pub fn new(camera: Entity, depth: f32, position: Option, normal: Option) -> Self { Self { camera, diff --git a/crates/bevy_ptr/src/lib.rs b/crates/bevy_ptr/src/lib.rs index bcfd060f01f50..f083c6a3b8fb9 100644 --- a/crates/bevy_ptr/src/lib.rs +++ b/crates/bevy_ptr/src/lib.rs @@ -1,7 +1,7 @@ #![doc = include_str!("../README.md")] #![no_std] #![cfg_attr(docsrs, feature(doc_auto_cfg))] -#![allow(unsafe_code)] +#![expect(unsafe_code, reason = "Raw pointers are inherently unsafe.")] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" @@ -312,7 +312,6 @@ impl<'a, A: IsAligned> Ptr<'a, A> { /// If possible, it is strongly encouraged to use [`deref`](Self::deref) over this function, /// as it retains the lifetime. #[inline] - #[allow(clippy::wrong_self_convention)] pub fn as_ptr(self) -> *mut u8 { self.0.as_ptr() } @@ -368,7 +367,6 @@ impl<'a, A: IsAligned> PtrMut<'a, A> { /// If possible, it is strongly encouraged to use [`deref_mut`](Self::deref_mut) over /// this function, as it retains the lifetime. #[inline] - #[allow(clippy::wrong_self_convention)] pub fn as_ptr(&self) -> *mut u8 { self.0.as_ptr() } @@ -455,7 +453,6 @@ impl<'a, A: IsAligned> OwningPtr<'a, A> { /// If possible, it is strongly encouraged to use the other more type-safe functions /// over this function. #[inline] - #[allow(clippy::wrong_self_convention)] pub fn as_ptr(&self) -> *mut u8 { self.0.as_ptr() } diff --git a/crates/bevy_reflect/derive/src/container_attributes.rs b/crates/bevy_reflect/derive/src/container_attributes.rs index b5f0f906b3bcc..be1e5d52b4f11 100644 --- a/crates/bevy_reflect/derive/src/container_attributes.rs +++ b/crates/bevy_reflect/derive/src/container_attributes.rs @@ -434,7 +434,10 @@ impl ContainerAttributes { } /// The `FromReflect` configuration found within `#[reflect(...)]` attributes on this type. - #[allow(clippy::wrong_self_convention)] + #[expect( + clippy::wrong_self_convention, + reason = "Method returns `FromReflectAttrs`, does not actually convert data." + )] pub fn from_reflect_attrs(&self) -> &FromReflectAttrs { &self.from_reflect_attrs } diff --git a/crates/bevy_reflect/derive/src/derive_data.rs b/crates/bevy_reflect/derive/src/derive_data.rs index edb11f3ef3253..7ae1d4f473b2c 100644 --- a/crates/bevy_reflect/derive/src/derive_data.rs +++ b/crates/bevy_reflect/derive/src/derive_data.rs @@ -121,11 +121,7 @@ pub(crate) struct EnumVariant<'a> { /// The fields within this variant. pub fields: EnumVariantFields<'a>, /// The reflection-based attributes on the variant. - #[allow(dead_code)] pub attrs: FieldAttributes, - /// The index of this variant within the enum. - #[allow(dead_code)] - pub index: usize, /// The documentation for this variant, if any #[cfg(feature = "documentation")] pub doc: crate::documentation::Documentation, @@ -440,8 +436,7 @@ impl<'a> ReflectDerive<'a> { ) -> Result>, syn::Error> { let sifter: utility::ResultSifter> = variants .iter() - .enumerate() - .map(|(index, variant)| -> Result { + .map(|variant| -> Result { let fields = Self::collect_struct_fields(&variant.fields)?; let fields = match variant.fields { @@ -453,7 +448,6 @@ impl<'a> ReflectDerive<'a> { fields, attrs: FieldAttributes::parse_attributes(&variant.attrs)?, data: variant, - index, #[cfg(feature = "documentation")] doc: crate::documentation::Documentation::from_attributes(&variant.attrs), }) @@ -491,7 +485,10 @@ impl<'a> ReflectMeta<'a> { } /// The `FromReflect` attributes on this type. - #[allow(clippy::wrong_self_convention)] + #[expect( + clippy::wrong_self_convention, + reason = "Method returns `FromReflectAttrs`, does not actually convert data." + )] pub fn from_reflect(&self) -> &FromReflectAttrs { self.attrs.from_reflect_attrs() } @@ -562,7 +559,13 @@ impl<'a> StructField<'a> { let ty = self.reflected_type(); let custom_attributes = self.attrs.custom_attributes.to_tokens(bevy_reflect_path); - #[allow(unused_mut)] // Needs mutability for the feature gate + #[cfg_attr( + not(feature = "documentation"), + expect( + unused_mut, + reason = "Needs to be mutable if `documentation` feature is enabled.", + ) + )] let mut info = quote! { #field_info::new::<#ty>(#name).with_custom_attributes(#custom_attributes) }; @@ -674,7 +677,13 @@ impl<'a> ReflectStruct<'a> { .custom_attributes() .to_tokens(bevy_reflect_path); - #[allow(unused_mut)] // Needs mutability for the feature gate + #[cfg_attr( + not(feature = "documentation"), + expect( + unused_mut, + reason = "Needs to be mutable if `documentation` feature is enabled.", + ) + )] let mut info = quote! { #bevy_reflect_path::#info_struct::new::(&[ #(#field_infos),* @@ -771,7 +780,13 @@ impl<'a> ReflectEnum<'a> { .custom_attributes() .to_tokens(bevy_reflect_path); - #[allow(unused_mut)] // Needs mutability for the feature gate + #[cfg_attr( + not(feature = "documentation"), + expect( + unused_mut, + reason = "Needs to be mutable if `documentation` feature is enabled.", + ) + )] let mut info = quote! { #bevy_reflect_path::EnumInfo::new::(&[ #(#variants),* @@ -802,7 +817,6 @@ impl<'a> EnumVariant<'a> { } /// The complete set of fields in this variant. - #[allow(dead_code)] pub fn fields(&self) -> &[StructField<'a>] { match &self.fields { EnumVariantFields::Named(fields) | EnumVariantFields::Unnamed(fields) => fields, @@ -842,7 +856,13 @@ impl<'a> EnumVariant<'a> { let custom_attributes = self.attrs.custom_attributes.to_tokens(bevy_reflect_path); - #[allow(unused_mut)] // Needs mutability for the feature gate + #[cfg_attr( + not(feature = "documentation"), + expect( + unused_mut, + reason = "Needs to be mutable if `documentation` feature is enabled.", + ) + )] let mut info = quote! { #bevy_reflect_path::#info_struct::new(#args) .with_custom_attributes(#custom_attributes) @@ -922,8 +942,10 @@ pub(crate) enum ReflectTypePath<'a> { generics: &'a Generics, }, /// Any [`Type`] with only a defined `type_path` and `short_type_path`. - #[allow(dead_code)] - // Not currently used but may be useful in the future due to its generality. + #[expect( + dead_code, + reason = "Not currently used but may be useful in the future due to its generality." + )] Anonymous { qualified_type: Type, long_type_path: StringExpr, diff --git a/crates/bevy_reflect/derive/src/reflect_value.rs b/crates/bevy_reflect/derive/src/reflect_value.rs index 6faa0e8752d45..04cfd6a976f5a 100644 --- a/crates/bevy_reflect/derive/src/reflect_value.rs +++ b/crates/bevy_reflect/derive/src/reflect_value.rs @@ -25,7 +25,13 @@ use syn::{parenthesized, Attribute, Generics, Path}; /// (in my_crate::bar) Bar(TraitA, TraitB) /// ``` pub(crate) struct ReflectValueDef { - #[allow(dead_code)] + #[cfg_attr( + not(feature = "documentation"), + expect( + dead_code, + reason = "The is used when the `documentation` feature is enabled.", + ) + )] pub attrs: Vec, pub type_path: Path, pub generics: Generics, diff --git a/crates/bevy_reflect/derive/src/registration.rs b/crates/bevy_reflect/derive/src/registration.rs index d277d823c59f9..5d17e8954e5fc 100644 --- a/crates/bevy_reflect/derive/src/registration.rs +++ b/crates/bevy_reflect/derive/src/registration.rs @@ -7,7 +7,6 @@ use quote::quote; use syn::Type; /// Creates the `GetTypeRegistration` impl for the given type data. -#[allow(clippy::too_many_arguments)] pub(crate) fn impl_get_type_registration<'a>( meta: &ReflectMeta, where_clause_options: &WhereClauseOptions, diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 8685fb07d8b98..7af6020005ecd 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1,5 +1,5 @@ -// FIXME(3492): remove once docs are ready -#![allow(missing_docs)] +// FIXME(15321): solve CI failures, then replace with `#![expect()]`. +#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] // `rustdoc_internals` is needed for `#[doc(fake_variadics)]` #![allow(internal_features)] #![cfg_attr(any(docsrs, docsrs_dep), feature(doc_auto_cfg, rustdoc_internals))] diff --git a/crates/bevy_render/macros/src/lib.rs b/crates/bevy_render/macros/src/lib.rs index 5398037e5b28e..6d837fb095f5c 100644 --- a/crates/bevy_render/macros/src/lib.rs +++ b/crates/bevy_render/macros/src/lib.rs @@ -1,5 +1,5 @@ -// FIXME(3492): remove once docs are ready -#![allow(missing_docs)] +// FIXME(15321): solve CI failures, then replace with `#![expect()]`. +#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] mod as_bind_group; diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index ef1039920c6f1..e6c35f0783568 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -1,5 +1,5 @@ -// FIXME(3492): remove once docs are ready -#![allow(missing_docs)] +// FIXME(15321): solve CI failures, then replace with `#![expect()]`. +#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] #![allow(unsafe_code)] // `rustdoc_internals` is needed for `#[doc(fake_variadics)]` #![allow(internal_features)] diff --git a/crates/bevy_sprite/src/lib.rs b/crates/bevy_sprite/src/lib.rs index a907d85dd5a6b..7dd930b22d8ed 100644 --- a/crates/bevy_sprite/src/lib.rs +++ b/crates/bevy_sprite/src/lib.rs @@ -1,5 +1,5 @@ -// FIXME(3492): remove once docs are ready -#![allow(missing_docs)] +// FIXME(15321): solve CI failures, then replace with `#![expect()]`. +#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![forbid(unsafe_code)] #![doc( diff --git a/crates/bevy_state/macros/src/lib.rs b/crates/bevy_state/macros/src/lib.rs index 7d401a4793612..b18895cdb86ad 100644 --- a/crates/bevy_state/macros/src/lib.rs +++ b/crates/bevy_state/macros/src/lib.rs @@ -1,5 +1,5 @@ -// FIXME(3492): remove once docs are ready -#![allow(missing_docs)] +// FIXME(15321): solve CI failures, then replace with `#![expect()]`. +#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] extern crate proc_macro; diff --git a/crates/bevy_tasks/src/single_threaded_task_pool.rs b/crates/bevy_tasks/src/single_threaded_task_pool.rs index cd6bbc79d63ad..7022405cc2b55 100644 --- a/crates/bevy_tasks/src/single_threaded_task_pool.rs +++ b/crates/bevy_tasks/src/single_threaded_task_pool.rs @@ -68,7 +68,6 @@ impl TaskPool { TaskPoolBuilder::new().build() } - #[allow(unused_variables)] fn new_internal() -> Self { Self {} } @@ -96,7 +95,7 @@ impl TaskPool { /// to spawn tasks. This function will await the completion of all tasks before returning. /// /// This is similar to `rayon::scope` and `crossbeam::scope` - #[allow(unsafe_code)] + #[expect(unsafe_code, reason = "Required to transmute lifetimes.")] pub fn scope_with_executor<'env, F, T>( &self, _tick_task_pool_executor: bool, diff --git a/crates/bevy_tasks/src/task_pool.rs b/crates/bevy_tasks/src/task_pool.rs index dd892e7decc77..cd395a35fd2ce 100644 --- a/crates/bevy_tasks/src/task_pool.rs +++ b/crates/bevy_tasks/src/task_pool.rs @@ -330,7 +330,7 @@ impl TaskPool { }) } - #[allow(unsafe_code)] + #[expect(unsafe_code, reason = "Required to transmute lifetimes.")] fn scope_with_executor_inner<'env, F, T>( &self, tick_task_pool_executor: bool, diff --git a/crates/bevy_time/src/lib.rs b/crates/bevy_time/src/lib.rs index 8cb1c77ab8a8f..794423b196314 100644 --- a/crates/bevy_time/src/lib.rs +++ b/crates/bevy_time/src/lib.rs @@ -11,7 +11,6 @@ pub mod common_conditions; mod fixed; mod real; mod stopwatch; -#[allow(clippy::module_inception)] mod time; mod timer; mod virt; @@ -44,9 +43,9 @@ use crossbeam_channel::{Receiver, Sender}; #[derive(Default)] pub struct TimePlugin; -#[derive(Debug, PartialEq, Eq, Clone, Hash, SystemSet)] /// Updates the elapsed time. Any system that interacts with [`Time`] component should run after /// this. +#[derive(Debug, PartialEq, Eq, Clone, Hash, SystemSet)] pub struct TimeSystem; impl Plugin for TimePlugin { diff --git a/crates/bevy_transform/src/systems.rs b/crates/bevy_transform/src/systems.rs index d6113f3c093f7..c1a1df063171a 100644 --- a/crates/bevy_transform/src/systems.rs +++ b/crates/bevy_transform/src/systems.rs @@ -79,7 +79,7 @@ pub fn propagate_transforms( // - Since each root entity is unique and the hierarchy is consistent and forest-like, // other root entities' `propagate_recursive` calls will not conflict with this one. // - Since this is the only place where `transform_query` gets used, there will be no conflicting fetches elsewhere. - #[allow(unsafe_code)] + #[expect(unsafe_code, reason = "`propagate_recursive()` is unsafe due to its use of `Query::get_unchecked()`.")] unsafe { propagate_recursive( &global_transform, @@ -107,7 +107,10 @@ pub fn propagate_transforms( /// nor any of its descendants. /// - The caller must ensure that the hierarchy leading to `entity` /// is well-formed and must remain as a tree or a forest. Each entity must have at most one parent. -#[allow(unsafe_code)] +#[expect( + unsafe_code, + reason = "This function uses `Query::get_unchecked()`, which can result in multiple mutable references if the preconditions are not met." +)] unsafe fn propagate_recursive( parent: &GlobalTransform, transform_query: &Query< diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index f55e875de22c4..5a366b782e038 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -1,5 +1,5 @@ -// FIXME(3492): remove once docs are ready -#![allow(missing_docs)] +// FIXME(15321): solve CI failures, then replace with `#![expect()]`. +#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", diff --git a/crates/bevy_utils/macros/src/lib.rs b/crates/bevy_utils/macros/src/lib.rs index 4e539ebe435fa..78803cf079e9a 100644 --- a/crates/bevy_utils/macros/src/lib.rs +++ b/crates/bevy_utils/macros/src/lib.rs @@ -1,5 +1,5 @@ -// FIXME(3492): remove once docs are ready -#![allow(missing_docs)] +// FIXME(15321): solve CI failures, then replace with `#![expect()]`. +#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] use proc_macro::TokenStream; diff --git a/crates/bevy_utils/src/lib.rs b/crates/bevy_utils/src/lib.rs index 3d231cf0cff75..eaa197c0384ea 100644 --- a/crates/bevy_utils/src/lib.rs +++ b/crates/bevy_utils/src/lib.rs @@ -1,5 +1,8 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] -#![allow(unsafe_code)] +#![expect( + unsafe_code, + reason = "Some utilities, such as futures and cells, require unsafe code." +)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" @@ -63,7 +66,7 @@ mod conditional_send { } #[cfg(target_arch = "wasm32")] -#[allow(missing_docs)] +#[expect(missing_docs, reason = "Not all docs are written yet (#3492).")] mod conditional_send { pub trait ConditionalSend {} impl ConditionalSend for T {} diff --git a/crates/bevy_window/src/event.rs b/crates/bevy_window/src/event.rs index 2334024fbafc9..f7f0fd55c8983 100644 --- a/crates/bevy_window/src/event.rs +++ b/crates/bevy_window/src/event.rs @@ -413,7 +413,8 @@ impl AppLifecycle { derive(serde::Serialize, serde::Deserialize), reflect(Serialize, Deserialize) )] -#[allow(missing_docs)] +// FIXME(15321): solve CI failures, then replace with `#[expect()]`. +#[allow(missing_docs, reason = "Not all docs are written yet (#3492).")] pub enum WindowEvent { AppLifecycle(AppLifecycle), CursorEntered(CursorEntered),