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 <ben.frankel7@gmail.com>
Co-authored-by: Antony <antony.m.3012@gmail.com>
This commit is contained in:
Rich Churcher 2024-09-21 07:16:42 +12:00 committed by GitHub
parent ebb57c5511
commit fd329c0426
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
44 changed files with 182 additions and 100 deletions

View file

@ -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.80.0" rust-version = "1.81.0"
[workspace] [workspace]
exclude = [ exclude = [

View file

@ -40,7 +40,6 @@ pub(crate) enum AppError {
DuplicatePlugin { plugin_name: String }, DuplicatePlugin { plugin_name: String },
} }
#[allow(clippy::needless_doctest_main)]
/// [`App`] is the primary API for writing user applications. It automates the setup of a /// [`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`). /// [standard lifecycle](Main) and provides interface glue for [plugins](`Plugin`).
/// ///

View file

@ -167,7 +167,9 @@ mod sealed {
where where
$($plugins: Plugins<$param>),* $($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] #[track_caller]
fn add_to_app(self, app: &mut App) { fn add_to_app(self, app: &mut App) {
let ($($plugins,)*) = self; let ($($plugins,)*) = self;

View file

@ -279,7 +279,10 @@ impl PluginGroupBuilder {
/// Adds the plugin [`Plugin`] at the end of this [`PluginGroupBuilder`]. If the plugin was /// 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. /// already in the group, it is removed from its previous place.
// This is not confusing, clippy! // 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<T: Plugin>(mut self, plugin: T) -> Self { pub fn add<T: Plugin>(mut self, plugin: T) -> Self {
let target_index = self.order.len(); let target_index = self.order.len();
self.order.push(TypeId::of::<T>()); self.order.push(TypeId::of::<T>());

View file

@ -1,5 +1,5 @@
// FIXME(3492): remove once docs are ready // FIXME(15321): solve CI failures, then replace with `#![expect()]`.
#![allow(missing_docs)] #![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")]
#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![cfg_attr(docsrs, feature(doc_auto_cfg))]
use bevy_macro_utils::BevyManifest; use bevy_macro_utils::BevyManifest;

View file

@ -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` /// 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]` /// [`AssetSource`]. `value` is the bytes that will be returned for the asset. This can be _either_ a `&'static [u8]`
/// or a [`Vec<u8>`]. /// or a [`Vec<u8>`].
#[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<Value>) { pub fn insert_asset(&self, full_path: PathBuf, asset_path: &Path, value: impl Into<Value>) {
#[cfg(feature = "embedded_watcher")] #[cfg(feature = "embedded_watcher")]
self.root_paths 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` /// 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]` /// [`AssetSource`]. `value` is the bytes that will be returned for the asset. This can be _either_ a `&'static [u8]`
/// or a [`Vec<u8>`]. /// or a [`Vec<u8>`].
#[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<Value>) { pub fn insert_meta(&self, full_path: &Path, asset_path: &Path, value: impl Into<Value>) {
#[cfg(feature = "embedded_watcher")] #[cfg(feature = "embedded_watcher")]
self.root_paths self.root_paths
@ -59,12 +71,17 @@ impl EmbeddedAssetRegistry {
self.dir.remove_asset(full_path) 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) { pub fn register_source(&self, sources: &mut AssetSourceBuilders) {
let dir = self.dir.clone(); let dir = self.dir.clone();
let processed_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() let mut source = AssetSource::build()
.with_reader(move || Box::new(MemoryAssetReader { root: dir.clone() })) .with_reader(move || Box::new(MemoryAssetReader { root: dir.clone() }))
.with_processed_reader(move || { .with_processed_reader(move || {

View file

@ -11,8 +11,7 @@ use thiserror::Error;
use super::{ErasedAssetReader, ErasedAssetWriter}; use super::{ErasedAssetReader, ErasedAssetWriter};
// Needed for doc strings. #[allow(unused_imports, reason = "Needed for documentation links.")]
#[allow(unused_imports)]
use crate::io::{AssetReader, AssetWriter}; use crate::io::{AssetReader, AssetWriter};
/// A reference to an "asset source", which maps to an [`AssetReader`] and/or [`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. /// `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 /// 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. /// 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( pub fn get_default_watcher(
path: String, path: String,
file_debounce_wait_time: Duration, file_debounce_wait_time: Duration,

View file

@ -139,7 +139,8 @@
//! This trait mirrors [`AssetLoader`] in structure, and works in tandem with [`AssetWriter`](io::AssetWriter), which mirrors [`AssetReader`](io::AssetReader). //! 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 // 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))] #![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![doc( #![doc(
html_logo_url = "https://bevyengine.org/assets/icon.png", html_logo_url = "https://bevyengine.org/assets/icon.png",

View file

@ -256,7 +256,7 @@ impl ErasedLoadedAsset {
/// Cast this loaded asset as the given type. If the type does not match, /// Cast this loaded asset as the given type. If the type does not match,
/// the original type-erased asset is returned. /// 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<A: Asset>(mut self) -> Result<LoadedAsset<A>, ErasedLoadedAsset> { pub fn downcast<A: Asset>(mut self) -> Result<LoadedAsset<A>, ErasedLoadedAsset> {
match self.value.downcast::<A>() { match self.value.downcast::<A>() {
Ok(value) => Ok(LoadedAsset { Ok(value) => Ok(LoadedAsset {

View file

@ -76,7 +76,7 @@ use std::{
use thiserror::Error; use thiserror::Error;
// Needed for doc strings // Needed for doc strings
#[allow(unused_imports)] #[allow(unused_imports, reason = "Needed for documentation links.")]
use crate::io::{AssetReader, AssetWriter}; use crate::io::{AssetReader, AssetWriter};
/// A "background" asset processor that reads asset values from a source [`AssetSource`] (which corresponds to an [`AssetReader`] / [`AssetWriter`] pair), /// 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 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. /// 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> { async fn initialize(&self) -> Result<(), InitializeError> {
self.validate_transaction_log_and_recover().await; self.validate_transaction_log_and_recover().await;
let mut asset_infos = self.data.asset_infos.write().await; let mut asset_infos = self.data.asset_infos.write().await;

View file

@ -46,14 +46,19 @@ impl ReflectAsset {
} }
/// Equivalent of [`Assets::get_mut`] /// Equivalent of [`Assets::get_mut`]
#[allow(unsafe_code)]
pub fn get_mut<'w>( pub fn get_mut<'w>(
&self, &self,
world: &'w mut World, world: &'w mut World,
handle: UntypedHandle, handle: UntypedHandle,
) -> Option<&'w mut dyn Reflect> { ) -> Option<&'w mut dyn Reflect> {
// SAFETY: unique world access // 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`]. /// Equivalent of [`Assets::get_mut`], but works with an [`UnsafeWorldCell`].
@ -83,7 +88,10 @@ impl ReflectAsset {
/// violating Rust's aliasing rules. To avoid this: /// 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<T>` /// * Only call this method if you know that the [`UnsafeWorldCell`] may be used to access the corresponding `Assets<T>`
/// * Don't call this method more than once in the same scope. /// * 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>( pub unsafe fn get_unchecked_mut<'w>(
&self, &self,
world: UnsafeWorldCell<'w>, world: UnsafeWorldCell<'w>,
@ -108,7 +116,6 @@ impl ReflectAsset {
} }
/// Equivalent of [`Assets::len`] /// 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 { pub fn len(&self, world: &World) -> usize {
(self.len)(world) (self.len)(world)
} }
@ -137,7 +144,7 @@ impl<A: Asset + FromReflect> FromType<A> for ReflectAsset {
get_unchecked_mut: |world, handle| { get_unchecked_mut: |world, handle| {
// SAFETY: `get_unchecked_mut` must be called with `UnsafeWorldCell` having access to `Assets<A>`, // SAFETY: `get_unchecked_mut` must be called with `UnsafeWorldCell` having access to `Assets<A>`,
// and must ensure to only have at most one reference to it live at all times. // 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::<Assets<A>>().unwrap().into_inner() }; let assets = unsafe { world.get_resource_mut::<Assets<A>>().unwrap().into_inner() };
let asset = assets.get_mut(&handle.typed_debug_checked()); let asset = assets.get_mut(&handle.typed_debug_checked());
asset.map(|asset| asset as &mut dyn Reflect) asset.map(|asset| asset as &mut dyn Reflect)

View file

@ -111,7 +111,10 @@ impl AssetInfos {
.unwrap() .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( fn create_handle_internal(
infos: &mut HashMap<UntypedAssetId, AssetInfo>, infos: &mut HashMap<UntypedAssetId, AssetInfo>,
handle_providers: &TypeIdMap<AssetHandleProvider>, handle_providers: &TypeIdMap<AssetHandleProvider>,

View file

@ -32,8 +32,7 @@ use std::{any::TypeId, path::Path, sync::Arc};
use std::{future::Future, panic::AssertUnwindSafe}; use std::{future::Future, panic::AssertUnwindSafe};
use thiserror::Error; use thiserror::Error;
// Needed for doc string #[allow(unused_imports, reason = "Needed for documentation links.")]
#[allow(unused_imports)]
use crate::io::{AssetReader, AssetWriter}; 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 /// 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 /// Internal events for asset load results
#[allow(clippy::large_enum_variant)]
pub(crate) enum InternalAssetEvent { pub(crate) enum InternalAssetEvent {
Loaded { Loaded {
id: UntypedAssetId, id: UntypedAssetId,

View file

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

View file

@ -1,5 +1,3 @@
#![warn(missing_docs)]
//! Adds motion vector support to skyboxes. See [`SkyboxPrepassPipeline`] for details. //! Adds motion vector support to skyboxes. See [`SkyboxPrepassPipeline`] for details.
use bevy_asset::Handle; use bevy_asset::Handle;

View file

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

View file

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

View file

@ -1,5 +1,5 @@
// FIXME(3492): remove once docs are ready // FIXME(15321): solve CI failures, then replace with `#![expect()]`.
#![allow(missing_docs)] #![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")]
#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![cfg_attr(docsrs, feature(doc_auto_cfg))]
extern crate proc_macro; extern crate proc_macro;

View file

@ -104,7 +104,6 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
let read_only_struct_name = if attributes.is_mutable { let read_only_struct_name = if attributes.is_mutable {
Ident::new(&format!("{struct_name}ReadOnly"), Span::call_site()) Ident::new(&format!("{struct_name}ReadOnly"), Span::call_site())
} else { } else {
#[allow(clippy::redundant_clone)]
struct_name.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 { let read_only_item_struct_name = if attributes.is_mutable {
Ident::new(&format!("{struct_name}ReadOnlyItem"), Span::call_site()) Ident::new(&format!("{struct_name}ReadOnlyItem"), Span::call_site())
} else { } else {
#[allow(clippy::redundant_clone)]
item_struct_name.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()); let new_ident = Ident::new(&format!("{struct_name}ReadOnlyFetch"), Span::call_site());
ensure_no_collision(new_ident, tokens.clone()) ensure_no_collision(new_ident, tokens.clone())
} else { } else {
#[allow(clippy::redundant_clone)]
fetch_struct_name.clone() fetch_struct_name.clone()
}; };

View file

@ -2,7 +2,10 @@ use proc_macro2::Ident;
use quote::quote; use quote::quote;
use syn::{Attribute, Fields, ImplGenerics, TypeGenerics, Visibility, WhereClause}; 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( pub(crate) fn item_struct(
path: &syn::Path, path: &syn::Path,
fields: &Fields, 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( pub(crate) fn world_query_impl(
path: &syn::Path, path: &syn::Path,
struct_name: &Ident, struct_name: &Ident,

View file

@ -1893,7 +1893,7 @@ impl ScheduleGraph {
&'a self, &'a self,
ambiguities: &'a [(NodeId, NodeId, Vec<ComponentId>)], ambiguities: &'a [(NodeId, NodeId, Vec<ComponentId>)],
components: &'a Components, components: &'a Components,
) -> impl Iterator<Item = (String, String, Vec<&str>)> + 'a { ) -> impl Iterator<Item = (String, String, Vec<&'a str>)> + 'a {
ambiguities ambiguities
.iter() .iter()
.map(move |(system_a, system_b, conflicts)| { .map(move |(system_a, system_b, conflicts)| {

View file

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

View file

@ -67,7 +67,10 @@ use {bevy_ecs::system::Resource, bevy_utils::synccell::SyncCell};
/// Wrapper resource for `tracing-chrome`'s flush guard. /// Wrapper resource for `tracing-chrome`'s flush guard.
/// When the guard is dropped the chrome log is written to file. /// When the guard is dropped the chrome log is written to file.
#[cfg(feature = "tracing-chrome")] #[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)] #[derive(Resource)]
pub(crate) struct FlushGuard(SyncCell<tracing_chrome::FlushGuard>); pub(crate) struct FlushGuard(SyncCell<tracing_chrome::FlushGuard>);
@ -187,7 +190,6 @@ impl Default for LogPlugin {
} }
impl Plugin for LogPlugin { impl Plugin for LogPlugin {
#[cfg_attr(not(feature = "tracing-chrome"), allow(unused_variables))]
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
{ {

View file

@ -2,10 +2,10 @@
unsafe_op_in_unsafe_fn, unsafe_op_in_unsafe_fn,
clippy::all, clippy::all,
clippy::undocumented_unsafe_blocks, 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))] #![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![doc( #![doc(
html_logo_url = "https://bevyengine.org/assets/icon.png", html_logo_url = "https://bevyengine.org/assets/icon.png",

View file

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

View file

@ -84,7 +84,8 @@ pub struct PointerHits {
} }
impl 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 { pub fn new(pointer: prelude::PointerId, picks: Vec<(Entity, HitData)>, order: f32) -> Self {
Self { Self {
pointer, pointer,
@ -112,7 +113,8 @@ pub struct HitData {
} }
impl 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<Vec3>, normal: Option<Vec3>) -> Self { pub fn new(camera: Entity, depth: f32, position: Option<Vec3>, normal: Option<Vec3>) -> Self {
Self { Self {
camera, camera,

View file

@ -1,7 +1,7 @@
#![doc = include_str!("../README.md")] #![doc = include_str!("../README.md")]
#![no_std] #![no_std]
#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![allow(unsafe_code)] #![expect(unsafe_code, reason = "Raw pointers are inherently unsafe.")]
#![doc( #![doc(
html_logo_url = "https://bevyengine.org/assets/icon.png", html_logo_url = "https://bevyengine.org/assets/icon.png",
html_favicon_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, /// If possible, it is strongly encouraged to use [`deref`](Self::deref) over this function,
/// as it retains the lifetime. /// as it retains the lifetime.
#[inline] #[inline]
#[allow(clippy::wrong_self_convention)]
pub fn as_ptr(self) -> *mut u8 { pub fn as_ptr(self) -> *mut u8 {
self.0.as_ptr() 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 /// If possible, it is strongly encouraged to use [`deref_mut`](Self::deref_mut) over
/// this function, as it retains the lifetime. /// this function, as it retains the lifetime.
#[inline] #[inline]
#[allow(clippy::wrong_self_convention)]
pub fn as_ptr(&self) -> *mut u8 { pub fn as_ptr(&self) -> *mut u8 {
self.0.as_ptr() 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 /// If possible, it is strongly encouraged to use the other more type-safe functions
/// over this function. /// over this function.
#[inline] #[inline]
#[allow(clippy::wrong_self_convention)]
pub fn as_ptr(&self) -> *mut u8 { pub fn as_ptr(&self) -> *mut u8 {
self.0.as_ptr() self.0.as_ptr()
} }

View file

@ -434,7 +434,10 @@ impl ContainerAttributes {
} }
/// The `FromReflect` configuration found within `#[reflect(...)]` attributes on this type. /// 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 { pub fn from_reflect_attrs(&self) -> &FromReflectAttrs {
&self.from_reflect_attrs &self.from_reflect_attrs
} }

View file

@ -121,11 +121,7 @@ pub(crate) struct EnumVariant<'a> {
/// The fields within this variant. /// The fields within this variant.
pub fields: EnumVariantFields<'a>, pub fields: EnumVariantFields<'a>,
/// The reflection-based attributes on the variant. /// The reflection-based attributes on the variant.
#[allow(dead_code)]
pub attrs: FieldAttributes, pub attrs: FieldAttributes,
/// The index of this variant within the enum.
#[allow(dead_code)]
pub index: usize,
/// The documentation for this variant, if any /// The documentation for this variant, if any
#[cfg(feature = "documentation")] #[cfg(feature = "documentation")]
pub doc: crate::documentation::Documentation, pub doc: crate::documentation::Documentation,
@ -440,8 +436,7 @@ impl<'a> ReflectDerive<'a> {
) -> Result<Vec<EnumVariant<'a>>, syn::Error> { ) -> Result<Vec<EnumVariant<'a>>, syn::Error> {
let sifter: utility::ResultSifter<EnumVariant<'a>> = variants let sifter: utility::ResultSifter<EnumVariant<'a>> = variants
.iter() .iter()
.enumerate() .map(|variant| -> Result<EnumVariant, syn::Error> {
.map(|(index, variant)| -> Result<EnumVariant, syn::Error> {
let fields = Self::collect_struct_fields(&variant.fields)?; let fields = Self::collect_struct_fields(&variant.fields)?;
let fields = match variant.fields { let fields = match variant.fields {
@ -453,7 +448,6 @@ impl<'a> ReflectDerive<'a> {
fields, fields,
attrs: FieldAttributes::parse_attributes(&variant.attrs)?, attrs: FieldAttributes::parse_attributes(&variant.attrs)?,
data: variant, data: variant,
index,
#[cfg(feature = "documentation")] #[cfg(feature = "documentation")]
doc: crate::documentation::Documentation::from_attributes(&variant.attrs), doc: crate::documentation::Documentation::from_attributes(&variant.attrs),
}) })
@ -491,7 +485,10 @@ impl<'a> ReflectMeta<'a> {
} }
/// The `FromReflect` attributes on this type. /// 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 { pub fn from_reflect(&self) -> &FromReflectAttrs {
self.attrs.from_reflect_attrs() self.attrs.from_reflect_attrs()
} }
@ -562,7 +559,13 @@ impl<'a> StructField<'a> {
let ty = self.reflected_type(); let ty = self.reflected_type();
let custom_attributes = self.attrs.custom_attributes.to_tokens(bevy_reflect_path); 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! { let mut info = quote! {
#field_info::new::<#ty>(#name).with_custom_attributes(#custom_attributes) #field_info::new::<#ty>(#name).with_custom_attributes(#custom_attributes)
}; };
@ -674,7 +677,13 @@ impl<'a> ReflectStruct<'a> {
.custom_attributes() .custom_attributes()
.to_tokens(bevy_reflect_path); .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! { let mut info = quote! {
#bevy_reflect_path::#info_struct::new::<Self>(&[ #bevy_reflect_path::#info_struct::new::<Self>(&[
#(#field_infos),* #(#field_infos),*
@ -771,7 +780,13 @@ impl<'a> ReflectEnum<'a> {
.custom_attributes() .custom_attributes()
.to_tokens(bevy_reflect_path); .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! { let mut info = quote! {
#bevy_reflect_path::EnumInfo::new::<Self>(&[ #bevy_reflect_path::EnumInfo::new::<Self>(&[
#(#variants),* #(#variants),*
@ -802,7 +817,6 @@ impl<'a> EnumVariant<'a> {
} }
/// The complete set of fields in this variant. /// The complete set of fields in this variant.
#[allow(dead_code)]
pub fn fields(&self) -> &[StructField<'a>] { pub fn fields(&self) -> &[StructField<'a>] {
match &self.fields { match &self.fields {
EnumVariantFields::Named(fields) | EnumVariantFields::Unnamed(fields) => 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); 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! { let mut info = quote! {
#bevy_reflect_path::#info_struct::new(#args) #bevy_reflect_path::#info_struct::new(#args)
.with_custom_attributes(#custom_attributes) .with_custom_attributes(#custom_attributes)
@ -922,8 +942,10 @@ pub(crate) enum ReflectTypePath<'a> {
generics: &'a Generics, generics: &'a Generics,
}, },
/// Any [`Type`] with only a defined `type_path` and `short_type_path`. /// Any [`Type`] with only a defined `type_path` and `short_type_path`.
#[allow(dead_code)] #[expect(
// Not currently used but may be useful in the future due to its generality. dead_code,
reason = "Not currently used but may be useful in the future due to its generality."
)]
Anonymous { Anonymous {
qualified_type: Type, qualified_type: Type,
long_type_path: StringExpr, long_type_path: StringExpr,

View file

@ -25,7 +25,13 @@ use syn::{parenthesized, Attribute, Generics, Path};
/// (in my_crate::bar) Bar(TraitA, TraitB) /// (in my_crate::bar) Bar(TraitA, TraitB)
/// ``` /// ```
pub(crate) struct ReflectValueDef { 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<Attribute>, pub attrs: Vec<Attribute>,
pub type_path: Path, pub type_path: Path,
pub generics: Generics, pub generics: Generics,

View file

@ -7,7 +7,6 @@ use quote::quote;
use syn::Type; use syn::Type;
/// Creates the `GetTypeRegistration` impl for the given type data. /// Creates the `GetTypeRegistration` impl for the given type data.
#[allow(clippy::too_many_arguments)]
pub(crate) fn impl_get_type_registration<'a>( pub(crate) fn impl_get_type_registration<'a>(
meta: &ReflectMeta, meta: &ReflectMeta,
where_clause_options: &WhereClauseOptions, where_clause_options: &WhereClauseOptions,

View file

@ -1,5 +1,5 @@
// FIXME(3492): remove once docs are ready // FIXME(15321): solve CI failures, then replace with `#![expect()]`.
#![allow(missing_docs)] #![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")]
// `rustdoc_internals` is needed for `#[doc(fake_variadics)]` // `rustdoc_internals` is needed for `#[doc(fake_variadics)]`
#![allow(internal_features)] #![allow(internal_features)]
#![cfg_attr(any(docsrs, docsrs_dep), feature(doc_auto_cfg, rustdoc_internals))] #![cfg_attr(any(docsrs, docsrs_dep), feature(doc_auto_cfg, rustdoc_internals))]

View file

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

View file

@ -1,5 +1,5 @@
// FIXME(3492): remove once docs are ready // FIXME(15321): solve CI failures, then replace with `#![expect()]`.
#![allow(missing_docs)] #![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")]
#![allow(unsafe_code)] #![allow(unsafe_code)]
// `rustdoc_internals` is needed for `#[doc(fake_variadics)]` // `rustdoc_internals` is needed for `#[doc(fake_variadics)]`
#![allow(internal_features)] #![allow(internal_features)]

View file

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

View file

@ -1,5 +1,5 @@
// FIXME(3492): remove once docs are ready // FIXME(15321): solve CI failures, then replace with `#![expect()]`.
#![allow(missing_docs)] #![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")]
#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![cfg_attr(docsrs, feature(doc_auto_cfg))]
extern crate proc_macro; extern crate proc_macro;

View file

@ -68,7 +68,6 @@ impl TaskPool {
TaskPoolBuilder::new().build() TaskPoolBuilder::new().build()
} }
#[allow(unused_variables)]
fn new_internal() -> Self { fn new_internal() -> Self {
Self {} Self {}
} }
@ -96,7 +95,7 @@ impl TaskPool {
/// to spawn tasks. This function will await the completion of all tasks before returning. /// to spawn tasks. This function will await the completion of all tasks before returning.
/// ///
/// This is similar to `rayon::scope` and `crossbeam::scope` /// 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>( pub fn scope_with_executor<'env, F, T>(
&self, &self,
_tick_task_pool_executor: bool, _tick_task_pool_executor: bool,

View file

@ -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>( fn scope_with_executor_inner<'env, F, T>(
&self, &self,
tick_task_pool_executor: bool, tick_task_pool_executor: bool,

View file

@ -11,7 +11,6 @@ pub mod common_conditions;
mod fixed; mod fixed;
mod real; mod real;
mod stopwatch; mod stopwatch;
#[allow(clippy::module_inception)]
mod time; mod time;
mod timer; mod timer;
mod virt; mod virt;
@ -44,9 +43,9 @@ use crossbeam_channel::{Receiver, Sender};
#[derive(Default)] #[derive(Default)]
pub struct TimePlugin; pub struct TimePlugin;
#[derive(Debug, PartialEq, Eq, Clone, Hash, SystemSet)]
/// Updates the elapsed time. Any system that interacts with [`Time`] component should run after /// Updates the elapsed time. Any system that interacts with [`Time`] component should run after
/// this. /// this.
#[derive(Debug, PartialEq, Eq, Clone, Hash, SystemSet)]
pub struct TimeSystem; pub struct TimeSystem;
impl Plugin for TimePlugin { impl Plugin for TimePlugin {

View file

@ -79,7 +79,7 @@ pub fn propagate_transforms(
// - Since each root entity is unique and the hierarchy is consistent and forest-like, // - 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. // 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. // - 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 { unsafe {
propagate_recursive( propagate_recursive(
&global_transform, &global_transform,
@ -107,7 +107,10 @@ pub fn propagate_transforms(
/// nor any of its descendants. /// nor any of its descendants.
/// - The caller must ensure that the hierarchy leading to `entity` /// - 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. /// 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( unsafe fn propagate_recursive(
parent: &GlobalTransform, parent: &GlobalTransform,
transform_query: &Query< transform_query: &Query<

View file

@ -1,5 +1,5 @@
// FIXME(3492): remove once docs are ready // FIXME(15321): solve CI failures, then replace with `#![expect()]`.
#![allow(missing_docs)] #![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")]
#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![doc( #![doc(
html_logo_url = "https://bevyengine.org/assets/icon.png", html_logo_url = "https://bevyengine.org/assets/icon.png",

View file

@ -1,5 +1,5 @@
// FIXME(3492): remove once docs are ready // FIXME(15321): solve CI failures, then replace with `#![expect()]`.
#![allow(missing_docs)] #![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")]
#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![cfg_attr(docsrs, feature(doc_auto_cfg))]
use proc_macro::TokenStream; use proc_macro::TokenStream;

View file

@ -1,5 +1,8 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![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( #![doc(
html_logo_url = "https://bevyengine.org/assets/icon.png", html_logo_url = "https://bevyengine.org/assets/icon.png",
html_favicon_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")] #[cfg(target_arch = "wasm32")]
#[allow(missing_docs)] #[expect(missing_docs, reason = "Not all docs are written yet (#3492).")]
mod conditional_send { mod conditional_send {
pub trait ConditionalSend {} pub trait ConditionalSend {}
impl<T> ConditionalSend for T {} impl<T> ConditionalSend for T {}

View file

@ -413,7 +413,8 @@ impl AppLifecycle {
derive(serde::Serialize, serde::Deserialize), derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, 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 { pub enum WindowEvent {
AppLifecycle(AppLifecycle), AppLifecycle(AppLifecycle),
CursorEntered(CursorEntered), CursorEntered(CursorEntered),