From a6adced9ed5a8953528fd08d085e8f1297f1de70 Mon Sep 17 00:00:00 2001 From: Zachary Harrold Date: Sat, 7 Dec 2024 04:03:55 +1100 Subject: [PATCH] Deny `derive_more` `error` feature and replace it with `thiserror` (#16684) # Objective - Remove `derive_more`'s error derivation and replace it with `thiserror` ## Solution - Added `derive_more`'s `error` feature to `deny.toml` to prevent it sneaking back in. - Reverted to `thiserror` error derivation ## Notes Merge conflicts were too numerous to revert the individual changes, so this reversion was done manually. Please scrutinise carefully during review. --- crates/bevy_animation/Cargo.toml | 7 +- crates/bevy_animation/src/gltf_curves.rs | 11 +-- crates/bevy_animation/src/graph.rs | 17 ++-- crates/bevy_app/Cargo.toml | 6 +- crates/bevy_app/src/app.rs | 6 +- crates/bevy_asset/Cargo.toml | 7 +- crates/bevy_asset/src/assets.rs | 6 +- crates/bevy_asset/src/handle.rs | 6 +- crates/bevy_asset/src/id.rs | 7 +- crates/bevy_asset/src/io/mod.rs | 18 ++--- crates/bevy_asset/src/io/source.rs | 22 +++--- crates/bevy_asset/src/lib.rs | 14 ++-- crates/bevy_asset/src/loader.rs | 33 ++++---- crates/bevy_asset/src/path.rs | 12 +-- crates/bevy_asset/src/processor/log.rs | 36 ++++----- crates/bevy_asset/src/processor/mod.rs | 10 ++- crates/bevy_asset/src/processor/process.rs | 42 +++++----- crates/bevy_asset/src/server/info.rs | 14 ++-- crates/bevy_asset/src/server/loaders.rs | 7 +- crates/bevy_asset/src/server/mod.rs | 78 ++++++++++--------- crates/bevy_color/Cargo.toml | 7 +- crates/bevy_color/src/srgba.rs | 13 ++-- crates/bevy_core_pipeline/Cargo.toml | 6 +- .../src/auto_exposure/compensation_curve.rs | 10 +-- crates/bevy_ecs/Cargo.toml | 2 +- crates/bevy_ecs/src/component.rs | 12 +-- crates/bevy_ecs/src/lib.rs | 2 +- crates/bevy_ecs/src/query/error.rs | 10 +-- crates/bevy_ecs/src/schedule/schedule.rs | 29 ++++--- crates/bevy_ecs/src/schedule/stepping.rs | 6 +- crates/bevy_ecs/src/system/system.rs | 7 +- crates/bevy_ecs/src/system/system_registry.rs | 14 ++-- crates/bevy_ecs/src/world/entity_ref.rs | 12 +-- crates/bevy_ecs/src/world/error.rs | 23 +++--- crates/bevy_ecs/src/world/reflect.rs | 16 ++-- .../bevy_ecs/src/world/unsafe_world_cell.rs | 7 +- crates/bevy_gilrs/Cargo.toml | 6 +- crates/bevy_gilrs/src/rumble.rs | 10 +-- crates/bevy_gltf/Cargo.toml | 6 +- crates/bevy_gltf/src/loader.rs | 51 ++++++------ crates/bevy_gltf/src/vertex_attributes.rs | 19 ++--- crates/bevy_image/Cargo.toml | 6 +- .../bevy_image/src/compressed_image_saver.rs | 7 +- crates/bevy_image/src/exr_texture_loader.rs | 10 ++- crates/bevy_image/src/hdr_texture_loader.rs | 12 +-- crates/bevy_image/src/image.rs | 43 ++++------ crates/bevy_image/src/image_loader.rs | 16 ++-- .../src/image_texture_conversion.rs | 10 +-- crates/bevy_input/Cargo.toml | 7 +- crates/bevy_input/src/gamepad.rs | 34 ++++---- crates/bevy_math/Cargo.toml | 3 +- crates/bevy_math/src/aspect_ratio.rs | 11 +-- crates/bevy_math/src/cubic_splines.rs | 22 +++--- crates/bevy_math/src/curve/cores.rs | 28 +++---- crates/bevy_math/src/curve/interval.rs | 18 ++--- crates/bevy_math/src/curve/mod.rs | 45 ++++++----- crates/bevy_math/src/primitives/dim2.rs | 7 +- crates/bevy_mesh/Cargo.toml | 6 +- crates/bevy_mesh/src/conversions.rs | 6 +- crates/bevy_mesh/src/index.rs | 20 ++--- crates/bevy_mesh/src/mikktspace.rs | 17 ++-- crates/bevy_mesh/src/morph.rs | 8 +- .../bevy_mesh/src/primitives/dim3/sphere.rs | 6 +- crates/bevy_mesh/src/vertex.rs | 6 +- crates/bevy_pbr/Cargo.toml | 7 +- crates/bevy_pbr/src/meshlet/asset.rs | 16 ++-- crates/bevy_pbr/src/meshlet/from_mesh.rs | 10 +-- crates/bevy_reflect/Cargo.toml | 7 +- crates/bevy_reflect/src/enums/variants.rs | 6 +- crates/bevy_reflect/src/func/args/error.rs | 12 ++- crates/bevy_reflect/src/func/error.rs | 16 ++-- crates/bevy_reflect/src/kind.rs | 6 +- crates/bevy_reflect/src/path/mod.rs | 16 ++-- crates/bevy_reflect/src/path/parse.rs | 27 +++---- crates/bevy_reflect/src/reflect.rs | 14 ++-- crates/bevy_reflect/src/type_info.rs | 6 +- crates/bevy_render/Cargo.toml | 7 +- crates/bevy_render/src/render_asset.rs | 8 +- .../bevy_render/src/render_graph/context.rs | 28 +++---- crates/bevy_render/src/render_graph/mod.rs | 29 +++---- crates/bevy_render/src/render_graph/node.rs | 20 ++--- crates/bevy_render/src/render_phase/draw.rs | 11 ++- .../src/render_resource/bind_group.rs | 10 +-- .../src/render_resource/pipeline_cache.rs | 18 ++--- .../render_resource/pipeline_specializer.rs | 7 +- .../bevy_render/src/render_resource/shader.rs | 26 ++++--- .../bevy_render/src/renderer/graph_runner.rs | 15 ++-- crates/bevy_scene/Cargo.toml | 7 +- crates/bevy_scene/src/scene_loader.rs | 12 +-- crates/bevy_scene/src/scene_spawner.rs | 18 ++--- crates/bevy_sprite/Cargo.toml | 7 +- .../bevy_sprite/src/texture_atlas_builder.rs | 8 +- crates/bevy_text/Cargo.toml | 6 +- crates/bevy_text/src/error.rs | 12 ++- crates/bevy_text/src/font_loader.rs | 10 ++- crates/bevy_transform/Cargo.toml | 7 +- crates/bevy_transform/src/helper.rs | 13 ++-- crates/bevy_ui/Cargo.toml | 7 +- crates/bevy_ui/src/geometry.rs | 8 +- crates/bevy_ui/src/layout/mod.rs | 8 +- crates/bevy_ui/src/ui_node.rs | 9 ++- deny.toml | 5 ++ 102 files changed, 668 insertions(+), 766 deletions(-) diff --git a/crates/bevy_animation/Cargo.toml b/crates/bevy_animation/Cargo.toml index 4f493ceb34..81e662e5c3 100644 --- a/crates/bevy_animation/Cargo.toml +++ b/crates/bevy_animation/Cargo.toml @@ -34,11 +34,8 @@ ron = "0.8" serde = "1" blake3 = { version = "1.0" } downcast-rs = "1.2.0" -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } +derive_more = { version = "1", default-features = false, features = ["from"] } either = "1.13" thread_local = "1" uuid = { version = "1.7", features = ["v4"] } diff --git a/crates/bevy_animation/src/gltf_curves.rs b/crates/bevy_animation/src/gltf_curves.rs index 8d3b6cc248..d5b2cbb6b9 100644 --- a/crates/bevy_animation/src/gltf_curves.rs +++ b/crates/bevy_animation/src/gltf_curves.rs @@ -5,8 +5,8 @@ use bevy_math::{ vec4, Quat, Vec4, VectorSpace, }; use bevy_reflect::Reflect; -use derive_more::derive::{Display, Error, From}; use either::Either; +use thiserror::Error; /// A keyframe-defined curve that "interpolates" by stepping at `t = 1.0` to the next keyframe. #[derive(Debug, Clone, Reflect)] @@ -319,11 +319,11 @@ where } /// An error indicating that a multisampling keyframe curve could not be constructed. -#[derive(Debug, Error, Display, From)] -#[display("unable to construct a curve using this data")] +#[derive(Debug, Error)] +#[error("unable to construct a curve using this data")] pub enum WideKeyframeCurveError { /// The number of given values was not divisible by a multiple of the number of keyframes. - #[display("number of values ({values_given}) is not divisible by {divisor}")] + #[error("number of values ({values_given}) is not divisible by {divisor}")] LengthMismatch { /// The number of values given. values_given: usize, @@ -331,7 +331,8 @@ pub enum WideKeyframeCurveError { divisor: usize, }, /// An error was returned by the internal core constructor. - CoreError(ChunkedUnevenCoreError), + #[error(transparent)] + CoreError(#[from] ChunkedUnevenCoreError), } impl WideCubicKeyframeCurve { diff --git a/crates/bevy_animation/src/graph.rs b/crates/bevy_animation/src/graph.rs index eb0589c539..2507895bf0 100644 --- a/crates/bevy_animation/src/graph.rs +++ b/crates/bevy_animation/src/graph.rs @@ -16,7 +16,7 @@ use bevy_ecs::{ }; use bevy_reflect::{prelude::ReflectDefault, Reflect, ReflectSerialize}; use bevy_utils::HashMap; -use derive_more::derive::{Display, Error, From}; +use derive_more::derive::From; use petgraph::{ graph::{DiGraph, NodeIndex}, Direction, @@ -24,6 +24,7 @@ use petgraph::{ use ron::de::SpannedError; use serde::{Deserialize, Serialize}; use smallvec::SmallVec; +use thiserror::Error; use crate::{AnimationClip, AnimationTargetId}; @@ -237,18 +238,18 @@ pub struct AnimationGraphAssetLoader; /// Various errors that can occur when serializing or deserializing animation /// graphs to and from RON, respectively. -#[derive(Error, Display, Debug, From)] +#[derive(Error, Debug)] pub enum AnimationGraphLoadError { /// An I/O error occurred. - #[display("I/O")] - Io(io::Error), + #[error("I/O")] + Io(#[from] io::Error), /// An error occurred in RON serialization or deserialization. - #[display("RON serialization")] - Ron(ron::Error), + #[error("RON serialization")] + Ron(#[from] ron::Error), /// An error occurred in RON deserialization, and the location of the error /// is supplied. - #[display("RON serialization")] - SpannedRon(SpannedError), + #[error("RON serialization")] + SpannedRon(#[from] SpannedError), } /// Acceleration structures for animation graphs that allows Bevy to evaluate diff --git a/crates/bevy_app/Cargo.toml b/crates/bevy_app/Cargo.toml index a719ddd4c9..74c00dd78a 100644 --- a/crates/bevy_app/Cargo.toml +++ b/crates/bevy_app/Cargo.toml @@ -29,11 +29,7 @@ bevy_tasks = { path = "../bevy_tasks", version = "0.15.0-dev" } # other downcast-rs = "1.2.0" -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } variadics_please = "1.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 70a2f7456d..4aad33c9d6 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -15,11 +15,11 @@ use bevy_ecs::{ use bevy_utils::tracing::info_span; use bevy_utils::{tracing::debug, HashMap}; use core::{fmt::Debug, num::NonZero, panic::AssertUnwindSafe}; -use derive_more::derive::{Display, Error}; use std::{ panic::{catch_unwind, resume_unwind}, process::{ExitCode, Termination}, }; +use thiserror::Error; bevy_ecs::define_label!( /// A strongly-typed class of labels used to identify an [`App`]. @@ -32,9 +32,9 @@ pub use bevy_ecs::label::DynEq; /// A shorthand for `Interned`. pub type InternedAppLabel = Interned; -#[derive(Debug, Error, Display)] +#[derive(Debug, Error)] pub(crate) enum AppError { - #[display("duplicate plugin {plugin_name:?}")] + #[error("duplicate plugin {plugin_name:?}")] DuplicatePlugin { plugin_name: String }, } diff --git a/crates/bevy_asset/Cargo.toml b/crates/bevy_asset/Cargo.toml index f596805b46..e1d62ad2a2 100644 --- a/crates/bevy_asset/Cargo.toml +++ b/crates/bevy_asset/Cargo.toml @@ -44,11 +44,8 @@ blake3 = "1.5" parking_lot = { version = "0.12", features = ["arc_lock", "send_guard"] } ron = "0.8" serde = { version = "1", features = ["derive"] } -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } +derive_more = { version = "1", default-features = false, features = ["from"] } uuid = { version = "1.0", features = ["v4"] } [target.'cfg(target_os = "android")'.dependencies] diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index 5f4a053846..3c33aa43fa 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -11,8 +11,8 @@ use bevy_reflect::{Reflect, TypePath}; use bevy_utils::HashMap; use core::{any::TypeId, iter::Enumerate, marker::PhantomData, sync::atomic::AtomicU32}; use crossbeam_channel::{Receiver, Sender}; -use derive_more::derive::{Display, Error}; use serde::{Deserialize, Serialize}; +use thiserror::Error; use uuid::Uuid; /// A generational runtime-only identifier for a specific [`Asset`] stored in [`Assets`]. This is optimized for efficient runtime @@ -613,8 +613,8 @@ impl<'a, A: Asset> Iterator for AssetsMutIterator<'a, A> { } } -#[derive(Error, Display, Debug)] -#[display("AssetIndex {index:?} has an invalid generation. The current generation is: '{current_generation}'.")] +#[derive(Error, Debug)] +#[error("AssetIndex {index:?} has an invalid generation. The current generation is: '{current_generation}'.")] pub struct InvalidGenerationError { index: AssetIndex, current_generation: u32, diff --git a/crates/bevy_asset/src/handle.rs b/crates/bevy_asset/src/handle.rs index 6e4dec39ce..977a50b98b 100644 --- a/crates/bevy_asset/src/handle.rs +++ b/crates/bevy_asset/src/handle.rs @@ -9,8 +9,8 @@ use core::{ hash::{Hash, Hasher}, }; use crossbeam_channel::{Receiver, Sender}; -use derive_more::derive::{Display, Error}; use disqualified::ShortName; +use thiserror::Error; use uuid::Uuid; /// Provides [`Handle`] and [`UntypedHandle`] _for a specific asset type_. @@ -502,11 +502,11 @@ impl TryFrom for Handle { } /// Errors preventing the conversion of to/from an [`UntypedHandle`] and a [`Handle`]. -#[derive(Error, Display, Debug, PartialEq, Clone)] +#[derive(Error, Debug, PartialEq, Clone)] #[non_exhaustive] pub enum UntypedAssetConversionError { /// Caused when trying to convert an [`UntypedHandle`] into a [`Handle`] of the wrong type. - #[display( + #[error( "This UntypedHandle is for {found:?} and cannot be converted into a Handle<{expected:?}>" )] TypeIdMismatch { expected: TypeId, found: TypeId }, diff --git a/crates/bevy_asset/src/id.rs b/crates/bevy_asset/src/id.rs index 245b3d4fcd..7e2abc50e3 100644 --- a/crates/bevy_asset/src/id.rs +++ b/crates/bevy_asset/src/id.rs @@ -9,7 +9,8 @@ use core::{ hash::Hash, marker::PhantomData, }; -use derive_more::derive::{Display, Error, From}; +use derive_more::derive::From; +use thiserror::Error; /// A unique runtime-only identifier for an [`Asset`]. This is cheap to [`Copy`]/[`Clone`] and is not directly tied to the /// lifetime of the Asset. This means it _can_ point to an [`Asset`] that no longer exists. @@ -398,11 +399,11 @@ impl TryFrom for AssetId { } /// Errors preventing the conversion of to/from an [`UntypedAssetId`] and an [`AssetId`]. -#[derive(Error, Display, Debug, PartialEq, Clone)] +#[derive(Error, Debug, PartialEq, Clone)] #[non_exhaustive] pub enum UntypedAssetIdConversionError { /// Caused when trying to convert an [`UntypedAssetId`] into an [`AssetId`] of the wrong type. - #[display("This UntypedAssetId is for {found:?} and cannot be converted into an AssetId<{expected:?}>")] + #[error("This UntypedAssetId is for {found:?} and cannot be converted into an AssetId<{expected:?}>")] TypeIdMismatch { expected: TypeId, found: TypeId }, } diff --git a/crates/bevy_asset/src/io/mod.rs b/crates/bevy_asset/src/io/mod.rs index 207e51659b..0c4c0b1f00 100644 --- a/crates/bevy_asset/src/io/mod.rs +++ b/crates/bevy_asset/src/io/mod.rs @@ -29,27 +29,25 @@ use core::{ pin::Pin, task::{Context, Poll}, }; -use derive_more::derive::{Display, Error, From}; use futures_io::{AsyncRead, AsyncWrite}; use futures_lite::{ready, Stream}; use std::path::{Path, PathBuf}; +use thiserror::Error; /// Errors that occur while loading assets. -#[derive(Error, Display, Debug, Clone)] +#[derive(Error, Debug, Clone)] pub enum AssetReaderError { /// Path not found. - #[display("Path not found: {}", _0.display())] - #[error(ignore)] + #[error("Path not found: {}", _0.display())] NotFound(PathBuf), /// Encountered an I/O error while loading an asset. - #[display("Encountered an I/O error while loading asset: {_0}")] + #[error("Encountered an I/O error while loading asset: {0}")] Io(Arc), /// The HTTP request completed but returned an unhandled [HTTP response status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status). /// If the request fails before getting a status code (e.g. request timeout, interrupted connection, etc), expect [`AssetReaderError::Io`]. - #[display("Encountered HTTP status {_0:?} when loading asset")] - #[error(ignore)] + #[error("Encountered HTTP status {0:?} when loading asset")] HttpError(u16), } @@ -333,11 +331,11 @@ pub type Writer = dyn AsyncWrite + Unpin + Send + Sync; pub type PathStream = dyn Stream + Unpin + Send; /// Errors that occur while loading assets. -#[derive(Error, Display, Debug, From)] +#[derive(Error, Debug)] pub enum AssetWriterError { /// Encountered an I/O error while loading an asset. - #[display("encountered an io error while loading asset: {_0}")] - Io(std::io::Error), + #[error("encountered an io error while loading asset: {0}")] + Io(#[from] std::io::Error), } /// Preforms write operations on an asset storage. [`AssetWriter`] exposes a "virtual filesystem" diff --git a/crates/bevy_asset/src/io/source.rs b/crates/bevy_asset/src/io/source.rs index 42789bd26f..fe0d8df17f 100644 --- a/crates/bevy_asset/src/io/source.rs +++ b/crates/bevy_asset/src/io/source.rs @@ -10,7 +10,7 @@ use bevy_utils::{ Duration, HashMap, }; use core::{fmt::Display, hash::Hash}; -use derive_more::derive::{Display, Error}; +use thiserror::Error; use super::{ErasedAssetReader, ErasedAssetWriter}; @@ -629,27 +629,23 @@ impl AssetSources { } /// An error returned when an [`AssetSource`] does not exist for a given id. -#[derive(Error, Display, Debug, Clone, PartialEq, Eq)] -#[display("Asset Source '{_0}' does not exist")] -#[error(ignore)] +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Asset Source '{0}' does not exist")] pub struct MissingAssetSourceError(AssetSourceId<'static>); /// An error returned when an [`AssetWriter`](crate::io::AssetWriter) does not exist for a given id. -#[derive(Error, Display, Debug, Clone)] -#[display("Asset Source '{_0}' does not have an AssetWriter.")] -#[error(ignore)] +#[derive(Error, Debug, Clone)] +#[error("Asset Source '{0}' does not have an AssetWriter.")] pub struct MissingAssetWriterError(AssetSourceId<'static>); /// An error returned when a processed [`AssetReader`](crate::io::AssetReader) does not exist for a given id. -#[derive(Error, Display, Debug, Clone, PartialEq, Eq)] -#[display("Asset Source '{_0}' does not have a processed AssetReader.")] -#[error(ignore)] +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("Asset Source '{0}' does not have a processed AssetReader.")] pub struct MissingProcessedAssetReaderError(AssetSourceId<'static>); /// An error returned when a processed [`AssetWriter`](crate::io::AssetWriter) does not exist for a given id. -#[derive(Error, Display, Debug, Clone)] -#[display("Asset Source '{_0}' does not have a processed AssetWriter.")] -#[error(ignore)] +#[derive(Error, Debug, Clone)] +#[error("Asset Source '{0}' does not have a processed AssetWriter.")] pub struct MissingProcessedAssetWriterError(AssetSourceId<'static>); const MISSING_DEFAULT_SOURCE: &str = diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index 8937c8838c..d252946c3c 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -630,9 +630,9 @@ mod tests { use bevy_log::LogPlugin; use bevy_reflect::TypePath; use bevy_utils::{Duration, HashMap}; - use derive_more::derive::{Display, Error, From}; use serde::{Deserialize, Serialize}; use std::path::Path; + use thiserror::Error; #[derive(Asset, TypePath, Debug, Default)] pub struct CoolText { @@ -660,14 +660,14 @@ mod tests { #[derive(Default)] pub struct CoolTextLoader; - #[derive(Error, Display, Debug, From)] + #[derive(Error, Debug)] pub enum CoolTextLoaderError { - #[display("Could not load dependency: {dependency}")] + #[error("Could not load dependency: {dependency}")] CannotLoadDependency { dependency: AssetPath<'static> }, - #[display("A RON error occurred during loading")] - RonSpannedError(ron::error::SpannedError), - #[display("An IO error occurred during loading")] - Io(std::io::Error), + #[error("A RON error occurred during loading")] + RonSpannedError(#[from] ron::error::SpannedError), + #[error("An IO error occurred during loading")] + Io(#[from] std::io::Error), } impl AssetLoader for CoolTextLoader { diff --git a/crates/bevy_asset/src/loader.rs b/crates/bevy_asset/src/loader.rs index 7192fe265c..4cab51634f 100644 --- a/crates/bevy_asset/src/loader.rs +++ b/crates/bevy_asset/src/loader.rs @@ -10,11 +10,11 @@ use atomicow::CowArc; use bevy_ecs::world::World; use bevy_utils::{BoxedFuture, ConditionalSendFuture, HashMap, HashSet}; use core::any::{Any, TypeId}; -use derive_more::derive::{Display, Error, From}; use downcast_rs::{impl_downcast, Downcast}; use ron::error::SpannedError; use serde::{Deserialize, Serialize}; use std::path::{Path, PathBuf}; +use thiserror::Error; /// Loads an [`Asset`] from a given byte [`Reader`]. This can accept [`AssetLoader::Settings`], which configure how the [`Asset`] /// should be loaded. @@ -295,20 +295,19 @@ impl AssetContainer for A { /// /// [`NestedLoader::load`]: crate::NestedLoader::load /// [immediately]: crate::Immediate -#[derive(Error, Display, Debug)] -#[display("Failed to load dependency {dependency:?} {error}")] +#[derive(Error, Debug)] +#[error("Failed to load dependency {dependency:?} {error}")] pub struct LoadDirectError { pub dependency: AssetPath<'static>, pub error: AssetLoadError, } /// An error that occurs while deserializing [`AssetMeta`]. -#[derive(Error, Display, Debug, Clone, PartialEq, Eq, From)] +#[derive(Error, Debug, Clone, PartialEq, Eq)] pub enum DeserializeMetaError { - #[display("Failed to deserialize asset meta: {_0:?}")] - DeserializeSettings(SpannedError), - #[display("Failed to deserialize minimal asset meta: {_0:?}")] - #[from(ignore)] + #[error("Failed to deserialize asset meta: {0:?}")] + DeserializeSettings(#[from] SpannedError), + #[error("Failed to deserialize minimal asset meta: {0:?}")] DeserializeMinimal(SpannedError), } @@ -573,18 +572,22 @@ impl<'a> LoadContext<'a> { } /// An error produced when calling [`LoadContext::read_asset_bytes`] -#[derive(Error, Display, Debug, From)] +#[derive(Error, Debug)] pub enum ReadAssetBytesError { - DeserializeMetaError(DeserializeMetaError), - AssetReaderError(AssetReaderError), - MissingAssetSourceError(MissingAssetSourceError), - MissingProcessedAssetReaderError(MissingProcessedAssetReaderError), + #[error(transparent)] + DeserializeMetaError(#[from] DeserializeMetaError), + #[error(transparent)] + AssetReaderError(#[from] AssetReaderError), + #[error(transparent)] + MissingAssetSourceError(#[from] MissingAssetSourceError), + #[error(transparent)] + MissingProcessedAssetReaderError(#[from] MissingProcessedAssetReaderError), /// Encountered an I/O error while loading an asset. - #[display("Encountered an io error while loading asset at `{}`: {source}", path.display())] + #[error("Encountered an io error while loading asset at `{}`: {source}", path.display())] Io { path: PathBuf, source: std::io::Error, }, - #[display("The LoadContext for this read_asset_bytes call requires hash metadata, but it was not provided. This is likely an internal implementation error.")] + #[error("The LoadContext for this read_asset_bytes call requires hash metadata, but it was not provided. This is likely an internal implementation error.")] MissingAssetHash, } diff --git a/crates/bevy_asset/src/path.rs b/crates/bevy_asset/src/path.rs index c86a190fe1..3bbb643650 100644 --- a/crates/bevy_asset/src/path.rs +++ b/crates/bevy_asset/src/path.rs @@ -6,9 +6,9 @@ use core::{ hash::Hash, ops::Deref, }; -use derive_more::derive::{Display, Error}; use serde::{de::Visitor, Deserialize, Serialize}; use std::path::{Path, PathBuf}; +use thiserror::Error; /// Represents a path to an asset in a "virtual filesystem". /// @@ -76,19 +76,19 @@ impl<'a> Display for AssetPath<'a> { } /// An error that occurs when parsing a string type to create an [`AssetPath`] fails, such as during [`AssetPath::parse`]. -#[derive(Error, Display, Debug, PartialEq, Eq)] +#[derive(Error, Debug, PartialEq, Eq)] pub enum ParseAssetPathError { /// Error that occurs when the [`AssetPath::source`] section of a path string contains the [`AssetPath::label`] delimiter `#`. E.g. `bad#source://file.test`. - #[display("Asset source must not contain a `#` character")] + #[error("Asset source must not contain a `#` character")] InvalidSourceSyntax, /// Error that occurs when the [`AssetPath::label`] section of a path string contains the [`AssetPath::source`] delimiter `://`. E.g. `source://file.test#bad://label`. - #[display("Asset label must not contain a `://` substring")] + #[error("Asset label must not contain a `://` substring")] InvalidLabelSyntax, /// Error that occurs when a path string has an [`AssetPath::source`] delimiter `://` with no characters preceding it. E.g. `://file.test`. - #[display("Asset source must be at least one character. Either specify the source before the '://' or remove the `://`")] + #[error("Asset source must be at least one character. Either specify the source before the '://' or remove the `://`")] MissingSource, /// Error that occurs when a path string has an [`AssetPath::label`] delimiter `#` with no characters succeeding it. E.g. `file.test#` - #[display("Asset label must be at least one character. Either specify the label after the '#' or remove the '#'")] + #[error("Asset label must be at least one character. Either specify the label after the '#' or remove the '#'")] MissingLabel, } diff --git a/crates/bevy_asset/src/processor/log.rs b/crates/bevy_asset/src/processor/log.rs index d0582d5dbd..2649b815d8 100644 --- a/crates/bevy_asset/src/processor/log.rs +++ b/crates/bevy_asset/src/processor/log.rs @@ -1,9 +1,9 @@ use crate::AssetPath; use async_fs::File; use bevy_utils::{tracing::error, HashSet}; -use derive_more::derive::{Display, Error, From}; use futures_lite::{AsyncReadExt, AsyncWriteExt}; use std::path::PathBuf; +use thiserror::Error; /// An in-memory representation of a single [`ProcessorTransactionLog`] entry. #[derive(Debug)] @@ -24,18 +24,17 @@ pub struct ProcessorTransactionLog { } /// An error that occurs when reading from the [`ProcessorTransactionLog`] fails. -#[derive(Error, Display, Debug, From)] +#[derive(Error, Debug)] pub enum ReadLogError { - #[display("Encountered an invalid log line: '{_0}'")] - #[error(ignore)] + #[error("Encountered an invalid log line: '{0}'")] InvalidLine(String), - #[display("Failed to read log file: {_0}")] - Io(futures_io::Error), + #[error("Failed to read log file: {0}")] + Io(#[from] futures_io::Error), } /// An error that occurs when writing to the [`ProcessorTransactionLog`] fails. -#[derive(Error, Display, Debug)] -#[display( +#[derive(Error, Debug)] +#[error( "Failed to write {log_entry:?} to the asset processor log. This is not recoverable. {error}" )] pub struct WriteLogError { @@ -44,27 +43,24 @@ pub struct WriteLogError { } /// An error that occurs when validating the [`ProcessorTransactionLog`] fails. -#[derive(Error, Display, Debug, From)] +#[derive(Error, Debug)] pub enum ValidateLogError { - #[display("Encountered an unrecoverable error. All assets will be reprocessed.")] + #[error("Encountered an unrecoverable error. All assets will be reprocessed.")] UnrecoverableError, - ReadLogError(ReadLogError), - #[display("Encountered a duplicate process asset transaction: {_0:?}")] - #[error(ignore)] + #[error(transparent)] + ReadLogError(#[from] ReadLogError), + #[error("Encountered a duplicate process asset transaction: {0:?}")] EntryErrors(Vec), } /// An error that occurs when validating individual [`ProcessorTransactionLog`] entries. -#[derive(Error, Display, Debug)] +#[derive(Error, Debug)] pub enum LogEntryError { - #[display("Encountered a duplicate process asset transaction: {_0}")] - #[error(ignore)] + #[error("Encountered a duplicate process asset transaction: {0}")] DuplicateTransaction(AssetPath<'static>), - #[display("A transaction was ended that never started {_0}")] - #[error(ignore)] + #[error("A transaction was ended that never started {0}")] EndedMissingTransaction(AssetPath<'static>), - #[display("An asset started processing but never finished: {_0}")] - #[error(ignore)] + #[error("An asset started processing but never finished: {0}")] UnfinishedTransaction(AssetPath<'static>), } diff --git a/crates/bevy_asset/src/processor/mod.rs b/crates/bevy_asset/src/processor/mod.rs index a047cd7971..c74fd80b56 100644 --- a/crates/bevy_asset/src/processor/mod.rs +++ b/crates/bevy_asset/src/processor/mod.rs @@ -68,11 +68,11 @@ use bevy_utils::{ tracing::{info_span, instrument::Instrument}, ConditionalSendFuture, }; -use derive_more::derive::{Display, Error}; use futures_io::ErrorKind; use futures_lite::{AsyncReadExt, AsyncWriteExt, StreamExt}; use parking_lot::RwLock; use std::path::{Path, PathBuf}; +use thiserror::Error; /// A "background" asset processor that reads asset values from a source [`AssetSource`] (which corresponds to an [`AssetReader`](crate::io::AssetReader) / [`AssetWriter`](crate::io::AssetWriter) pair), /// processes them in some way, and writes them to a destination [`AssetSource`]. @@ -1413,10 +1413,12 @@ pub enum ProcessorState { } /// An error that occurs when initializing the [`AssetProcessor`]. -#[derive(Error, Display, Debug)] +#[derive(Error, Debug)] pub enum InitializeError { + #[error(transparent)] FailedToReadSourcePaths(AssetReaderError), + #[error(transparent)] FailedToReadDestinationPaths(AssetReaderError), - #[display("Failed to validate asset log: {_0}")] - ValidateLogError(ValidateLogError), + #[error("Failed to validate asset log: {0}")] + ValidateLogError(#[from] ValidateLogError), } diff --git a/crates/bevy_asset/src/processor/process.rs b/crates/bevy_asset/src/processor/process.rs index b9d2cd3b47..5b084de849 100644 --- a/crates/bevy_asset/src/processor/process.rs +++ b/crates/bevy_asset/src/processor/process.rs @@ -12,8 +12,8 @@ use crate::{ }; use bevy_utils::{BoxedFuture, ConditionalSendFuture}; use core::marker::PhantomData; -use derive_more::derive::{Display, Error, From}; use serde::{Deserialize, Serialize}; +use thiserror::Error; /// Asset "processor" logic that reads input asset bytes (stored on [`ProcessContext`]), processes the value in some way, /// and then writes the final processed bytes with [`Writer`]. The resulting bytes must be loadable with the given [`Process::OutputLoader`]. @@ -126,46 +126,52 @@ pub type LoadAndSaveSettings = LoadTransformAndSaveSettings; /// An error that is encountered during [`Process::process`]. -#[derive(Error, Display, Debug, From)] +#[derive(Error, Debug)] pub enum ProcessError { - MissingAssetLoaderForExtension(MissingAssetLoaderForExtensionError), - MissingAssetLoaderForTypeName(MissingAssetLoaderForTypeNameError), - #[display("The processor '{_0}' does not exist")] - #[error(ignore)] + #[error(transparent)] + MissingAssetLoaderForExtension(#[from] MissingAssetLoaderForExtensionError), + #[error(transparent)] + MissingAssetLoaderForTypeName(#[from] MissingAssetLoaderForTypeNameError), + #[error("The processor '{0}' does not exist")] #[from(ignore)] MissingProcessor(String), - #[display("Encountered an AssetReader error for '{path}': {err}")] + #[error("Encountered an AssetReader error for '{path}': {err}")] #[from(ignore)] AssetReaderError { path: AssetPath<'static>, err: AssetReaderError, }, - #[display("Encountered an AssetWriter error for '{path}': {err}")] + #[error("Encountered an AssetWriter error for '{path}': {err}")] #[from(ignore)] AssetWriterError { path: AssetPath<'static>, err: AssetWriterError, }, - MissingAssetWriterError(MissingAssetWriterError), - MissingProcessedAssetReaderError(MissingProcessedAssetReaderError), - MissingProcessedAssetWriterError(MissingProcessedAssetWriterError), - #[display("Failed to read asset metadata for {path}: {err}")] + #[error(transparent)] + MissingAssetWriterError(#[from] MissingAssetWriterError), + #[error(transparent)] + MissingProcessedAssetReaderError(#[from] MissingProcessedAssetReaderError), + #[error(transparent)] + MissingProcessedAssetWriterError(#[from] MissingProcessedAssetWriterError), + #[error("Failed to read asset metadata for {path}: {err}")] #[from(ignore)] ReadAssetMetaError { path: AssetPath<'static>, err: AssetReaderError, }, - DeserializeMetaError(DeserializeMetaError), - AssetLoadError(AssetLoadError), - #[display("The wrong meta type was passed into a processor. This is probably an internal implementation error.")] + #[error(transparent)] + DeserializeMetaError(#[from] DeserializeMetaError), + #[error(transparent)] + AssetLoadError(#[from] AssetLoadError), + #[error("The wrong meta type was passed into a processor. This is probably an internal implementation error.")] WrongMetaType, - #[display("Encountered an error while saving the asset: {_0}")] + #[error("Encountered an error while saving the asset: {0}")] #[from(ignore)] AssetSaveError(Box), - #[display("Encountered an error while transforming the asset: {_0}")] + #[error("Encountered an error while transforming the asset: {0}")] #[from(ignore)] AssetTransformError(Box), - #[display("Assets without extensions are not supported.")] + #[error("Assets without extensions are not supported.")] ExtensionRequired, } diff --git a/crates/bevy_asset/src/server/info.rs b/crates/bevy_asset/src/server/info.rs index 99bcb5a1e0..3a38797fc8 100644 --- a/crates/bevy_asset/src/server/info.rs +++ b/crates/bevy_asset/src/server/info.rs @@ -10,8 +10,8 @@ use bevy_tasks::Task; use bevy_utils::{tracing::warn, Entry, HashMap, HashSet, TypeIdMap}; use core::{any::TypeId, task::Waker}; use crossbeam_channel::Sender; -use derive_more::derive::{Display, Error, From}; use either::Either; +use thiserror::Error; #[derive(Debug)] pub(crate) struct AssetInfo { @@ -757,16 +757,16 @@ pub(crate) enum HandleLoadingMode { Force, } -#[derive(Error, Display, Debug)] -#[display("Cannot allocate a handle because no handle provider exists for asset type {_0:?}")] -#[error(ignore)] +#[derive(Error, Debug)] +#[error("Cannot allocate a handle because no handle provider exists for asset type {0:?}")] pub struct MissingHandleProviderError(TypeId); /// An error encountered during [`AssetInfos::get_or_create_path_handle_internal`]. -#[derive(Error, Display, Debug, From)] +#[derive(Error, Debug)] pub(crate) enum GetOrCreateHandleInternalError { - MissingHandleProviderError(MissingHandleProviderError), - #[display("Handle does not exist but TypeId was not specified.")] + #[error(transparent)] + MissingHandleProviderError(#[from] MissingHandleProviderError), + #[error("Handle does not exist but TypeId was not specified.")] HandleMissingButTypeIdNotSpecified, } diff --git a/crates/bevy_asset/src/server/loaders.rs b/crates/bevy_asset/src/server/loaders.rs index 3850a7fb78..2442de389a 100644 --- a/crates/bevy_asset/src/server/loaders.rs +++ b/crates/bevy_asset/src/server/loaders.rs @@ -12,7 +12,7 @@ use bevy_utils::{ ConditionalSendFuture, }; use core::any::TypeId; -use derive_more::derive::{Display, Error, From}; +use thiserror::Error; #[derive(Default)] pub(crate) struct AssetLoaders { @@ -275,9 +275,10 @@ impl AssetLoaders { } } -#[derive(Error, Display, Debug, Clone, From)] +#[derive(Error, Debug, Clone)] pub(crate) enum GetLoaderError { - CouldNotResolve(RecvError), + #[error(transparent)] + CouldNotResolve(#[from] RecvError), } #[derive(Clone)] diff --git a/crates/bevy_asset/src/server/mod.rs b/crates/bevy_asset/src/server/mod.rs index 2971640629..fc97ad775e 100644 --- a/crates/bevy_asset/src/server/mod.rs +++ b/crates/bevy_asset/src/server/mod.rs @@ -27,13 +27,13 @@ use bevy_utils::{ }; use core::{any::TypeId, future::Future, panic::AssertUnwindSafe, task::Poll}; use crossbeam_channel::{Receiver, Sender}; -use derive_more::derive::{Display, Error, From}; use either::Either; use futures_lite::{FutureExt, StreamExt}; use info::*; use loaders::*; use parking_lot::{RwLock, RwLockWriteGuard}; use std::path::{Path, PathBuf}; +use thiserror::Error; /// Loads and tracks the state of [`Asset`] values from a configured [`AssetReader`](crate::io::AssetReader). This can be used to kick off new asset loads and /// retrieve their current load states. @@ -1722,53 +1722,57 @@ impl RecursiveDependencyLoadState { } /// An error that occurs during an [`Asset`] load. -#[derive(Error, Display, Debug, Clone, From)] +#[derive(Error, Debug, Clone)] pub enum AssetLoadError { - #[display("Requested handle of type {requested:?} for asset '{path}' does not match actual asset type '{actual_asset_name}', which used loader '{loader_name}'")] + #[error("Requested handle of type {requested:?} for asset '{path}' does not match actual asset type '{actual_asset_name}', which used loader '{loader_name}'")] RequestedHandleTypeMismatch { path: AssetPath<'static>, requested: TypeId, actual_asset_name: &'static str, loader_name: &'static str, }, - #[display("Could not find an asset loader matching: Loader Name: {loader_name:?}; Asset Type: {loader_name:?}; Extension: {extension:?}; Path: {asset_path:?};")] + #[error("Could not find an asset loader matching: Loader Name: {loader_name:?}; Asset Type: {loader_name:?}; Extension: {extension:?}; Path: {asset_path:?};")] MissingAssetLoader { loader_name: Option, asset_type_id: Option, extension: Option, asset_path: Option, }, - MissingAssetLoaderForExtension(MissingAssetLoaderForExtensionError), - MissingAssetLoaderForTypeName(MissingAssetLoaderForTypeNameError), - MissingAssetLoaderForTypeIdError(MissingAssetLoaderForTypeIdError), - AssetReaderError(AssetReaderError), - MissingAssetSourceError(MissingAssetSourceError), - MissingProcessedAssetReaderError(MissingProcessedAssetReaderError), - #[display("Encountered an error while reading asset metadata bytes")] + #[error(transparent)] + MissingAssetLoaderForExtension(#[from] MissingAssetLoaderForExtensionError), + #[error(transparent)] + MissingAssetLoaderForTypeName(#[from] MissingAssetLoaderForTypeNameError), + #[error(transparent)] + MissingAssetLoaderForTypeIdError(#[from] MissingAssetLoaderForTypeIdError), + #[error(transparent)] + AssetReaderError(#[from] AssetReaderError), + #[error(transparent)] + MissingAssetSourceError(#[from] MissingAssetSourceError), + #[error(transparent)] + MissingProcessedAssetReaderError(#[from] MissingProcessedAssetReaderError), + #[error("Encountered an error while reading asset metadata bytes")] AssetMetaReadError, - #[display("Failed to deserialize meta for asset {path}: {error}")] + #[error("Failed to deserialize meta for asset {path}: {error}")] DeserializeMeta { path: AssetPath<'static>, error: Box, }, - #[display("Asset '{path}' is configured to be processed. It cannot be loaded directly.")] + #[error("Asset '{path}' is configured to be processed. It cannot be loaded directly.")] #[from(ignore)] - CannotLoadProcessedAsset { - path: AssetPath<'static>, - }, - #[display("Asset '{path}' is configured to be ignored. It cannot be loaded.")] + CannotLoadProcessedAsset { path: AssetPath<'static> }, + #[error("Asset '{path}' is configured to be ignored. It cannot be loaded.")] #[from(ignore)] - CannotLoadIgnoredAsset { - path: AssetPath<'static>, - }, - #[display("Failed to load asset '{path}', asset loader '{loader_name}' panicked")] + CannotLoadIgnoredAsset { path: AssetPath<'static> }, + #[error("Failed to load asset '{path}', asset loader '{loader_name}' panicked")] AssetLoaderPanic { path: AssetPath<'static>, loader_name: &'static str, }, - AssetLoaderError(AssetLoaderError), - AddAsyncError(AddAsyncError), - #[display("The file at '{}' does not contain the labeled asset '{}'; it contains the following {} assets: {}", + #[error(transparent)] + AssetLoaderError(#[from] AssetLoaderError), + #[error(transparent)] + AddAsyncError(#[from] AddAsyncError), + #[error("The file at '{}' does not contain the labeled asset '{}'; it contains the following {} assets: {}", base_path, label, all_labels.len(), @@ -1780,8 +1784,8 @@ pub enum AssetLoadError { }, } -#[derive(Error, Display, Debug, Clone)] -#[display("Failed to load asset '{path}' with asset loader '{loader_name}': {error}")] +#[derive(Error, Debug, Clone)] +#[error("Failed to load asset '{path}' with asset loader '{loader_name}': {error}")] pub struct AssetLoaderError { path: AssetPath<'static>, loader_name: &'static str, @@ -1794,29 +1798,29 @@ impl AssetLoaderError { } } -#[derive(Error, Display, Debug, Clone)] -#[display("An error occurred while resolving an asset added by `add_async`: {error}")] +#[derive(Error, Debug, Clone)] +#[error("An error occurred while resolving an asset added by `add_async`: {error}")] pub struct AddAsyncError { error: Arc, } /// An error that occurs when an [`AssetLoader`] is not registered for a given extension. -#[derive(Error, Display, Debug, Clone, PartialEq, Eq)] -#[display("no `AssetLoader` found{}", format_missing_asset_ext(extensions))] +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("no `AssetLoader` found{}", format_missing_asset_ext(extensions))] pub struct MissingAssetLoaderForExtensionError { extensions: Vec, } /// An error that occurs when an [`AssetLoader`] is not registered for a given [`std::any::type_name`]. -#[derive(Error, Display, Debug, Clone, PartialEq, Eq)] -#[display("no `AssetLoader` found with the name '{type_name}'")] +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("no `AssetLoader` found with the name '{type_name}'")] pub struct MissingAssetLoaderForTypeNameError { type_name: String, } /// An error that occurs when an [`AssetLoader`] is not registered for a given [`Asset`] [`TypeId`]. -#[derive(Error, Display, Debug, Clone, PartialEq, Eq)] -#[display("no `AssetLoader` found with the ID '{type_id:?}'")] +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("no `AssetLoader` found with the ID '{type_id:?}'")] pub struct MissingAssetLoaderForTypeIdError { pub type_id: TypeId, } @@ -1846,10 +1850,12 @@ impl core::fmt::Debug for AssetServer { const UNTYPED_SOURCE_SUFFIX: &str = "--untyped"; /// An error when attempting to wait asynchronously for an [`Asset`] to load. -#[derive(Error, Debug, Clone, Display)] +#[derive(Error, Debug, Clone)] pub enum WaitForAssetError { - #[display("tried to wait for an asset that is not being loaded")] + #[error("tried to wait for an asset that is not being loaded")] NotLoaded, + #[error(transparent)] Failed(Arc), + #[error(transparent)] DependencyFailed(Arc), } diff --git a/crates/bevy_color/Cargo.toml b/crates/bevy_color/Cargo.toml index d58c86e886..cb53472950 100644 --- a/crates/bevy_color/Cargo.toml +++ b/crates/bevy_color/Cargo.toml @@ -20,11 +20,8 @@ bytemuck = { version = "1", features = ["derive"] } serde = { version = "1.0", features = [ "derive", ], default-features = false, optional = true } -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } +derive_more = { version = "1", default-features = false, features = ["from"] } wgpu-types = { version = "23", default-features = false, optional = true } encase = { version = "0.10", default-features = false, optional = true } diff --git a/crates/bevy_color/src/srgba.rs b/crates/bevy_color/src/srgba.rs index d8f247b703..8f4549df3b 100644 --- a/crates/bevy_color/src/srgba.rs +++ b/crates/bevy_color/src/srgba.rs @@ -7,7 +7,7 @@ use alloc::{format, string::String}; use bevy_math::{ops, Vec3, Vec4}; #[cfg(feature = "bevy_reflect")] use bevy_reflect::prelude::*; -use derive_more::derive::{Display, Error, From}; +use thiserror::Error; /// Non-linear standard RGB with alpha. #[doc = include_str!("../docs/conversion.md")] @@ -424,17 +424,16 @@ impl From for Xyza { } /// Error returned if a hex string could not be parsed as a color. -#[derive(Debug, Error, Display, PartialEq, Eq, From)] +#[derive(Debug, Error, PartialEq, Eq)] pub enum HexColorError { /// Parsing error. - #[display("Invalid hex string")] - Parse(core::num::ParseIntError), + #[error("Invalid hex string")] + Parse(#[from] core::num::ParseIntError), /// Invalid length. - #[display("Unexpected length of hex string")] + #[error("Unexpected length of hex string")] Length, /// Invalid character. - #[display("Invalid hex char")] - #[error(ignore)] + #[error("Invalid hex char")] Char(char), } diff --git a/crates/bevy_core_pipeline/Cargo.toml b/crates/bevy_core_pipeline/Cargo.toml index 31d37eeead..6298abb35d 100644 --- a/crates/bevy_core_pipeline/Cargo.toml +++ b/crates/bevy_core_pipeline/Cargo.toml @@ -41,11 +41,7 @@ bitflags = "2.3" radsort = "0.1" nonmax = "0.5" smallvec = "1" -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } [lints] workspace = true diff --git a/crates/bevy_core_pipeline/src/auto_exposure/compensation_curve.rs b/crates/bevy_core_pipeline/src/auto_exposure/compensation_curve.rs index d984b4a836..25ec27cee4 100644 --- a/crates/bevy_core_pipeline/src/auto_exposure/compensation_curve.rs +++ b/crates/bevy_core_pipeline/src/auto_exposure/compensation_curve.rs @@ -10,7 +10,7 @@ use bevy_render::{ }, renderer::{RenderDevice, RenderQueue}, }; -use derive_more::derive::{Display, Error}; +use thiserror::Error; const LUT_SIZE: usize = 256; @@ -40,16 +40,16 @@ pub struct AutoExposureCompensationCurve { } /// Various errors that can occur when constructing an [`AutoExposureCompensationCurve`]. -#[derive(Error, Display, Debug)] +#[derive(Error, Debug)] pub enum AutoExposureCompensationCurveError { /// The curve couldn't be built in the first place. - #[display("curve could not be constructed from the given data")] + #[error("curve could not be constructed from the given data")] InvalidCurve, /// A discontinuity was found in the curve. - #[display("discontinuity found between curve segments")] + #[error("discontinuity found between curve segments")] DiscontinuityFound, /// The curve is not monotonically increasing on the x-axis. - #[display("curve is not monotonically increasing on the x-axis")] + #[error("curve is not monotonically increasing on the x-axis")] NotMonotonic, } diff --git a/crates/bevy_ecs/Cargo.toml b/crates/bevy_ecs/Cargo.toml index 222788ec81..166c0178e4 100644 --- a/crates/bevy_ecs/Cargo.toml +++ b/crates/bevy_ecs/Cargo.toml @@ -32,8 +32,8 @@ concurrent-queue = "2.5.0" disqualified = "1.0" fixedbitset = "0.5" serde = { version = "1", optional = true, default-features = false } +thiserror = { version = "2", default-features = false } derive_more = { version = "1", default-features = false, features = [ - "error", "from", "display", "into", diff --git a/crates/bevy_ecs/src/component.rs b/crates/bevy_ecs/src/component.rs index 9bdb0cb6ff..56e06315e5 100644 --- a/crates/bevy_ecs/src/component.rs +++ b/crates/bevy_ecs/src/component.rs @@ -27,7 +27,7 @@ use core::{ marker::PhantomData, mem::needs_drop, }; -use derive_more::derive::{Display, Error}; +use thiserror::Error; pub use bevy_ecs_macros::require; @@ -1836,18 +1836,14 @@ impl FromWorld for InitComponentId { } /// An error returned when the registration of a required component fails. -#[derive(Error, Display, Debug)] +#[derive(Error, Debug)] #[non_exhaustive] pub enum RequiredComponentsError { /// The component is already a directly required component for the requiree. - #[display("Component {0:?} already directly requires component {_1:?}")] - #[error(ignore)] + #[error("Component {0:?} already directly requires component {1:?}")] DuplicateRegistration(ComponentId, ComponentId), /// An archetype with the component that requires other components already exists - #[display( - "An archetype with the component {_0:?} that requires other components already exists" - )] - #[error(ignore)] + #[error("An archetype with the component {0:?} that requires other components already exists")] ArchetypeExists(ComponentId), } diff --git a/crates/bevy_ecs/src/lib.rs b/crates/bevy_ecs/src/lib.rs index 20f40f7036..cfe4557d64 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -45,7 +45,7 @@ pub use bevy_ptr as ptr; /// /// This includes the most common types in this crate, re-exported for your convenience. pub mod prelude { - #[expect(deprecated)] + #[allow(deprecated)] #[doc(hidden)] pub use crate::{ bundle::Bundle, diff --git a/crates/bevy_ecs/src/query/error.rs b/crates/bevy_ecs/src/query/error.rs index 9adf7d542c..97cc011d39 100644 --- a/crates/bevy_ecs/src/query/error.rs +++ b/crates/bevy_ecs/src/query/error.rs @@ -1,4 +1,4 @@ -use derive_more::derive::{Display, Error}; +use thiserror::Error; use crate::{entity::Entity, world::unsafe_world_cell::UnsafeWorldCell}; @@ -90,15 +90,13 @@ impl<'w> Eq for QueryEntityError<'w> {} /// An error that occurs when evaluating a [`Query`](crate::system::Query) or [`QueryState`](crate::query::QueryState) as a single expected result via /// [`get_single`](crate::system::Query::get_single) or [`get_single_mut`](crate::system::Query::get_single_mut). -#[derive(Debug, Error, Display)] +#[derive(Debug, Error)] pub enum QuerySingleError { /// No entity fits the query. - #[display("No entities fit the query {_0}")] - #[error(ignore)] + #[error("No entities fit the query {0}")] NoEntities(&'static str), /// Multiple entities fit the query. - #[display("Multiple entities fit the query {_0}")] - #[error(ignore)] + #[error("Multiple entities fit the query {0}")] MultipleEntities(&'static str), } diff --git a/crates/bevy_ecs/src/schedule/schedule.rs b/crates/bevy_ecs/src/schedule/schedule.rs index a68edd1adb..449b609a28 100644 --- a/crates/bevy_ecs/src/schedule/schedule.rs +++ b/crates/bevy_ecs/src/schedule/schedule.rs @@ -9,9 +9,9 @@ use bevy_utils::{ tracing::{error, info, warn}, AHasher, HashMap, HashSet, }; -use derive_more::derive::{Display, Error}; use disqualified::ShortName; use fixedbitset::FixedBitSet; +use thiserror::Error; use crate::{ self as bevy_ecs, @@ -1933,43 +1933,42 @@ impl ScheduleGraph { } /// Category of errors encountered during schedule construction. -#[derive(Error, Display, Debug)] -#[error(ignore)] +#[derive(Error, Debug)] #[non_exhaustive] pub enum ScheduleBuildError { /// A system set contains itself. - #[display("System set `{_0}` contains itself.")] + #[error("System set `{0}` contains itself.")] HierarchyLoop(String), /// The hierarchy of system sets contains a cycle. - #[display("System set hierarchy contains cycle(s).\n{_0}")] + #[error("System set hierarchy contains cycle(s).\n{0}")] HierarchyCycle(String), /// The hierarchy of system sets contains redundant edges. /// /// This error is disabled by default, but can be opted-in using [`ScheduleBuildSettings`]. - #[display("System set hierarchy contains redundant edges.\n{_0}")] + #[error("System set hierarchy contains redundant edges.\n{0}")] HierarchyRedundancy(String), /// A system (set) has been told to run before itself. - #[display("System set `{_0}` depends on itself.")] + #[error("System set `{0}` depends on itself.")] DependencyLoop(String), /// The dependency graph contains a cycle. - #[display("System dependencies contain cycle(s).\n{_0}")] + #[error("System dependencies contain cycle(s).\n{0}")] DependencyCycle(String), /// Tried to order a system (set) relative to a system set it belongs to. - #[display("`{_0}` and `{_1}` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.")] + #[error("`{0}` and `{1}` have both `in_set` and `before`-`after` relationships (these might be transitive). This combination is unsolvable as a system cannot run before or after a set it belongs to.")] CrossDependency(String, String), /// Tried to order system sets that share systems. - #[display("`{_0}` and `{_1}` have a `before`-`after` relationship (which may be transitive) but share systems.")] + #[error("`{0}` and `{1}` have a `before`-`after` relationship (which may be transitive) but share systems.")] SetsHaveOrderButIntersect(String, String), /// Tried to order a system (set) relative to all instances of some system function. - #[display("Tried to order against `{_0}` in a schedule that has more than one `{_0}` instance. `{_0}` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.")] + #[error("Tried to order against `{0}` in a schedule that has more than one `{0}` instance. `{0}` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.")] SystemTypeSetAmbiguity(String), /// Systems with conflicting access have indeterminate run order. /// /// This error is disabled by default, but can be opted-in using [`ScheduleBuildSettings`]. - #[display("Systems with conflicting access have indeterminate run order.\n{_0}")] + #[error("Systems with conflicting access have indeterminate run order.\n{0}")] Ambiguity(String), /// Tried to run a schedule before all of its systems have been initialized. - #[display("Systems in schedule have not been initialized.")] + #[error("Systems in schedule have not been initialized.")] Uninitialized, } @@ -2040,8 +2039,8 @@ impl ScheduleBuildSettings { /// Error to denote that [`Schedule::initialize`] or [`Schedule::run`] has not yet been called for /// this schedule. -#[derive(Error, Display, Debug)] -#[display("executable schedule has not been built")] +#[derive(Error, Debug)] +#[error("executable schedule has not been built")] pub struct ScheduleNotInitialized; #[cfg(test)] diff --git a/crates/bevy_ecs/src/schedule/stepping.rs b/crates/bevy_ecs/src/schedule/stepping.rs index c5a964a2cb..9c607f6ce0 100644 --- a/crates/bevy_ecs/src/schedule/stepping.rs +++ b/crates/bevy_ecs/src/schedule/stepping.rs @@ -10,7 +10,7 @@ use bevy_utils::{ tracing::{info, warn}, TypeIdMap, }; -use derive_more::derive::{Display, Error}; +use thiserror::Error; #[cfg(not(feature = "bevy_debug_stepping"))] use bevy_utils::tracing::error; @@ -90,8 +90,8 @@ enum Update { ClearBehavior(InternedScheduleLabel, SystemIdentifier), } -#[derive(Error, Display, Debug)] -#[display("not available until all configured schedules have been run; try again next frame")] +#[derive(Error, Debug)] +#[error("not available until all configured schedules have been run; try again next frame")] pub struct NotReady; #[derive(Resource, Default)] diff --git a/crates/bevy_ecs/src/system/system.rs b/crates/bevy_ecs/src/system/system.rs index e68287c699..c1c628cb2e 100644 --- a/crates/bevy_ecs/src/system/system.rs +++ b/crates/bevy_ecs/src/system/system.rs @@ -1,6 +1,6 @@ use bevy_utils::tracing::warn; use core::fmt::Debug; -use derive_more::derive::{Display, Error}; +use thiserror::Error; use crate::{ archetype::ArchetypeComponentId, @@ -357,13 +357,12 @@ impl RunSystemOnce for &mut World { } /// Running system failed. -#[derive(Error, Display)] +#[derive(Error)] pub enum RunSystemError { /// System could not be run due to parameters that failed validation. /// /// This can occur because the data required by the system was not present in the world. - #[display("The data required by the system {_0:?} was not found in the world and the system did not run due to failed parameter validation.")] - #[error(ignore)] + #[error("The data required by the system {0:?} was not found in the world and the system did not run due to failed parameter validation.")] InvalidParams(Cow<'static, str>), } diff --git a/crates/bevy_ecs/src/system/system_registry.rs b/crates/bevy_ecs/src/system/system_registry.rs index 573194713f..f00740a1f7 100644 --- a/crates/bevy_ecs/src/system/system_registry.rs +++ b/crates/bevy_ecs/src/system/system_registry.rs @@ -12,7 +12,7 @@ use bevy_ecs_macros::{Component, Resource}; #[cfg(feature = "bevy_reflect")] use bevy_reflect::Reflect; use core::marker::PhantomData; -use derive_more::derive::{Display, Error}; +use thiserror::Error; /// A small wrapper for [`BoxedSystem`] that also keeps track whether or not the system has been initialized. #[derive(Component)] @@ -613,28 +613,28 @@ where } /// An operation with stored systems failed. -#[derive(Error, Display)] +#[derive(Error)] pub enum RegisteredSystemError { /// A system was run by id, but no system with that id was found. /// /// Did you forget to register it? - #[display("System {_0:?} was not registered")] + #[error("System {0:?} was not registered")] SystemIdNotRegistered(SystemId), /// A cached system was removed by value, but no system with its type was found. /// /// Did you forget to register it? - #[display("Cached system was not found")] + #[error("Cached system was not found")] SystemNotCached, /// A system tried to run itself recursively. - #[display("System {_0:?} tried to run itself recursively")] + #[error("System {0:?} tried to run itself recursively")] Recursive(SystemId), /// A system tried to remove itself. - #[display("System {_0:?} tried to remove itself")] + #[error("System {0:?} tried to remove itself")] SelfRemove(SystemId), /// System could not be run due to parameters that failed validation. /// /// This can occur because the data required by the system was not present in the world. - #[display("The data required by the system {_0:?} was not found in the world and the system did not run due to failed parameter validation.")] + #[error("The data required by the system {0:?} was not found in the world and the system did not run due to failed parameter validation.")] InvalidParams(SystemId), } diff --git a/crates/bevy_ecs/src/world/entity_ref.rs b/crates/bevy_ecs/src/world/entity_ref.rs index e78ac882b5..87e28c2fa6 100644 --- a/crates/bevy_ecs/src/world/entity_ref.rs +++ b/crates/bevy_ecs/src/world/entity_ref.rs @@ -15,7 +15,7 @@ use crate::{ use bevy_ptr::{OwningPtr, Ptr}; use bevy_utils::{HashMap, HashSet}; use core::{any::TypeId, marker::PhantomData, mem::MaybeUninit}; -use derive_more::derive::{Display, Error}; +use thiserror::Error; use super::{unsafe_world_cell::UnsafeEntityCell, Ref, ON_REMOVE, ON_REPLACE}; @@ -3019,19 +3019,15 @@ impl<'a> From<&'a mut EntityWorldMut<'_>> for FilteredEntityMut<'a> { /// Error type returned by [`TryFrom`] conversions from filtered entity types /// ([`FilteredEntityRef`]/[`FilteredEntityMut`]) to full-access entity types /// ([`EntityRef`]/[`EntityMut`]). -#[derive(Error, Display, Debug)] +#[derive(Error, Debug)] pub enum TryFromFilteredError { /// Error indicating that the filtered entity does not have read access to /// all components. - #[display( - "Conversion failed, filtered entity ref does not have read access to all components" - )] + #[error("Conversion failed, filtered entity ref does not have read access to all components")] MissingReadAllAccess, /// Error indicating that the filtered entity does not have write access to /// all components. - #[display( - "Conversion failed, filtered entity ref does not have write access to all components" - )] + #[error("Conversion failed, filtered entity ref does not have write access to all components")] MissingWriteAllAccess, } diff --git a/crates/bevy_ecs/src/world/error.rs b/crates/bevy_ecs/src/world/error.rs index 71589789df..91cd2fa034 100644 --- a/crates/bevy_ecs/src/world/error.rs +++ b/crates/bevy_ecs/src/world/error.rs @@ -1,39 +1,34 @@ //! Contains error types returned by bevy's schedule. -use derive_more::derive::{Display, Error}; +use thiserror::Error; use crate::{component::ComponentId, entity::Entity, schedule::InternedScheduleLabel}; /// The error type returned by [`World::try_run_schedule`] if the provided schedule does not exist. /// /// [`World::try_run_schedule`]: crate::world::World::try_run_schedule -#[derive(Error, Display, Debug)] -#[display("The schedule with the label {_0:?} was not found.")] -#[error(ignore)] +#[derive(Error, Debug)] +#[error("The schedule with the label {0:?} was not found.")] pub struct TryRunScheduleError(pub InternedScheduleLabel); /// An error that occurs when dynamically retrieving components from an entity. -#[derive(Error, Display, Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Error, Debug, Clone, Copy, PartialEq, Eq)] pub enum EntityComponentError { /// The component with the given [`ComponentId`] does not exist on the entity. - #[display("The component with ID {_0:?} does not exist on the entity.")] - #[error(ignore)] + #[error("The component with ID {0:?} does not exist on the entity.")] MissingComponent(ComponentId), /// The component with the given [`ComponentId`] was requested mutably more than once. - #[display("The component with ID {_0:?} was requested mutably more than once.")] - #[error(ignore)] + #[error("The component with ID {0:?} was requested mutably more than once.")] AliasedMutability(ComponentId), } /// An error that occurs when fetching entities mutably from a world. -#[derive(Error, Display, Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Error, Debug, Clone, Copy, PartialEq, Eq)] pub enum EntityFetchError { /// The entity with the given ID does not exist. - #[display("The entity with ID {_0:?} does not exist.")] - #[error(ignore)] + #[error("The entity with ID {0:?} does not exist.")] NoSuchEntity(Entity), /// The entity with the given ID was requested mutably more than once. - #[display("The entity with ID {_0:?} was requested mutably more than once.")] - #[error(ignore)] + #[error("The entity with ID {0:?} was requested mutably more than once.")] AliasedMutability(Entity), } diff --git a/crates/bevy_ecs/src/world/reflect.rs b/crates/bevy_ecs/src/world/reflect.rs index cb6c76920e..f0f9829265 100644 --- a/crates/bevy_ecs/src/world/reflect.rs +++ b/crates/bevy_ecs/src/world/reflect.rs @@ -2,7 +2,7 @@ use core::any::TypeId; -use derive_more::derive::{Display, Error}; +use thiserror::Error; use bevy_reflect::{Reflect, ReflectFromPtr}; @@ -198,7 +198,7 @@ impl World { } /// The error type returned by [`World::get_reflect`] and [`World::get_reflect_mut`]. -#[derive(Error, Display, Debug)] +#[derive(Error, Debug)] pub enum GetComponentReflectError { /// There is no [`ComponentId`] corresponding to the given [`TypeId`]. /// @@ -208,14 +208,11 @@ pub enum GetComponentReflectError { /// See the documentation for [`bevy_reflect`] for more information. /// /// [`App::register_type`]: ../../../bevy_app/struct.App.html#method.register_type - #[display( - "No `ComponentId` corresponding to {_0:?} found (did you call App::register_type()?)" - )] - #[error(ignore)] + #[error("No `ComponentId` corresponding to {0:?} found (did you call App::register_type()?)")] NoCorrespondingComponentId(TypeId), /// The given [`Entity`] does not have a [`Component`] corresponding to the given [`TypeId`]. - #[display("The given `Entity` {entity:?} does not have a `{component_name:?}` component ({component_id:?}, which corresponds to {type_id:?})")] + #[error("The given `Entity` {entity:?} does not have a `{component_name:?}` component ({component_id:?}, which corresponds to {type_id:?})")] EntityDoesNotHaveComponent { /// The given [`Entity`]. entity: Entity, @@ -229,7 +226,7 @@ pub enum GetComponentReflectError { }, /// The [`World`] was missing the [`AppTypeRegistry`] resource. - #[display("The `World` was missing the `AppTypeRegistry` resource")] + #[error("The `World` was missing the `AppTypeRegistry` resource")] MissingAppTypeRegistry, /// The [`World`]'s [`TypeRegistry`] did not contain [`TypeData`] for [`ReflectFromPtr`] for the given [`TypeId`]. @@ -243,8 +240,7 @@ pub enum GetComponentReflectError { /// [`TypeRegistry`]: bevy_reflect::TypeRegistry /// [`ReflectFromPtr`]: bevy_reflect::ReflectFromPtr /// [`App::register_type`]: ../../../bevy_app/struct.App.html#method.register_type - #[display("The `World`'s `TypeRegistry` did not contain `TypeData` for `ReflectFromPtr` for the given {_0:?} (did you call `App::register_type()`?)")] - #[error(ignore)] + #[error("The `World`'s `TypeRegistry` did not contain `TypeData` for `ReflectFromPtr` for the given {0:?} (did you call `App::register_type()`?)")] MissingReflectFromPtrTypeData(TypeId), } diff --git a/crates/bevy_ecs/src/world/unsafe_world_cell.rs b/crates/bevy_ecs/src/world/unsafe_world_cell.rs index 1a4a3d343b..aed797c555 100644 --- a/crates/bevy_ecs/src/world/unsafe_world_cell.rs +++ b/crates/bevy_ecs/src/world/unsafe_world_cell.rs @@ -21,7 +21,7 @@ use bevy_ptr::Ptr; #[cfg(feature = "track_change_detection")] use bevy_ptr::UnsafeCellDeref; use core::{any::TypeId, cell::UnsafeCell, fmt::Debug, marker::PhantomData, ptr}; -use derive_more::derive::{Display, Error}; +use thiserror::Error; /// Variant of the [`World`] where resource and component accesses take `&self`, and the responsibility to avoid /// aliasing violations are given to the caller instead of being checked at compile-time by rust's unique XOR shared rule. @@ -1033,14 +1033,17 @@ impl<'w> UnsafeEntityCell<'w> { } /// Error that may be returned when calling [`UnsafeEntityCell::get_mut_by_id`]. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Error, Display)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)] pub enum GetEntityMutByIdError { /// The [`ComponentInfo`](crate::component::ComponentInfo) could not be found. + #[error("the `ComponentInfo` could not be found")] InfoNotFound, /// The [`Component`] is immutable. Creating a mutable reference violates its /// invariants. + #[error("the `Component` is immutable")] ComponentIsImmutable, /// This [`Entity`] does not have the desired [`Component`]. + #[error("the `Component` could not be found")] ComponentNotFound, } diff --git a/crates/bevy_gilrs/Cargo.toml b/crates/bevy_gilrs/Cargo.toml index 5f4dd54805..cd20696e77 100644 --- a/crates/bevy_gilrs/Cargo.toml +++ b/crates/bevy_gilrs/Cargo.toml @@ -18,11 +18,7 @@ bevy_time = { path = "../bevy_time", version = "0.15.0-dev" } # other gilrs = "0.11.0" -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } [lints] workspace = true diff --git a/crates/bevy_gilrs/src/rumble.rs b/crates/bevy_gilrs/src/rumble.rs index a4466e49ae..62c6b0dc7d 100644 --- a/crates/bevy_gilrs/src/rumble.rs +++ b/crates/bevy_gilrs/src/rumble.rs @@ -10,11 +10,11 @@ use bevy_utils::{ tracing::{debug, warn}, Duration, HashMap, }; -use derive_more::derive::{Display, Error, From}; use gilrs::{ ff::{self, BaseEffect, BaseEffectType, Repeat, Replay}, GamepadId, }; +use thiserror::Error; /// A rumble effect that is currently in effect. struct RunningRumble { @@ -27,12 +27,12 @@ struct RunningRumble { effect: SyncCell, } -#[derive(Error, Display, Debug, From)] +#[derive(Error, Debug)] enum RumbleError { - #[display("gamepad not found")] + #[error("gamepad not found")] GamepadNotFound, - #[display("gilrs error while rumbling gamepad: {_0}")] - GilrsError(ff::Error), + #[error("gilrs error while rumbling gamepad: {0}")] + GilrsError(#[from] ff::Error), } /// Contains the gilrs rumble effects that are currently running for each gamepad diff --git a/crates/bevy_gltf/Cargo.toml b/crates/bevy_gltf/Cargo.toml index c25bb05778..db5e6e53d0 100644 --- a/crates/bevy_gltf/Cargo.toml +++ b/crates/bevy_gltf/Cargo.toml @@ -54,11 +54,7 @@ gltf = { version = "1.4.0", default-features = false, features = [ "names", "utils", ] } -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } base64 = "0.22.0" percent-encoding = "2.1" serde = { version = "1.0", features = ["derive"] } diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index 84c565bd8e..f3c0a4d9fb 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -45,7 +45,6 @@ use bevy_utils::{ tracing::{error, info_span, warn}, HashMap, HashSet, }; -use derive_more::derive::{Display, Error, From}; use gltf::{ accessor::Iter, image::Source, @@ -60,6 +59,7 @@ use std::{ io::Error, path::{Path, PathBuf}, }; +use thiserror::Error; #[cfg(feature = "bevy_animation")] use { bevy_animation::{prelude::*, AnimationTarget, AnimationTargetId}, @@ -67,59 +67,56 @@ use { }; /// An error that occurs when loading a glTF file. -#[derive(Error, Display, Debug, From)] +#[derive(Error, Debug)] pub enum GltfError { /// Unsupported primitive mode. - #[display("unsupported primitive mode")] + #[error("unsupported primitive mode")] UnsupportedPrimitive { /// The primitive mode. mode: Mode, }, /// Invalid glTF file. - #[display("invalid glTF file: {_0}")] - Gltf(gltf::Error), + #[error("invalid glTF file: {0}")] + Gltf(#[from] gltf::Error), /// Binary blob is missing. - #[display("binary blob is missing")] + #[error("binary blob is missing")] MissingBlob, /// Decoding the base64 mesh data failed. - #[display("failed to decode base64 mesh data")] - Base64Decode(base64::DecodeError), + #[error("failed to decode base64 mesh data")] + Base64Decode(#[from] base64::DecodeError), /// Unsupported buffer format. - #[display("unsupported buffer format")] + #[error("unsupported buffer format")] BufferFormatUnsupported, /// Invalid image mime type. - #[display("invalid image mime type: {_0}")] - #[error(ignore)] + #[error("invalid image mime type: {0}")] #[from(ignore)] InvalidImageMimeType(String), /// Error when loading a texture. Might be due to a disabled image file format feature. - #[display("You may need to add the feature for the file format: {_0}")] - ImageError(TextureError), + #[error("You may need to add the feature for the file format: {0}")] + ImageError(#[from] TextureError), /// Failed to read bytes from an asset path. - #[display("failed to read bytes from an asset path: {_0}")] - ReadAssetBytesError(ReadAssetBytesError), + #[error("failed to read bytes from an asset path: {0}")] + ReadAssetBytesError(#[from] ReadAssetBytesError), /// Failed to load asset from an asset path. - #[display("failed to load asset from an asset path: {_0}")] - AssetLoadError(AssetLoadError), + #[error("failed to load asset from an asset path: {0}")] + AssetLoadError(#[from] AssetLoadError), /// Missing sampler for an animation. - #[display("Missing sampler for animation {_0}")] - #[error(ignore)] + #[error("Missing sampler for animation {0}")] #[from(ignore)] MissingAnimationSampler(usize), /// Failed to generate tangents. - #[display("failed to generate tangents: {_0}")] - GenerateTangentsError(bevy_render::mesh::GenerateTangentsError), + #[error("failed to generate tangents: {0}")] + GenerateTangentsError(#[from] bevy_render::mesh::GenerateTangentsError), /// Failed to generate morph targets. - #[display("failed to generate morph targets: {_0}")] - MorphTarget(bevy_render::mesh::morph::MorphBuildError), + #[error("failed to generate morph targets: {0}")] + MorphTarget(#[from] bevy_render::mesh::morph::MorphBuildError), /// Circular children in Nodes - #[display("GLTF model must be a tree, found cycle instead at node indices: {_0:?}")] - #[error(ignore)] + #[error("GLTF model must be a tree, found cycle instead at node indices: {0:?}")] #[from(ignore)] CircularChildren(String), /// Failed to load a file. - #[display("failed to load file: {_0}")] - Io(Error), + #[error("failed to load file: {0}")] + Io(#[from] Error), } /// Loads glTF files with all of their data as their corresponding bevy representations. diff --git a/crates/bevy_gltf/src/vertex_attributes.rs b/crates/bevy_gltf/src/vertex_attributes.rs index 1ecf477f7b..d42ecbf397 100644 --- a/crates/bevy_gltf/src/vertex_attributes.rs +++ b/crates/bevy_gltf/src/vertex_attributes.rs @@ -4,11 +4,11 @@ use bevy_render::{ render_resource::VertexFormat, }; use bevy_utils::HashMap; -use derive_more::derive::{Display, Error}; use gltf::{ accessor::{DataType, Dimensions}, mesh::util::{ReadColors, ReadJoints, ReadTexCoords, ReadWeights}, }; +use thiserror::Error; /// Represents whether integer data requires normalization #[derive(Copy, Clone)] @@ -30,11 +30,11 @@ impl Normalization { } /// An error that occurs when accessing buffer data -#[derive(Error, Display, Debug)] +#[derive(Error, Debug)] pub(crate) enum AccessFailed { - #[display("Malformed vertex attribute data")] + #[error("Malformed vertex attribute data")] MalformedData, - #[display("Unsupported vertex attribute format")] + #[error("Unsupported vertex attribute format")] UnsupportedFormat, } @@ -241,16 +241,13 @@ enum ConversionMode { TexCoord, } -#[derive(Error, Display, Debug)] -#[error(ignore)] +#[derive(Error, Debug)] pub(crate) enum ConvertAttributeError { - #[display( - "Vertex attribute {_0} has format {_1:?} but expected {_3:?} for target attribute {_2}" - )] + #[error("Vertex attribute {0} has format {1:?} but expected {3:?} for target attribute {2}")] WrongFormat(String, VertexFormat, String, VertexFormat), - #[display("{_0} in accessor {_1}")] + #[error("{0} in accessor {1}")] AccessFailed(AccessFailed, usize), - #[display("Unknown vertex attribute {_0}")] + #[error("Unknown vertex attribute {0}")] UnknownName(String), } diff --git a/crates/bevy_image/Cargo.toml b/crates/bevy_image/Cargo.toml index 666598723b..df033d64d6 100644 --- a/crates/bevy_image/Cargo.toml +++ b/crates/bevy_image/Cargo.toml @@ -53,11 +53,7 @@ wgpu-types = { version = "23", default-features = false } # TODO: remove dependency on wgpu once https://github.com/gfx-rs/wgpu/pull/6648, 6649 and 6650 have been released wgpu = { version = "23.0.1", default-features = false } serde = { version = "1", features = ["derive"] } -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } futures-lite = "2.0.1" ddsfile = { version = "0.5.2", optional = true } ktx2 = { version = "0.3.0", optional = true } diff --git a/crates/bevy_image/src/compressed_image_saver.rs b/crates/bevy_image/src/compressed_image_saver.rs index 8698a37d87..2203171726 100644 --- a/crates/bevy_image/src/compressed_image_saver.rs +++ b/crates/bevy_image/src/compressed_image_saver.rs @@ -1,15 +1,16 @@ use crate::{Image, ImageFormat, ImageFormatSetting, ImageLoader, ImageLoaderSettings}; use bevy_asset::saver::{AssetSaver, SavedAsset}; -use derive_more::derive::{Display, Error, From}; use futures_lite::AsyncWriteExt; +use thiserror::Error; pub struct CompressedImageSaver; #[non_exhaustive] -#[derive(Debug, Error, Display, From)] +#[derive(Debug, Error)] pub enum CompressedImageSaverError { - Io(std::io::Error), + #[error(transparent)] + Io(#[from] std::io::Error), } impl AssetSaver for CompressedImageSaver { diff --git a/crates/bevy_image/src/exr_texture_loader.rs b/crates/bevy_image/src/exr_texture_loader.rs index 658fcccafd..d9b89dd21e 100644 --- a/crates/bevy_image/src/exr_texture_loader.rs +++ b/crates/bevy_image/src/exr_texture_loader.rs @@ -1,8 +1,8 @@ use crate::{Image, TextureFormatPixelInfo}; use bevy_asset::{io::Reader, AssetLoader, LoadContext, RenderAssetUsages}; -use derive_more::derive::{Display, Error, From}; use image::ImageDecoder; use serde::{Deserialize, Serialize}; +use thiserror::Error; use wgpu_types::{Extent3d, TextureDimension, TextureFormat}; /// Loads EXR textures as Texture assets @@ -18,11 +18,13 @@ pub struct ExrTextureLoaderSettings { /// Possible errors that can be produced by [`ExrTextureLoader`] #[non_exhaustive] -#[derive(Debug, Error, Display, From)] +#[derive(Debug, Error)] #[cfg(feature = "exr")] pub enum ExrTextureLoaderError { - Io(std::io::Error), - ImageError(image::ImageError), + #[error(transparent)] + Io(#[from] std::io::Error), + #[error(transparent)] + ImageError(#[from] image::ImageError), } impl AssetLoader for ExrTextureLoader { diff --git a/crates/bevy_image/src/hdr_texture_loader.rs b/crates/bevy_image/src/hdr_texture_loader.rs index 64032c0430..3177e94865 100644 --- a/crates/bevy_image/src/hdr_texture_loader.rs +++ b/crates/bevy_image/src/hdr_texture_loader.rs @@ -1,9 +1,9 @@ use crate::{Image, TextureFormatPixelInfo}; use bevy_asset::RenderAssetUsages; use bevy_asset::{io::Reader, AssetLoader, LoadContext}; -use derive_more::derive::{Display, Error, From}; use image::DynamicImage; use serde::{Deserialize, Serialize}; +use thiserror::Error; use wgpu_types::{Extent3d, TextureDimension, TextureFormat}; /// Loads HDR textures as Texture assets @@ -16,12 +16,12 @@ pub struct HdrTextureLoaderSettings { } #[non_exhaustive] -#[derive(Debug, Error, Display, From)] +#[derive(Debug, Error)] pub enum HdrTextureLoaderError { - #[display("Could load texture: {_0}")] - Io(std::io::Error), - #[display("Could not extract image: {_0}")] - Image(image::ImageError), + #[error("Could load texture: {0}")] + Io(#[from] std::io::Error), + #[error("Could not extract image: {0}")] + Image(#[from] image::ImageError), } impl AssetLoader for HdrTextureLoader { diff --git a/crates/bevy_image/src/image.rs b/crates/bevy_image/src/image.rs index a0953b74f0..d9f02379f4 100644 --- a/crates/bevy_image/src/image.rs +++ b/crates/bevy_image/src/image.rs @@ -11,8 +11,8 @@ use bevy_math::{AspectRatio, UVec2, UVec3, Vec2}; use bevy_reflect::std_traits::ReflectDefault; use bevy_reflect::Reflect; use core::hash::Hash; -use derive_more::derive::{Display, Error, From}; use serde::{Deserialize, Serialize}; +use thiserror::Error; use wgpu::{SamplerDescriptor, TextureViewDescriptor}; use wgpu_types::{ AddressMode, CompareFunction, Extent3d, Features, FilterMode, SamplerBorderColor, @@ -1393,48 +1393,39 @@ pub enum TranscodeFormat { } /// An error that occurs when accessing specific pixels in a texture -#[derive(Error, Display, Debug)] +#[derive(Error, Debug)] pub enum TextureAccessError { - #[display("out of bounds (x: {x}, y: {y}, z: {z})")] + #[error("out of bounds (x: {x}, y: {y}, z: {z})")] OutOfBounds { x: u32, y: u32, z: u32 }, - #[display("unsupported texture format: {_0:?}")] - #[error(ignore)] + #[error("unsupported texture format: {0:?}")] UnsupportedTextureFormat(TextureFormat), - #[display("attempt to access texture with different dimension")] + #[error("attempt to access texture with different dimension")] WrongDimension, } /// An error that occurs when loading a texture -#[derive(Error, Display, Debug, From)] -#[error(ignore)] +#[derive(Error, Debug)] pub enum TextureError { - #[display("invalid image mime type: {_0}")] - #[from(ignore)] + #[error("invalid image mime type: {0}")] InvalidImageMimeType(String), - #[display("invalid image extension: {_0}")] - #[from(ignore)] + #[error("invalid image extension: {0}")] InvalidImageExtension(String), - #[display("failed to load an image: {_0}")] - ImageError(image::ImageError), - #[display("unsupported texture format: {_0}")] - #[from(ignore)] + #[error("failed to load an image: {0}")] + ImageError(#[from] image::ImageError), + #[error("unsupported texture format: {0}")] UnsupportedTextureFormat(String), - #[display("supercompression not supported: {_0}")] - #[from(ignore)] + #[error("supercompression not supported: {0}")] SuperCompressionNotSupported(String), - #[display("failed to load an image: {_0}")] - #[from(ignore)] + #[error("failed to load an image: {0}")] SuperDecompressionError(String), - #[display("invalid data: {_0}")] - #[from(ignore)] + #[error("invalid data: {0}")] InvalidData(String), - #[display("transcode error: {_0}")] - #[from(ignore)] + #[error("transcode error: {0}")] TranscodeError(String), - #[display("format requires transcoding: {_0:?}")] + #[error("format requires transcoding: {0:?}")] FormatRequiresTranscodingError(TranscodeFormat), /// Only cubemaps with six faces are supported. - #[display("only cubemaps with six faces are supported")] + #[error("only cubemaps with six faces are supported")] IncompleteCubemap, } diff --git a/crates/bevy_image/src/image_loader.rs b/crates/bevy_image/src/image_loader.rs index b3ce3e35f6..949ee78e49 100644 --- a/crates/bevy_image/src/image_loader.rs +++ b/crates/bevy_image/src/image_loader.rs @@ -1,6 +1,6 @@ use crate::image::{Image, ImageFormat, ImageType, TextureError}; use bevy_asset::{io::Reader, AssetLoader, LoadContext, RenderAssetUsages}; -use derive_more::derive::{Display, Error, From}; +use thiserror::Error; use super::{CompressedImageFormats, ImageSampler}; use serde::{Deserialize, Serialize}; @@ -109,12 +109,12 @@ impl Default for ImageLoaderSettings { } #[non_exhaustive] -#[derive(Debug, Error, Display, From)] +#[derive(Debug, Error)] pub enum ImageLoaderError { - #[display("Could load shader: {_0}")] - Io(std::io::Error), - #[display("Could not load texture file: {_0}")] - FileTexture(FileTextureError), + #[error("Could load shader: {0}")] + Io(#[from] std::io::Error), + #[error("Could not load texture file: {0}")] + FileTexture(#[from] FileTextureError), } impl AssetLoader for ImageLoader { @@ -171,8 +171,8 @@ impl AssetLoader for ImageLoader { } /// An error that occurs when loading a texture from a file. -#[derive(Error, Display, Debug)] -#[display("Error reading image file {path}: {error}, this is an error in `bevy_render`.")] +#[derive(Error, Debug)] +#[error("Error reading image file {path}: {error}, this is an error in `bevy_render`.")] pub struct FileTextureError { error: TextureError, path: String, diff --git a/crates/bevy_image/src/image_texture_conversion.rs b/crates/bevy_image/src/image_texture_conversion.rs index fc3531a50d..8d7c7b514f 100644 --- a/crates/bevy_image/src/image_texture_conversion.rs +++ b/crates/bevy_image/src/image_texture_conversion.rs @@ -1,7 +1,7 @@ use crate::{Image, TextureFormatPixelInfo}; use bevy_asset::RenderAssetUsages; -use derive_more::derive::{Display, Error}; use image::{DynamicImage, ImageBuffer}; +use thiserror::Error; use wgpu_types::{Extent3d, TextureDimension, TextureFormat}; impl Image { @@ -204,16 +204,14 @@ impl Image { /// Errors that occur while converting an [`Image`] into a [`DynamicImage`] #[non_exhaustive] -#[derive(Error, Display, Debug)] +#[derive(Error, Debug)] pub enum IntoDynamicImageError { /// Conversion into dynamic image not supported for source format. - #[display("Conversion into dynamic image not supported for {_0:?}.")] - #[error(ignore)] + #[error("Conversion into dynamic image not supported for {0:?}.")] UnsupportedFormat(TextureFormat), /// Encountered an unknown error during conversion. - #[display("Failed to convert into {_0:?}.")] - #[error(ignore)] + #[error("Failed to convert into {0:?}.")] UnknownConversionError(TextureFormat), } diff --git a/crates/bevy_input/Cargo.toml b/crates/bevy_input/Cargo.toml index 5ea757f150..adb3021d5b 100644 --- a/crates/bevy_input/Cargo.toml +++ b/crates/bevy_input/Cargo.toml @@ -37,11 +37,8 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", features = [ # other serde = { version = "1", features = ["derive"], optional = true } -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } +derive_more = { version = "1", default-features = false, features = ["from"] } smol_str = "0.2" [lints] diff --git a/crates/bevy_input/src/gamepad.rs b/crates/bevy_input/src/gamepad.rs index 7c13da902f..8b17525baa 100644 --- a/crates/bevy_input/src/gamepad.rs +++ b/crates/bevy_input/src/gamepad.rs @@ -19,7 +19,8 @@ use bevy_utils::{ tracing::{info, warn}, Duration, HashMap, }; -use derive_more::derive::{Display, Error, From}; +use derive_more::derive::From; +use thiserror::Error; /// A gamepad event. /// @@ -247,26 +248,22 @@ impl GamepadAxisChangedEvent { } /// Errors that occur when setting axis settings for gamepad input. -#[derive(Error, Display, Debug, PartialEq)] +#[derive(Error, Debug, PartialEq)] pub enum AxisSettingsError { /// The given parameter `livezone_lowerbound` was not in range -1.0..=0.0. - #[display("invalid livezone_lowerbound {_0}, expected value [-1.0..=0.0]")] - #[error(ignore)] + #[error("invalid livezone_lowerbound {0}, expected value [-1.0..=0.0]")] LiveZoneLowerBoundOutOfRange(f32), /// The given parameter `deadzone_lowerbound` was not in range -1.0..=0.0. - #[display("invalid deadzone_lowerbound {_0}, expected value [-1.0..=0.0]")] - #[error(ignore)] + #[error("invalid deadzone_lowerbound {0}, expected value [-1.0..=0.0]")] DeadZoneLowerBoundOutOfRange(f32), /// The given parameter `deadzone_lowerbound` was not in range -1.0..=0.0. - #[display("invalid deadzone_upperbound {_0}, expected value [0.0..=1.0]")] - #[error(ignore)] + #[error("invalid deadzone_upperbound {0}, expected value [0.0..=1.0]")] DeadZoneUpperBoundOutOfRange(f32), /// The given parameter `deadzone_lowerbound` was not in range -1.0..=0.0. - #[display("invalid livezone_upperbound {_0}, expected value [0.0..=1.0]")] - #[error(ignore)] + #[error("invalid livezone_upperbound {0}, expected value [0.0..=1.0]")] LiveZoneUpperBoundOutOfRange(f32), /// Parameter `livezone_lowerbound` was not less than or equal to parameter `deadzone_lowerbound`. - #[display("invalid parameter values livezone_lowerbound {} deadzone_lowerbound {}, expected livezone_lowerbound <= deadzone_lowerbound", livezone_lowerbound, deadzone_lowerbound)] + #[error("invalid parameter values livezone_lowerbound {} deadzone_lowerbound {}, expected livezone_lowerbound <= deadzone_lowerbound", livezone_lowerbound, deadzone_lowerbound)] LiveZoneLowerBoundGreaterThanDeadZoneLowerBound { /// The value of the `livezone_lowerbound` parameter. livezone_lowerbound: f32, @@ -274,7 +271,7 @@ pub enum AxisSettingsError { deadzone_lowerbound: f32, }, /// Parameter `deadzone_upperbound` was not less than or equal to parameter `livezone_upperbound`. - #[display("invalid parameter values livezone_upperbound {} deadzone_upperbound {}, expected deadzone_upperbound <= livezone_upperbound", livezone_upperbound, deadzone_upperbound)] + #[error("invalid parameter values livezone_upperbound {} deadzone_upperbound {}, expected deadzone_upperbound <= livezone_upperbound", livezone_upperbound, deadzone_upperbound)] DeadZoneUpperBoundGreaterThanLiveZoneUpperBound { /// The value of the `livezone_upperbound` parameter. livezone_upperbound: f32, @@ -282,24 +279,21 @@ pub enum AxisSettingsError { deadzone_upperbound: f32, }, /// The given parameter was not in range 0.0..=2.0. - #[display("invalid threshold {_0}, expected 0.0 <= threshold <= 2.0")] - #[error(ignore)] + #[error("invalid threshold {0}, expected 0.0 <= threshold <= 2.0")] Threshold(f32), } /// Errors that occur when setting button settings for gamepad input. -#[derive(Error, Display, Debug, PartialEq)] +#[derive(Error, Debug, PartialEq)] pub enum ButtonSettingsError { /// The given parameter was not in range 0.0..=1.0. - #[display("invalid release_threshold {_0}, expected value [0.0..=1.0]")] - #[error(ignore)] + #[error("invalid release_threshold {0}, expected value [0.0..=1.0]")] ReleaseThresholdOutOfRange(f32), /// The given parameter was not in range 0.0..=1.0. - #[display("invalid press_threshold {_0}, expected [0.0..=1.0]")] - #[error(ignore)] + #[error("invalid press_threshold {0}, expected [0.0..=1.0]")] PressThresholdOutOfRange(f32), /// Parameter `release_threshold` was not less than or equal to `press_threshold`. - #[display("invalid parameter values release_threshold {} press_threshold {}, expected release_threshold <= press_threshold", release_threshold, press_threshold)] + #[error("invalid parameter values release_threshold {} press_threshold {}, expected release_threshold <= press_threshold", release_threshold, press_threshold)] ReleaseThresholdGreaterThanPressThreshold { /// The value of the `press_threshold` parameter. press_threshold: f32, diff --git a/crates/bevy_math/Cargo.toml b/crates/bevy_math/Cargo.toml index 9da2e9c045..2e92ea89a8 100644 --- a/crates/bevy_math/Cargo.toml +++ b/crates/bevy_math/Cargo.toml @@ -11,10 +11,9 @@ rust-version = "1.81.0" [dependencies] glam = { version = "0.29", default-features = false, features = ["bytemuck"] } +thiserror = { version = "2", default-features = false } derive_more = { version = "1", default-features = false, features = [ - "error", "from", - "display", "into", ] } itertools = { version = "0.13.0", default-features = false } diff --git a/crates/bevy_math/src/aspect_ratio.rs b/crates/bevy_math/src/aspect_ratio.rs index 1a07de91d3..0289957164 100644 --- a/crates/bevy_math/src/aspect_ratio.rs +++ b/crates/bevy_math/src/aspect_ratio.rs @@ -1,7 +1,8 @@ //! Provides a simple aspect ratio struct to help with calculations. use crate::Vec2; -use derive_more::derive::{Display, Error, Into}; +use derive_more::derive::Into; +use thiserror::Error; #[cfg(feature = "bevy_reflect")] use bevy_reflect::Reflect; @@ -84,15 +85,15 @@ impl TryFrom for AspectRatio { } /// An Error type for when [`super::AspectRatio`] is provided invalid width or height values -#[derive(Error, Display, Debug, PartialEq, Eq, Clone, Copy)] +#[derive(Error, Debug, PartialEq, Eq, Clone, Copy)] pub enum AspectRatioError { /// Error due to width or height having zero as a value. - #[display("AspectRatio error: width or height is zero")] + #[error("AspectRatio error: width or height is zero")] Zero, /// Error due towidth or height being infinite. - #[display("AspectRatio error: width or height is infinite")] + #[error("AspectRatio error: width or height is infinite")] Infinite, /// Error due to width or height being Not a Number (NaN). - #[display("AspectRatio error: width or height is NaN")] + #[error("AspectRatio error: width or height is NaN")] NaN, } diff --git a/crates/bevy_math/src/cubic_splines.rs b/crates/bevy_math/src/cubic_splines.rs index 31fbc8824b..ce57667879 100644 --- a/crates/bevy_math/src/cubic_splines.rs +++ b/crates/bevy_math/src/cubic_splines.rs @@ -7,7 +7,7 @@ use crate::{ Vec2, VectorSpace, }; -use derive_more::derive::{Display, Error}; +use thiserror::Error; #[cfg(feature = "alloc")] use {alloc::vec, alloc::vec::Vec, core::iter::once, itertools::Itertools}; @@ -102,8 +102,8 @@ impl CubicGenerator

for CubicBezier

{ /// An error returned during cubic curve generation for cubic Bezier curves indicating that a /// segment of control points was not present. -#[derive(Clone, Debug, Error, Display)] -#[display("Unable to generate cubic curve: at least one set of control points is required")] +#[derive(Clone, Debug, Error)] +#[error("Unable to generate cubic curve: at least one set of control points is required")] pub struct CubicBezierError; /// A spline interpolated continuously between the nearest two control points, with the position and @@ -527,10 +527,10 @@ impl CyclicCubicGenerator

for CubicBSpline

{ } /// Error during construction of [`CubicNurbs`] -#[derive(Clone, Debug, Error, Display)] +#[derive(Clone, Debug, Error)] pub enum CubicNurbsError { /// Provided the wrong number of knots. - #[display("Wrong number of knots: expected {expected}, provided {provided}")] + #[error("Wrong number of knots: expected {expected}, provided {provided}")] KnotsNumberMismatch { /// Expected number of knots expected: usize, @@ -539,13 +539,13 @@ pub enum CubicNurbsError { }, /// The provided knots had a descending knot pair. Subsequent knots must /// either increase or stay the same. - #[display("Invalid knots: contains descending knot pair")] + #[error("Invalid knots: contains descending knot pair")] DescendingKnots, /// The provided knots were all equal. Knots must contain at least one increasing pair. - #[display("Invalid knots: all knots are equal")] + #[error("Invalid knots: all knots are equal")] ConstantKnots, /// Provided a different number of weights and control points. - #[display("Incorrect number of weights: expected {expected}, provided {provided}")] + #[error("Incorrect number of weights: expected {expected}, provided {provided}")] WeightsNumberMismatch { /// Expected number of weights expected: usize, @@ -553,7 +553,7 @@ pub enum CubicNurbsError { provided: usize, }, /// The number of control points provided is less than 4. - #[display("Not enough control points, at least 4 are required, {provided} were provided")] + #[error("Not enough control points, at least 4 are required, {provided} were provided")] NotEnoughControlPoints { /// The number of control points provided provided: usize, @@ -909,8 +909,8 @@ impl CyclicCubicGenerator

for LinearSpline

{ } /// An error indicating that a spline construction didn't have enough control points to generate a curve. -#[derive(Clone, Debug, Error, Display)] -#[display("Not enough data to build curve: needed at least {expected} control points but was only given {given}")] +#[derive(Clone, Debug, Error)] +#[error("Not enough data to build curve: needed at least {expected} control points but was only given {given}")] pub struct InsufficientDataError { expected: usize, given: usize, diff --git a/crates/bevy_math/src/curve/cores.rs b/crates/bevy_math/src/curve/cores.rs index 237ee47f58..0733045657 100644 --- a/crates/bevy_math/src/curve/cores.rs +++ b/crates/bevy_math/src/curve/cores.rs @@ -10,7 +10,7 @@ use crate::ops; use super::interval::Interval; use core::fmt::Debug; -use derive_more::derive::{Display, Error}; +use thiserror::Error; #[cfg(feature = "alloc")] use {alloc::vec::Vec, itertools::Itertools}; @@ -136,18 +136,18 @@ pub struct EvenCore { } /// An error indicating that an [`EvenCore`] could not be constructed. -#[derive(Debug, Error, Display)] -#[display("Could not construct an EvenCore")] +#[derive(Debug, Error)] +#[error("Could not construct an EvenCore")] pub enum EvenCoreError { /// Not enough samples were provided. - #[display("Need at least two samples to create an EvenCore, but {samples} were provided")] + #[error("Need at least two samples to create an EvenCore, but {samples} were provided")] NotEnoughSamples { /// The number of samples that were provided. samples: usize, }, /// Unbounded domains are not compatible with `EvenCore`. - #[display("Cannot create a EvenCore over an unbounded domain")] + #[error("Cannot create a EvenCore over an unbounded domain")] UnboundedDomain, } @@ -340,11 +340,11 @@ pub struct UnevenCore { } /// An error indicating that an [`UnevenCore`] could not be constructed. -#[derive(Debug, Error, Display)] -#[display("Could not construct an UnevenCore")] +#[derive(Debug, Error)] +#[error("Could not construct an UnevenCore")] pub enum UnevenCoreError { /// Not enough samples were provided. - #[display( + #[error( "Need at least two unique samples to create an UnevenCore, but {samples} were provided" )] NotEnoughSamples { @@ -481,15 +481,15 @@ pub struct ChunkedUnevenCore { } /// An error that indicates that a [`ChunkedUnevenCore`] could not be formed. -#[derive(Debug, Error, Display)] -#[display("Could not create a ChunkedUnevenCore")] +#[derive(Debug, Error)] +#[error("Could not create a ChunkedUnevenCore")] pub enum ChunkedUnevenCoreError { /// The width of a `ChunkedUnevenCore` cannot be zero. - #[display("Chunk width must be at least 1")] + #[error("Chunk width must be at least 1")] ZeroWidth, /// At least two sample times are necessary to interpolate in `ChunkedUnevenCore`. - #[display( + #[error( "Need at least two unique samples to create a ChunkedUnevenCore, but {samples} were provided" )] NotEnoughSamples { @@ -498,7 +498,7 @@ pub enum ChunkedUnevenCoreError { }, /// The length of the value buffer is supposed to be the `width` times the number of samples. - #[display("Expected {expected} total values based on width, but {actual} were provided")] + #[error("Expected {expected} total values based on width, but {actual} were provided")] MismatchedLengths { /// The expected length of the value buffer. expected: usize, @@ -507,7 +507,7 @@ pub enum ChunkedUnevenCoreError { }, /// Tried to infer the width, but the ratio of lengths wasn't an integer, so no such length exists. - #[display("The length of the list of values ({values_len}) was not divisible by that of the list of times ({times_len})")] + #[error("The length of the list of values ({values_len}) was not divisible by that of the list of times ({times_len})")] NonDivisibleLengths { /// The length of the value buffer. values_len: usize, diff --git a/crates/bevy_math/src/curve/interval.rs b/crates/bevy_math/src/curve/interval.rs index f15b21e1cb..6e5f4465ae 100644 --- a/crates/bevy_math/src/curve/interval.rs +++ b/crates/bevy_math/src/curve/interval.rs @@ -4,8 +4,8 @@ use core::{ cmp::{max_by, min_by}, ops::RangeInclusive, }; -use derive_more::derive::{Display, Error}; use itertools::Either; +use thiserror::Error; #[cfg(feature = "bevy_reflect")] use bevy_reflect::Reflect; @@ -29,26 +29,26 @@ pub struct Interval { } /// An error that indicates that an operation would have returned an invalid [`Interval`]. -#[derive(Debug, Error, Display)] -#[display("The resulting interval would be invalid (empty or with a NaN endpoint)")] +#[derive(Debug, Error)] +#[error("The resulting interval would be invalid (empty or with a NaN endpoint)")] pub struct InvalidIntervalError; /// An error indicating that spaced points could not be extracted from an unbounded interval. -#[derive(Debug, Error, Display)] -#[display("Cannot extract spaced points from an unbounded interval")] +#[derive(Debug, Error)] +#[error("Cannot extract spaced points from an unbounded interval")] pub struct SpacedPointsError; /// An error indicating that a linear map between intervals could not be constructed because of /// unboundedness. -#[derive(Debug, Error, Display)] -#[display("Could not construct linear function to map between intervals")] +#[derive(Debug, Error)] +#[error("Could not construct linear function to map between intervals")] pub(super) enum LinearMapError { /// The source interval being mapped out of was unbounded. - #[display("The source interval is unbounded")] + #[error("The source interval is unbounded")] SourceUnbounded, /// The target interval being mapped into was unbounded. - #[display("The target interval is unbounded")] + #[error("The target interval is unbounded")] TargetUnbounded, } diff --git a/crates/bevy_math/src/curve/mod.rs b/crates/bevy_math/src/curve/mod.rs index a1d24301aa..6f8ce6c301 100644 --- a/crates/bevy_math/src/curve/mod.rs +++ b/crates/bevy_math/src/curve/mod.rs @@ -309,8 +309,8 @@ pub use { use crate::VectorSpace; use core::{marker::PhantomData, ops::Deref}; -use derive_more::derive::{Display, Error}; use interval::InvalidIntervalError; +use thiserror::Error; /// A trait for a type that can represent values of type `T` parametrized over a fixed interval. /// @@ -915,74 +915,73 @@ where /// An error indicating that a linear reparameterization couldn't be performed because of /// malformed inputs. -#[derive(Debug, Error, Display)] -#[display("Could not build a linear function to reparametrize this curve")] +#[derive(Debug, Error)] +#[error("Could not build a linear function to reparametrize this curve")] pub enum LinearReparamError { /// The source curve that was to be reparametrized had unbounded domain. - #[display("This curve has unbounded domain")] + #[error("This curve has unbounded domain")] SourceCurveUnbounded, /// The target interval for reparameterization was unbounded. - #[display("The target interval for reparameterization is unbounded")] + #[error("The target interval for reparameterization is unbounded")] TargetIntervalUnbounded, } /// An error indicating that a reversion of a curve couldn't be performed because of /// malformed inputs. -#[derive(Debug, Error, Display)] -#[display("Could not reverse this curve")] +#[derive(Debug, Error)] +#[error("Could not reverse this curve")] pub enum ReverseError { /// The source curve that was to be reversed had unbounded domain end. - #[display("This curve has an unbounded domain end")] + #[error("This curve has an unbounded domain end")] SourceDomainEndInfinite, } /// An error indicating that a repetition of a curve couldn't be performed because of malformed /// inputs. -#[derive(Debug, Error, Display)] -#[display("Could not repeat this curve")] +#[derive(Debug, Error)] +#[error("Could not repeat this curve")] pub enum RepeatError { /// The source curve that was to be repeated had unbounded domain. - #[display("This curve has an unbounded domain")] + #[error("This curve has an unbounded domain")] SourceDomainUnbounded, } /// An error indicating that a ping ponging of a curve couldn't be performed because of /// malformed inputs. -#[derive(Debug, Error, Display)] -#[display("Could not ping pong this curve")] +#[derive(Debug, Error)] +#[error("Could not ping pong this curve")] pub enum PingPongError { /// The source curve that was to be ping ponged had unbounded domain end. - #[display("This curve has an unbounded domain end")] + #[error("This curve has an unbounded domain end")] SourceDomainEndInfinite, } /// An error indicating that an end-to-end composition couldn't be performed because of /// malformed inputs. -#[derive(Debug, Error, Display)] -#[display("Could not compose these curves together")] +#[derive(Debug, Error)] +#[error("Could not compose these curves together")] pub enum ChainError { /// The right endpoint of the first curve was infinite. - #[display("The first curve's domain has an infinite end")] + #[error("The first curve's domain has an infinite end")] FirstEndInfinite, /// The left endpoint of the second curve was infinite. - #[display("The second curve's domain has an infinite start")] + #[error("The second curve's domain has an infinite start")] SecondStartInfinite, } /// An error indicating that a resampling operation could not be performed because of /// malformed inputs. -#[derive(Debug, Error, Display)] -#[display("Could not resample from this curve because of bad inputs")] +#[derive(Debug, Error)] +#[error("Could not resample from this curve because of bad inputs")] pub enum ResamplingError { /// This resampling operation was not provided with enough samples to have well-formed output. - #[display("Not enough unique samples to construct resampled curve")] - #[error(ignore)] + #[error("Not enough unique samples to construct resampled curve")] NotEnoughSamples(usize), /// This resampling operation failed because of an unbounded interval. - #[display("Could not resample because this curve has unbounded domain")] + #[error("Could not resample because this curve has unbounded domain")] UnboundedDomain, } diff --git a/crates/bevy_math/src/primitives/dim2.rs b/crates/bevy_math/src/primitives/dim2.rs index 446a94fcba..f407917c73 100644 --- a/crates/bevy_math/src/primitives/dim2.rs +++ b/crates/bevy_math/src/primitives/dim2.rs @@ -1,5 +1,6 @@ use core::f32::consts::{FRAC_1_SQRT_2, FRAC_PI_2, FRAC_PI_3, PI}; -use derive_more::derive::{Display, Error, From}; +use derive_more::derive::From; +use thiserror::Error; use super::{Measured2d, Primitive2d, WindingOrder}; use crate::{ @@ -1654,10 +1655,10 @@ pub struct ConvexPolygon { impl Primitive2d for ConvexPolygon {} /// An error that happens when creating a [`ConvexPolygon`]. -#[derive(Error, Display, Debug, Clone)] +#[derive(Error, Debug, Clone)] pub enum ConvexPolygonError { /// The created polygon is not convex. - #[display("The created polygon is not convex")] + #[error("The created polygon is not convex")] Concave, } diff --git a/crates/bevy_mesh/Cargo.toml b/crates/bevy_mesh/Cargo.toml index 08336c424c..e5871c3e3c 100644 --- a/crates/bevy_mesh/Cargo.toml +++ b/crates/bevy_mesh/Cargo.toml @@ -27,11 +27,7 @@ bytemuck = { version = "1.5" } wgpu-types = { version = "23", default-features = false } serde = { version = "1", features = ["derive"] } hexasphere = "15.0" -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } [lints] workspace = true diff --git a/crates/bevy_mesh/src/conversions.rs b/crates/bevy_mesh/src/conversions.rs index 58cb9b42d0..f68c2d6f74 100644 --- a/crates/bevy_mesh/src/conversions.rs +++ b/crates/bevy_mesh/src/conversions.rs @@ -26,10 +26,10 @@ use super::VertexAttributeValues; use bevy_math::{IVec2, IVec3, IVec4, UVec2, UVec3, UVec4, Vec2, Vec3, Vec3A, Vec4}; -use derive_more::derive::{Display, Error}; +use thiserror::Error; -#[derive(Debug, Clone, Error, Display)] -#[display("cannot convert VertexAttributeValues::{variant} to {into}")] +#[derive(Debug, Clone, Error)] +#[error("cannot convert VertexAttributeValues::{variant} to {into}")] pub struct FromVertexAttributeError { from: VertexAttributeValues, variant: &'static str, diff --git a/crates/bevy_mesh/src/index.rs b/crates/bevy_mesh/src/index.rs index b00baf41e1..854eaaad8a 100644 --- a/crates/bevy_mesh/src/index.rs +++ b/crates/bevy_mesh/src/index.rs @@ -1,7 +1,7 @@ use bevy_reflect::Reflect; use core::iter; use core::iter::FusedIterator; -use derive_more::derive::{Display, Error}; +use thiserror::Error; use wgpu_types::IndexFormat; /// A disjunction of four iterators. This is necessary to have a well-formed type for the output @@ -34,35 +34,35 @@ where } /// An error that occurred while trying to invert the winding of a [`Mesh`](super::Mesh). -#[derive(Debug, Error, Display)] +#[derive(Debug, Error)] pub enum MeshWindingInvertError { /// This error occurs when you try to invert the winding for a mesh with [`PrimitiveTopology::PointList`](super::PrimitiveTopology::PointList). - #[display("Mesh winding invertation does not work for primitive topology `PointList`")] + #[error("Mesh winding invertation does not work for primitive topology `PointList`")] WrongTopology, /// This error occurs when you try to invert the winding for a mesh with /// * [`PrimitiveTopology::TriangleList`](super::PrimitiveTopology::TriangleList), but the indices are not in chunks of 3. /// * [`PrimitiveTopology::LineList`](super::PrimitiveTopology::LineList), but the indices are not in chunks of 2. - #[display("Indices weren't in chunks according to topology")] + #[error("Indices weren't in chunks according to topology")] AbruptIndicesEnd, } /// An error that occurred while trying to extract a collection of triangles from a [`Mesh`](super::Mesh). -#[derive(Debug, Error, Display)] +#[derive(Debug, Error)] pub enum MeshTrianglesError { - #[display("Source mesh does not have primitive topology TriangleList or TriangleStrip")] + #[error("Source mesh does not have primitive topology TriangleList or TriangleStrip")] WrongTopology, - #[display("Source mesh lacks position data")] + #[error("Source mesh lacks position data")] MissingPositions, - #[display("Source mesh position data is not Float32x3")] + #[error("Source mesh position data is not Float32x3")] PositionsFormat, - #[display("Source mesh lacks face index data")] + #[error("Source mesh lacks face index data")] MissingIndices, - #[display("Face index data references vertices that do not exist")] + #[error("Face index data references vertices that do not exist")] BadIndices, } diff --git a/crates/bevy_mesh/src/mikktspace.rs b/crates/bevy_mesh/src/mikktspace.rs index 2aa8680946..c450a8104d 100644 --- a/crates/bevy_mesh/src/mikktspace.rs +++ b/crates/bevy_mesh/src/mikktspace.rs @@ -1,6 +1,6 @@ use super::{Indices, Mesh, VertexAttributeValues}; use bevy_math::Vec3; -use derive_more::derive::{Display, Error}; +use thiserror::Error; use wgpu_types::{PrimitiveTopology, VertexFormat}; struct MikktspaceGeometryHelper<'a> { @@ -53,21 +53,18 @@ impl bevy_mikktspace::Geometry for MikktspaceGeometryHelper<'_> { } } -#[derive(Error, Display, Debug)] +#[derive(Error, Debug)] /// Failed to generate tangents for the mesh. pub enum GenerateTangentsError { - #[display("cannot generate tangents for {_0:?}")] - #[error(ignore)] + #[error("cannot generate tangents for {0:?}")] UnsupportedTopology(PrimitiveTopology), - #[display("missing indices")] + #[error("missing indices")] MissingIndices, - #[display("missing vertex attributes '{_0}'")] - #[error(ignore)] + #[error("missing vertex attributes '{0}'")] MissingVertexAttribute(&'static str), - #[display("the '{_0}' vertex attribute should have {_1:?} format")] - #[error(ignore)] + #[error("the '{0}' vertex attribute should have {1:?} format")] InvalidVertexAttributeFormat(&'static str, VertexFormat), - #[display("mesh not suitable for tangent generation")] + #[error("mesh not suitable for tangent generation")] MikktspaceError, } diff --git a/crates/bevy_mesh/src/morph.rs b/crates/bevy_mesh/src/morph.rs index ce427d7cb0..0c2c2c948c 100644 --- a/crates/bevy_mesh/src/morph.rs +++ b/crates/bevy_mesh/src/morph.rs @@ -6,7 +6,7 @@ use bevy_math::Vec3; use bevy_reflect::prelude::*; use bytemuck::{Pod, Zeroable}; use core::iter; -use derive_more::derive::{Display, Error}; +use thiserror::Error; use wgpu_types::{Extent3d, TextureDimension, TextureFormat}; const MAX_TEXTURE_WIDTH: u32 = 2048; @@ -17,9 +17,9 @@ const MAX_COMPONENTS: u32 = MAX_TEXTURE_WIDTH * MAX_TEXTURE_WIDTH; /// Max target count available for [morph targets](MorphWeights). pub const MAX_MORPH_WEIGHTS: usize = 64; -#[derive(Error, Display, Clone, Debug)] +#[derive(Error, Clone, Debug)] pub enum MorphBuildError { - #[display( + #[error( "Too many vertexĂ—components in morph target, max is {MAX_COMPONENTS}, \ got {vertex_count}Ă—{component_count} = {}", *vertex_count * *component_count as usize @@ -28,7 +28,7 @@ pub enum MorphBuildError { vertex_count: usize, component_count: u32, }, - #[display( + #[error( "Bevy only supports up to {} morph targets (individual poses), tried to \ create a model with {target_count} morph targets", MAX_MORPH_WEIGHTS diff --git a/crates/bevy_mesh/src/primitives/dim3/sphere.rs b/crates/bevy_mesh/src/primitives/dim3/sphere.rs index 1f52566fae..f834f02eab 100644 --- a/crates/bevy_mesh/src/primitives/dim3/sphere.rs +++ b/crates/bevy_mesh/src/primitives/dim3/sphere.rs @@ -2,14 +2,14 @@ use crate::{Indices, Mesh, MeshBuilder, Meshable, PrimitiveTopology}; use bevy_asset::RenderAssetUsages; use bevy_math::{ops, primitives::Sphere}; use core::f32::consts::PI; -use derive_more::derive::{Display, Error}; use hexasphere::shapes::IcoSphere; +use thiserror::Error; /// An error when creating an icosphere [`Mesh`] from a [`SphereMeshBuilder`]. -#[derive(Clone, Copy, Debug, Error, Display)] +#[derive(Clone, Copy, Debug, Error)] pub enum IcosphereError { /// The icosphere has too many vertices. - #[display("Cannot create an icosphere of {subdivisions} subdivisions due to there being too many vertices being generated: {number_of_resulting_points}. (Limited to 65535 vertices or 79 subdivisions)")] + #[error("Cannot create an icosphere of {subdivisions} subdivisions due to there being too many vertices being generated: {number_of_resulting_points}. (Limited to 65535 vertices or 79 subdivisions)")] TooManyVertices { /// The number of subdivisions used. 79 is the largest allowed value for a mesh to be generated. subdivisions: u32, diff --git a/crates/bevy_mesh/src/vertex.rs b/crates/bevy_mesh/src/vertex.rs index c6a2418e9d..4c6a36fc76 100644 --- a/crates/bevy_mesh/src/vertex.rs +++ b/crates/bevy_mesh/src/vertex.rs @@ -5,7 +5,7 @@ use bevy_math::Vec3; use bevy_utils::HashSet; use bytemuck::cast_slice; use core::hash::{Hash, Hasher}; -use derive_more::derive::{Display, Error}; +use thiserror::Error; use wgpu_types::{BufferAddress, VertexAttribute, VertexFormat, VertexStepMode}; #[derive(Debug, Clone, Copy)] @@ -108,8 +108,8 @@ impl MeshVertexBufferLayout { } } -#[derive(Error, Display, Debug)] -#[display("Mesh is missing requested attribute: {name} ({id:?}, pipeline type: {pipeline_type:?})")] +#[derive(Error, Debug)] +#[error("Mesh is missing requested attribute: {name} ({id:?}, pipeline type: {pipeline_type:?})")] pub struct MissingVertexAttributeError { pub pipeline_type: Option<&'static str>, id: MeshVertexAttributeId, diff --git a/crates/bevy_pbr/Cargo.toml b/crates/bevy_pbr/Cargo.toml index 571cd4082b..cd42bfebb8 100644 --- a/crates/bevy_pbr/Cargo.toml +++ b/crates/bevy_pbr/Cargo.toml @@ -52,11 +52,8 @@ bevy_window = { path = "../bevy_window", version = "0.15.0-dev" } # other bitflags = "2.3" fixedbitset = "0.5" -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } +derive_more = { version = "1", default-features = false, features = ["from"] } # meshlet lz4_flex = { version = "0.11", default-features = false, features = [ "frame", diff --git a/crates/bevy_pbr/src/meshlet/asset.rs b/crates/bevy_pbr/src/meshlet/asset.rs index 2589730338..66a84ed832 100644 --- a/crates/bevy_pbr/src/meshlet/asset.rs +++ b/crates/bevy_pbr/src/meshlet/asset.rs @@ -8,10 +8,10 @@ use bevy_math::{Vec2, Vec3}; use bevy_reflect::TypePath; use bevy_tasks::block_on; use bytemuck::{Pod, Zeroable}; -use derive_more::derive::{Display, Error, From}; use half::f16; use lz4_flex::frame::{FrameDecoder, FrameEncoder}; use std::io::{Read, Write}; +use thiserror::Error; /// Unique identifier for the [`MeshletMesh`] asset format. const MESHLET_MESH_ASSET_MAGIC: u64 = 1717551717668; @@ -211,16 +211,16 @@ impl AssetLoader for MeshletMeshLoader { } } -#[derive(Error, Display, Debug, From)] +#[derive(Error, Debug)] pub enum MeshletMeshSaveOrLoadError { - #[display("file was not a MeshletMesh asset")] + #[error("file was not a MeshletMesh asset")] WrongFileType, - #[display("expected asset version {MESHLET_MESH_ASSET_VERSION} but found version {found}")] + #[error("expected asset version {MESHLET_MESH_ASSET_VERSION} but found version {found}")] WrongVersion { found: u64 }, - #[display("failed to compress or decompress asset data")] - CompressionOrDecompression(lz4_flex::frame::Error), - #[display("failed to read or write asset data")] - Io(std::io::Error), + #[error("failed to compress or decompress asset data")] + CompressionOrDecompression(#[from] lz4_flex::frame::Error), + #[error("failed to read or write asset data")] + Io(#[from] std::io::Error), } async fn async_read_u64(reader: &mut dyn Reader) -> Result { diff --git a/crates/bevy_pbr/src/meshlet/from_mesh.rs b/crates/bevy_pbr/src/meshlet/from_mesh.rs index 5b5c503d3d..7a53652967 100644 --- a/crates/bevy_pbr/src/meshlet/from_mesh.rs +++ b/crates/bevy_pbr/src/meshlet/from_mesh.rs @@ -10,7 +10,6 @@ use bevy_render::{ use bevy_utils::HashMap; use bitvec::{order::Lsb0, vec::BitVec, view::BitView}; use core::iter; -use derive_more::derive::{Display, Error}; use half::f16; use itertools::Itertools; use meshopt::{ @@ -19,6 +18,7 @@ use meshopt::{ }; use metis::Graph; use smallvec::SmallVec; +use thiserror::Error; // Aim to have 8 meshlets per group const TARGET_MESHLETS_PER_GROUP: usize = 8; @@ -615,12 +615,12 @@ fn pack2x16snorm(v: Vec2) -> u32 { } /// An error produced by [`MeshletMesh::from_mesh`]. -#[derive(Error, Display, Debug)] +#[derive(Error, Debug)] pub enum MeshToMeshletMeshConversionError { - #[display("Mesh primitive topology is not TriangleList")] + #[error("Mesh primitive topology is not TriangleList")] WrongMeshPrimitiveTopology, - #[display("Mesh attributes are not {{POSITION, NORMAL, UV_0}}")] + #[error("Mesh attributes are not {{POSITION, NORMAL, UV_0}}")] WrongMeshVertexAttributes, - #[display("Mesh has no indices")] + #[error("Mesh has no indices")] MeshMissingIndices, } diff --git a/crates/bevy_reflect/Cargo.toml b/crates/bevy_reflect/Cargo.toml index 25f23db352..010b5a7298 100644 --- a/crates/bevy_reflect/Cargo.toml +++ b/crates/bevy_reflect/Cargo.toml @@ -51,11 +51,8 @@ erased-serde = { version = "0.4", default-features = false, features = [ ] } disqualified = { version = "1.0", default-features = false } downcast-rs = { version = "1.2", default-features = false } -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } +derive_more = { version = "1", default-features = false, features = ["from"] } serde = { version = "1", default-features = false, features = ["alloc"] } spin = { version = "0.9.8", default-features = false, features = [ "once", diff --git a/crates/bevy_reflect/src/enums/variants.rs b/crates/bevy_reflect/src/enums/variants.rs index c29c67770e..3397df50dd 100644 --- a/crates/bevy_reflect/src/enums/variants.rs +++ b/crates/bevy_reflect/src/enums/variants.rs @@ -6,7 +6,7 @@ use alloc::boxed::Box; use alloc::sync::Arc; use bevy_utils::HashMap; use core::slice::Iter; -use derive_more::derive::{Display, Error}; +use thiserror::Error; /// Describes the form of an enum variant. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] @@ -40,12 +40,12 @@ pub enum VariantType { } /// A [`VariantInfo`]-specific error. -#[derive(Debug, Error, Display)] +#[derive(Debug, Error)] pub enum VariantInfoError { /// Caused when a variant was expected to be of a certain [type], but was not. /// /// [type]: VariantType - #[display("variant type mismatch: expected {expected:?}, received {received:?}")] + #[error("variant type mismatch: expected {expected:?}, received {received:?}")] TypeMismatch { expected: VariantType, received: VariantType, diff --git a/crates/bevy_reflect/src/func/args/error.rs b/crates/bevy_reflect/src/func/args/error.rs index 4e1c6f001f..9d66c70393 100644 --- a/crates/bevy_reflect/src/func/args/error.rs +++ b/crates/bevy_reflect/src/func/args/error.rs @@ -1,6 +1,6 @@ use alloc::borrow::Cow; -use derive_more::derive::{Display, Error}; +use thiserror::Error; use crate::func::args::Ownership; @@ -10,19 +10,17 @@ use alloc::{boxed::Box, format, vec}; /// An error that occurs when converting an [argument]. /// /// [argument]: crate::func::args::Arg -#[derive(Debug, Error, Display, PartialEq)] +#[derive(Debug, Error, PartialEq)] pub enum ArgError { /// The argument is not the expected type. - #[display("expected `{expected}` but received `{received}` (@ argument index {index})")] + #[error("expected `{expected}` but received `{received}` (@ argument index {index})")] UnexpectedType { index: usize, expected: Cow<'static, str>, received: Cow<'static, str>, }, /// The argument has the wrong ownership. - #[display( - "expected {expected} value but received {received} value (@ argument index {index})" - )] + #[error("expected {expected} value but received {received} value (@ argument index {index})")] InvalidOwnership { index: usize, expected: Ownership, @@ -31,6 +29,6 @@ pub enum ArgError { /// Occurs when attempting to access an argument from an empty [`ArgList`]. /// /// [`ArgList`]: crate::func::args::ArgList - #[display("expected an argument but received none")] + #[error("expected an argument but received none")] EmptyArgList, } diff --git a/crates/bevy_reflect/src/func/error.rs b/crates/bevy_reflect/src/func/error.rs index ff65a91bd3..234cbb9e6a 100644 --- a/crates/bevy_reflect/src/func/error.rs +++ b/crates/bevy_reflect/src/func/error.rs @@ -1,6 +1,6 @@ use crate::func::{args::ArgError, Return}; use alloc::borrow::Cow; -use derive_more::derive::{Display, Error, From}; +use thiserror::Error; #[cfg(not(feature = "std"))] use alloc::{boxed::Box, format, vec}; @@ -9,12 +9,13 @@ use alloc::{boxed::Box, format, vec}; /// /// [`DynamicFunction`]: crate::func::DynamicFunction /// [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut -#[derive(Debug, Error, Display, PartialEq, From)] +#[derive(Debug, Error, PartialEq)] pub enum FunctionError { /// An error occurred while converting an argument. - ArgError(ArgError), + #[error(transparent)] + ArgError(#[from] ArgError), /// The number of arguments provided does not match the expected number. - #[display("expected {expected} arguments but received {received}")] + #[error("expected {expected} arguments but received {received}")] ArgCountMismatch { expected: usize, received: usize }, } @@ -30,15 +31,14 @@ pub type FunctionResult<'a> = Result, FunctionError>; /// An error that occurs when registering a function into a [`FunctionRegistry`]. /// /// [`FunctionRegistry`]: crate::func::FunctionRegistry -#[derive(Debug, Error, Display, PartialEq)] +#[derive(Debug, Error, PartialEq)] pub enum FunctionRegistrationError { /// A function with the given name has already been registered. /// /// Contains the duplicate function name. - #[display("a function has already been registered with name {_0:?}")] - #[error(ignore)] + #[error("a function has already been registered with name {0:?}")] DuplicateName(Cow<'static, str>), /// The function is missing a name by which it can be registered. - #[display("function name is missing")] + #[error("function name is missing")] MissingName, } diff --git a/crates/bevy_reflect/src/kind.rs b/crates/bevy_reflect/src/kind.rs index 66de3291ea..1120ae5d1f 100644 --- a/crates/bevy_reflect/src/kind.rs +++ b/crates/bevy_reflect/src/kind.rs @@ -1,5 +1,5 @@ use alloc::boxed::Box; -use derive_more::derive::{Display, Error}; +use thiserror::Error; #[cfg(feature = "functions")] use crate::func::Function; @@ -131,8 +131,8 @@ macro_rules! impl_reflect_kind_conversions { /// Caused when a type was expected to be of a certain [kind], but was not. /// /// [kind]: ReflectKind -#[derive(Debug, Error, Display)] -#[display("kind mismatch: expected {expected:?}, received {received:?}")] +#[derive(Debug, Error)] +#[error("kind mismatch: expected {expected:?}, received {received:?}")] pub struct ReflectKindMismatchError { pub expected: ReflectKind, pub received: ReflectKind, diff --git a/crates/bevy_reflect/src/path/mod.rs b/crates/bevy_reflect/src/path/mod.rs index 977882b93b..3fe0504cf7 100644 --- a/crates/bevy_reflect/src/path/mod.rs +++ b/crates/bevy_reflect/src/path/mod.rs @@ -11,23 +11,25 @@ use parse::PathParser; use crate::{PartialReflect, Reflect}; use alloc::vec::Vec; use core::fmt; -use derive_more::derive::{Display, From}; +use derive_more::derive::From; +use thiserror::Error; type PathResult<'a, T> = Result>; /// An error returned from a failed path string query. -#[derive(Debug, PartialEq, Eq, Display, From)] +#[derive(Error, Debug, PartialEq, Eq)] pub enum ReflectPathError<'a> { /// An error caused by trying to access a path that's not able to be accessed, /// see [`AccessError`] for details. + #[error(transparent)] InvalidAccess(AccessError<'a>), /// An error that occurs when a type cannot downcast to a given type. - #[display("Can't downcast result of access to the given type")] + #[error("Can't downcast result of access to the given type")] InvalidDowncast, /// An error caused by an invalid path string that couldn't be parsed. - #[display("Encountered an error at offset {offset} while parsing `{path}`: {error}")] + #[error("Encountered an error at offset {offset} while parsing `{path}`: {error}")] ParseError { /// Position in `path`. offset: usize, @@ -38,7 +40,11 @@ pub enum ReflectPathError<'a> { }, } -impl<'a> core::error::Error for ReflectPathError<'a> {} +impl<'a> From> for ReflectPathError<'a> { + fn from(value: AccessError<'a>) -> Self { + ReflectPathError::InvalidAccess(value) + } +} /// Something that can be interpreted as a reflection path in [`GetPath`]. pub trait ReflectPath<'a>: Sized { diff --git a/crates/bevy_reflect/src/path/parse.rs b/crates/bevy_reflect/src/path/parse.rs index 40b39365ff..bc48fe9c01 100644 --- a/crates/bevy_reflect/src/path/parse.rs +++ b/crates/bevy_reflect/src/path/parse.rs @@ -3,39 +3,34 @@ use core::{ num::ParseIntError, str::from_utf8_unchecked, }; - -use derive_more::derive::{Display, Error, From}; +use thiserror::Error; use super::{Access, ReflectPathError}; /// An error that occurs when parsing reflect path strings. -#[derive(Debug, PartialEq, Eq, Error, Display)] -#[error(ignore)] +#[derive(Debug, PartialEq, Eq, Error)] +#[error(transparent)] pub struct ParseError<'a>(Error<'a>); /// A parse error for a path string. -#[derive(Debug, PartialEq, Eq, Error, Display, From)] +#[derive(Debug, PartialEq, Eq, Error)] enum Error<'a> { - #[display("expected an identifier, but reached end of path string")] + #[error("expected an identifier, but reached end of path string")] NoIdent, - #[display("expected an identifier, got '{_0}' instead")] - #[error(ignore)] - #[from(ignore)] + #[error("expected an identifier, got '{0}' instead")] ExpectedIdent(Token<'a>), - #[display("failed to parse index as integer")] - InvalidIndex(ParseIntError), + #[error("failed to parse index as integer")] + InvalidIndex(#[from] ParseIntError), - #[display("a '[' wasn't closed, reached end of path string before finding a ']'")] + #[error("a '[' wasn't closed, reached end of path string before finding a ']'")] Unclosed, - #[display("a '[' wasn't closed properly, got '{_0}' instead")] - #[error(ignore)] - #[from(ignore)] + #[error("a '[' wasn't closed properly, got '{0}' instead")] BadClose(Token<'a>), - #[display("a ']' was found before an opening '['")] + #[error("a ']' was found before an opening '['")] CloseBeforeOpen, } diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 7ed380c98c..f3642d66b3 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -9,39 +9,39 @@ use core::{ fmt::Debug, }; -use derive_more::derive::{Display, Error}; +use thiserror::Error; use crate::utility::NonGenericTypeInfoCell; /// A enumeration of all error outcomes that might happen when running [`try_apply`](PartialReflect::try_apply). -#[derive(Error, Display, Debug)] +#[derive(Error, Debug)] pub enum ApplyError { - #[display("attempted to apply `{from_kind}` to `{to_kind}`")] + #[error("attempted to apply `{from_kind}` to `{to_kind}`")] /// Attempted to apply the wrong [kind](ReflectKind) to a type, e.g. a struct to a enum. MismatchedKinds { from_kind: ReflectKind, to_kind: ReflectKind, }, - #[display("enum variant `{variant_name}` doesn't have a field named `{field_name}`")] + #[error("enum variant `{variant_name}` doesn't have a field named `{field_name}`")] /// Enum variant that we tried to apply to was missing a field. MissingEnumField { variant_name: Box, field_name: Box, }, - #[display("`{from_type}` is not `{to_type}`")] + #[error("`{from_type}` is not `{to_type}`")] /// Tried to apply incompatible types. MismatchedTypes { from_type: Box, to_type: Box, }, - #[display("attempted to apply type with {from_size} size to a type with {to_size} size")] + #[error("attempted to apply type with {from_size} size to a type with {to_size} size")] /// Attempted to apply to types with mismatched sizez, e.g. a [u8; 4] to [u8; 3]. DifferentSize { from_size: usize, to_size: usize }, - #[display("variant with name `{variant_name}` does not exist on enum `{enum_name}`")] + #[error("variant with name `{variant_name}` does not exist on enum `{enum_name}`")] /// The enum we tried to apply to didn't contain a variant with the give name. UnknownVariant { enum_name: Box, diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index d396a6ba92..4ccac40508 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -8,7 +8,7 @@ use core::{ fmt::{Debug, Formatter}, hash::Hash, }; -use derive_more::derive::{Display, Error}; +use thiserror::Error; /// A static accessor to compile-time type information. /// @@ -163,12 +163,12 @@ impl DynamicTyped for T { } /// A [`TypeInfo`]-specific error. -#[derive(Debug, Error, Display)] +#[derive(Debug, Error)] pub enum TypeInfoError { /// Caused when a type was expected to be of a certain [kind], but was not. /// /// [kind]: ReflectKind - #[display("kind mismatch: expected {expected:?}, received {received:?}")] + #[error("kind mismatch: expected {expected:?}, received {received:?}")] KindMismatch { expected: ReflectKind, received: ReflectKind, diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index 9559942d1e..01031e983b 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -79,11 +79,8 @@ naga = { version = "23", features = ["wgsl-in"] } serde = { version = "1", features = ["derive"] } bytemuck = { version = "1.5", features = ["derive", "must_cast"] } downcast-rs = "1.2.0" -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } +derive_more = { version = "1", default-features = false, features = ["from"] } futures-lite = "2.0.1" ktx2 = { version = "0.3.0", optional = true } encase = { version = "0.10", features = ["glam"] } diff --git a/crates/bevy_render/src/render_asset.rs b/crates/bevy_render/src/render_asset.rs index 5a970056cf..047c2604b2 100644 --- a/crates/bevy_render/src/render_asset.rs +++ b/crates/bevy_render/src/render_asset.rs @@ -16,13 +16,13 @@ use bevy_utils::{ HashMap, HashSet, }; use core::marker::PhantomData; -use derive_more::derive::{Display, Error}; +use thiserror::Error; -#[derive(Debug, Error, Display)] +#[derive(Debug, Error)] pub enum PrepareAssetError { - #[display("Failed to prepare asset")] + #[error("Failed to prepare asset")] RetryNextUpdate(E), - #[display("Failed to build bind group: {_0}")] + #[error("Failed to build bind group: {0}")] AsBindGroupError(AsBindGroupError), } diff --git a/crates/bevy_render/src/render_graph/context.rs b/crates/bevy_render/src/render_graph/context.rs index 4a99dc07b5..c27f269d0b 100644 --- a/crates/bevy_render/src/render_graph/context.rs +++ b/crates/bevy_render/src/render_graph/context.rs @@ -4,7 +4,7 @@ use crate::{ }; use alloc::borrow::Cow; use bevy_ecs::entity::Entity; -use derive_more::derive::{Display, Error}; +use thiserror::Error; use super::{InternedRenderSubGraph, RenderSubGraph}; @@ -231,21 +231,19 @@ impl<'a> RenderGraphContext<'a> { } } -#[derive(Error, Display, Debug, Eq, PartialEq)] +#[derive(Error, Debug, Eq, PartialEq)] pub enum RunSubGraphError { - #[display("attempted to run sub-graph `{_0:?}`, but it does not exist")] - #[error(ignore)] + #[error("attempted to run sub-graph `{0:?}`, but it does not exist")] MissingSubGraph(InternedRenderSubGraph), - #[display("attempted to pass inputs to sub-graph `{_0:?}`, which has no input slots")] - #[error(ignore)] + #[error("attempted to pass inputs to sub-graph `{0:?}`, which has no input slots")] SubGraphHasNoInputs(InternedRenderSubGraph), - #[display("sub graph (name: `{graph_name:?}`) could not be run because slot `{slot_name}` at index {slot_index} has no value")] + #[error("sub graph (name: `{graph_name:?}`) could not be run because slot `{slot_name}` at index {slot_index} has no value")] MissingInput { slot_index: usize, slot_name: Cow<'static, str>, graph_name: InternedRenderSubGraph, }, - #[display("attempted to use the wrong type for input slot")] + #[error("attempted to use the wrong type for input slot")] MismatchedInputSlotType { graph_name: InternedRenderSubGraph, slot_index: usize, @@ -255,12 +253,11 @@ pub enum RunSubGraphError { }, } -#[derive(Error, Display, Debug, Eq, PartialEq)] +#[derive(Error, Debug, Eq, PartialEq)] pub enum OutputSlotError { - #[display("output slot `{_0:?}` does not exist")] - #[error(ignore)] + #[error("output slot `{0:?}` does not exist")] InvalidSlot(SlotLabel), - #[display("attempted to output a value of type `{actual}` to output slot `{label:?}`, which has type `{expected}`")] + #[error("attempted to output a value of type `{actual}` to output slot `{label:?}`, which has type `{expected}`")] MismatchedSlotType { label: SlotLabel, expected: SlotType, @@ -268,12 +265,11 @@ pub enum OutputSlotError { }, } -#[derive(Error, Display, Debug, Eq, PartialEq)] +#[derive(Error, Debug, Eq, PartialEq)] pub enum InputSlotError { - #[display("input slot `{_0:?}` does not exist")] - #[error(ignore)] + #[error("input slot `{0:?}` does not exist")] InvalidSlot(SlotLabel), - #[display("attempted to retrieve a value of type `{actual}` from input slot `{label:?}`, which has type `{expected}`")] + #[error("attempted to retrieve a value of type `{actual}` from input slot `{label:?}`, which has type `{expected}`")] MismatchedSlotType { label: SlotLabel, expected: SlotType, diff --git a/crates/bevy_render/src/render_graph/mod.rs b/crates/bevy_render/src/render_graph/mod.rs index 4769e1dc14..fbed33a23c 100644 --- a/crates/bevy_render/src/render_graph/mod.rs +++ b/crates/bevy_render/src/render_graph/mod.rs @@ -12,45 +12,40 @@ pub use graph::*; pub use node::*; pub use node_slot::*; -use derive_more::derive::{Display, Error}; +use thiserror::Error; -#[derive(Error, Display, Debug, Eq, PartialEq)] +#[derive(Error, Debug, Eq, PartialEq)] pub enum RenderGraphError { - #[display("node {_0:?} does not exist")] - #[error(ignore)] + #[error("node {0:?} does not exist")] InvalidNode(InternedRenderLabel), - #[display("output node slot does not exist")] - #[error(ignore)] + #[error("output node slot does not exist")] InvalidOutputNodeSlot(SlotLabel), - #[display("input node slot does not exist")] - #[error(ignore)] + #[error("input node slot does not exist")] InvalidInputNodeSlot(SlotLabel), - #[display("node does not match the given type")] + #[error("node does not match the given type")] WrongNodeType, - #[display("attempted to connect output slot {output_slot} from node {output_node:?} to incompatible input slot {input_slot} from node {input_node:?}")] + #[error("attempted to connect output slot {output_slot} from node {output_node:?} to incompatible input slot {input_slot} from node {input_node:?}")] MismatchedNodeSlots { output_node: InternedRenderLabel, output_slot: usize, input_node: InternedRenderLabel, input_slot: usize, }, - #[display("attempted to add an edge that already exists")] - #[error(ignore)] + #[error("attempted to add an edge that already exists")] EdgeAlreadyExists(Edge), - #[display("attempted to remove an edge that does not exist")] - #[error(ignore)] + #[error("attempted to remove an edge that does not exist")] EdgeDoesNotExist(Edge), - #[display("node {node:?} has an unconnected input slot {input_slot}")] + #[error("node {node:?} has an unconnected input slot {input_slot}")] UnconnectedNodeInputSlot { node: InternedRenderLabel, input_slot: usize, }, - #[display("node {node:?} has an unconnected output slot {output_slot}")] + #[error("node {node:?} has an unconnected output slot {output_slot}")] UnconnectedNodeOutputSlot { node: InternedRenderLabel, output_slot: usize, }, - #[display("node {node:?} input slot {input_slot} already occupied by {occupied_by_node:?}")] + #[error("node {node:?} input slot {input_slot} already occupied by {occupied_by_node:?}")] NodeInputSlotAlreadyOccupied { node: InternedRenderLabel, input_slot: usize, diff --git a/crates/bevy_render/src/render_graph/node.rs b/crates/bevy_render/src/render_graph/node.rs index c9ec725ff7..91775fef7c 100644 --- a/crates/bevy_render/src/render_graph/node.rs +++ b/crates/bevy_render/src/render_graph/node.rs @@ -14,8 +14,8 @@ use bevy_ecs::{ world::{FromWorld, World}, }; use core::fmt::Debug; -use derive_more::derive::{Display, Error, From}; use downcast_rs::{impl_downcast, Downcast}; +use thiserror::Error; use variadics_please::all_tuples_with_size; pub use bevy_render_macros::RenderLabel; @@ -98,16 +98,16 @@ pub trait Node: Downcast + Send + Sync + 'static { impl_downcast!(Node); -#[derive(Error, Display, Debug, Eq, PartialEq, From)] +#[derive(Error, Debug, Eq, PartialEq)] pub enum NodeRunError { - #[display("encountered an input slot error")] - InputSlotError(InputSlotError), - #[display("encountered an output slot error")] - OutputSlotError(OutputSlotError), - #[display("encountered an error when running a sub-graph")] - RunSubGraphError(RunSubGraphError), - #[display("encountered an error when executing draw command")] - DrawError(DrawError), + #[error("encountered an input slot error")] + InputSlotError(#[from] InputSlotError), + #[error("encountered an output slot error")] + OutputSlotError(#[from] OutputSlotError), + #[error("encountered an error when running a sub-graph")] + RunSubGraphError(#[from] RunSubGraphError), + #[error("encountered an error when executing draw command")] + DrawError(#[from] DrawError), } /// A collection of input and output [`Edges`](Edge) for a [`Node`]. diff --git a/crates/bevy_render/src/render_phase/draw.rs b/crates/bevy_render/src/render_phase/draw.rs index a03ae0a0c6..8b197025e0 100644 --- a/crates/bevy_render/src/render_phase/draw.rs +++ b/crates/bevy_render/src/render_phase/draw.rs @@ -8,8 +8,8 @@ use bevy_ecs::{ }; use bevy_utils::TypeIdMap; use core::{any::TypeId, fmt::Debug, hash::Hash}; -use derive_more::derive::{Display, Error}; use std::sync::{PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard}; +use thiserror::Error; use variadics_please::all_tuples; /// A draw function used to draw [`PhaseItem`]s. @@ -35,14 +35,13 @@ pub trait Draw: Send + Sync + 'static { ) -> Result<(), DrawError>; } -#[derive(Error, Display, Debug, PartialEq, Eq)] +#[derive(Error, Debug, PartialEq, Eq)] pub enum DrawError { - #[display("Failed to execute render command {_0:?}")] - #[error(ignore)] + #[error("Failed to execute render command {0:?}")] RenderCommandFailure(&'static str), - #[display("Failed to get execute view query")] + #[error("Failed to get execute view query")] InvalidViewQuery, - #[display("View entity not found")] + #[error("View entity not found")] ViewEntityNotFound, } diff --git a/crates/bevy_render/src/render_resource/bind_group.rs b/crates/bevy_render/src/render_resource/bind_group.rs index 290923b62d..99f1812319 100644 --- a/crates/bevy_render/src/render_resource/bind_group.rs +++ b/crates/bevy_render/src/render_resource/bind_group.rs @@ -11,8 +11,8 @@ use bevy_derive::{Deref, DerefMut}; use bevy_ecs::system::{SystemParam, SystemParamItem}; pub use bevy_render_macros::AsBindGroup; use core::ops::Deref; -use derive_more::derive::{Display, Error}; use encase::ShaderType; +use thiserror::Error; use wgpu::{BindGroupEntry, BindGroupLayoutEntry, BindingResource, TextureViewDimension}; define_atomic_id!(BindGroupId); @@ -401,14 +401,14 @@ pub trait AsBindGroup { } /// An error that occurs during [`AsBindGroup::as_bind_group`] calls. -#[derive(Debug, Error, Display)] +#[derive(Debug, Error)] pub enum AsBindGroupError { /// The bind group could not be generated. Try again next frame. - #[display("The bind group could not be generated")] + #[error("The bind group could not be generated")] RetryNextUpdate, - #[display("Create the bind group via `as_bind_group()` instead")] + #[error("Create the bind group via `as_bind_group()` instead")] CreateBindGroupDirectly, - #[display("At binding index {_0}, the provided image sampler `{_1}` does not match the required sampler type(s) `{_2}`.")] + #[error("At binding index {0}, the provided image sampler `{1}` does not match the required sampler type(s) `{2}`.")] InvalidSamplerType(u32, String, String), } diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index 5396b720e3..0e041968de 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -18,9 +18,9 @@ use bevy_utils::{ HashMap, HashSet, }; use core::{future::Future, hash::Hash, mem, ops::Deref}; -use derive_more::derive::{Display, Error, From}; use naga::valid::Capabilities; use std::sync::{Mutex, PoisonError}; +use thiserror::Error; #[cfg(feature = "shader_format_spirv")] use wgpu::util::make_spirv; use wgpu::{ @@ -974,19 +974,17 @@ fn create_pipeline_task( } /// Type of error returned by a [`PipelineCache`] when the creation of a GPU pipeline object failed. -#[derive(Error, Display, Debug, From)] +#[derive(Error, Debug)] pub enum PipelineCacheError { - #[display( - "Pipeline could not be compiled because the following shader could not be loaded: {_0:?}" + #[error( + "Pipeline could not be compiled because the following shader could not be loaded: {0:?}" )] - #[error(ignore)] ShaderNotLoaded(AssetId), - - ProcessShaderError(naga_oil::compose::ComposerError), - #[display("Shader import not yet available.")] + #[error(transparent)] + ProcessShaderError(#[from] naga_oil::compose::ComposerError), + #[error("Shader import not yet available.")] ShaderImportNotYetAvailable, - #[display("Could not create shader module: {_0}")] - #[error(ignore)] + #[error("Could not create shader module: {0}")] CreateShaderModule(String), } diff --git a/crates/bevy_render/src/render_resource/pipeline_specializer.rs b/crates/bevy_render/src/render_resource/pipeline_specializer.rs index 7656fd57d6..55c13b3ab1 100644 --- a/crates/bevy_render/src/render_resource/pipeline_specializer.rs +++ b/crates/bevy_render/src/render_resource/pipeline_specializer.rs @@ -13,7 +13,7 @@ use bevy_utils::{ Entry, HashMap, }; use core::{fmt::Debug, hash::Hash}; -use derive_more::derive::{Display, Error, From}; +use thiserror::Error; pub trait SpecializedRenderPipeline { type Key: Clone + Hash + PartialEq + Eq; @@ -183,7 +183,8 @@ impl SpecializedMeshPipelines { } } -#[derive(Error, Display, Debug, From)] +#[derive(Error, Debug)] pub enum SpecializedMeshPipelineError { - MissingVertexAttribute(MissingVertexAttributeError), + #[error(transparent)] + MissingVertexAttribute(#[from] MissingVertexAttributeError), } diff --git a/crates/bevy_render/src/render_resource/shader.rs b/crates/bevy_render/src/render_resource/shader.rs index 3c271541e4..36f71ed3bf 100644 --- a/crates/bevy_render/src/render_resource/shader.rs +++ b/crates/bevy_render/src/render_resource/shader.rs @@ -4,20 +4,22 @@ use alloc::borrow::Cow; use bevy_asset::{io::Reader, Asset, AssetLoader, AssetPath, Handle, LoadContext}; use bevy_reflect::TypePath; use core::marker::Copy; -use derive_more::derive::{Display, Error, From}; +use thiserror::Error; define_atomic_id!(ShaderId); -#[derive(Error, Display, Debug, From)] +#[derive(Error, Debug)] pub enum ShaderReflectError { - WgslParse(naga::front::wgsl::ParseError), + #[error(transparent)] + WgslParse(#[from] naga::front::wgsl::ParseError), #[cfg(feature = "shader_format_glsl")] - #[display("GLSL Parse Error: {_0:?}")] - #[error(ignore)] + #[error("GLSL Parse Error: {0:?}")] GlslParse(Vec), #[cfg(feature = "shader_format_spirv")] - SpirVParse(naga::front::spv::Error), - Validation(naga::WithSpan), + #[error(transparent)] + SpirVParse(#[from] naga::front::spv::Error), + #[error(transparent)] + Validation(#[from] naga::WithSpan), } /// A shader, as defined by its [`ShaderSource`](wgpu::ShaderSource) and [`ShaderStage`](naga::ShaderStage) /// This is an "unprocessed" shader. It can contain preprocessor directives. @@ -244,12 +246,12 @@ impl From<&Source> for naga_oil::compose::ShaderType { pub struct ShaderLoader; #[non_exhaustive] -#[derive(Debug, Error, Display, From)] +#[derive(Debug, Error)] pub enum ShaderLoaderError { - #[display("Could not load shader: {_0}")] - Io(std::io::Error), - #[display("Could not parse shader: {_0}")] - Parse(alloc::string::FromUtf8Error), + #[error("Could not load shader: {0}")] + Io(#[from] std::io::Error), + #[error("Could not parse shader: {0}")] + Parse(#[from] alloc::string::FromUtf8Error), } impl AssetLoader for ShaderLoader { diff --git a/crates/bevy_render/src/renderer/graph_runner.rs b/crates/bevy_render/src/renderer/graph_runner.rs index f2e90d33ea..15b3240638 100644 --- a/crates/bevy_render/src/renderer/graph_runner.rs +++ b/crates/bevy_render/src/renderer/graph_runner.rs @@ -4,8 +4,8 @@ use bevy_utils::tracing::info_span; use bevy_utils::HashMap; use alloc::{borrow::Cow, collections::VecDeque}; -use derive_more::derive::{Display, Error, From}; use smallvec::{smallvec, SmallVec}; +use thiserror::Error; use crate::{ diagnostic::internal::{DiagnosticsRecorder, RenderDiagnosticsMutex}, @@ -29,29 +29,30 @@ use crate::{ /// [`CommandBuffer`]: wgpu::CommandBuffer pub(crate) struct RenderGraphRunner; -#[derive(Error, Display, Debug, From)] +#[derive(Error, Debug)] pub enum RenderGraphRunnerError { - NodeRunError(NodeRunError), - #[display("node output slot not set (index {slot_index}, name {slot_name})")] + #[error(transparent)] + NodeRunError(#[from] NodeRunError), + #[error("node output slot not set (index {slot_index}, name {slot_name})")] EmptyNodeOutputSlot { type_name: &'static str, slot_index: usize, slot_name: Cow<'static, str>, }, - #[display("graph '{sub_graph:?}' could not be run because slot '{slot_name}' at index {slot_index} has no value")] + #[error("graph '{sub_graph:?}' could not be run because slot '{slot_name}' at index {slot_index} has no value")] MissingInput { slot_index: usize, slot_name: Cow<'static, str>, sub_graph: Option, }, - #[display("attempted to use the wrong type for input slot")] + #[error("attempted to use the wrong type for input slot")] MismatchedInputSlotType { slot_index: usize, label: SlotLabel, expected: SlotType, actual: SlotType, }, - #[display( + #[error( "node (name: '{node_name:?}') has {slot_count} input slots, but was provided {value_count} values" )] MismatchedInputCount { diff --git a/crates/bevy_scene/Cargo.toml b/crates/bevy_scene/Cargo.toml index 9ad5df7339..91eecb563b 100644 --- a/crates/bevy_scene/Cargo.toml +++ b/crates/bevy_scene/Cargo.toml @@ -29,11 +29,8 @@ bevy_render = { path = "../bevy_render", version = "0.15.0-dev", optional = true # other serde = { version = "1.0", features = ["derive"], optional = true } uuid = { version = "1.1", features = ["v4"] } -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } +derive_more = { version = "1", default-features = false, features = ["from"] } [dev-dependencies] postcard = { version = "1.0", features = ["alloc"] } diff --git a/crates/bevy_scene/src/scene_loader.rs b/crates/bevy_scene/src/scene_loader.rs index 643ad7a516..481b7ebc04 100644 --- a/crates/bevy_scene/src/scene_loader.rs +++ b/crates/bevy_scene/src/scene_loader.rs @@ -7,9 +7,9 @@ use bevy_ecs::{ world::{FromWorld, World}, }; use bevy_reflect::TypeRegistryArc; -use derive_more::derive::{Display, Error, From}; #[cfg(feature = "serialize")] use serde::de::DeserializeSeed; +use thiserror::Error; /// Asset loader for a Bevy dynamic scene (`.scn` / `.scn.ron`). /// @@ -30,14 +30,14 @@ impl FromWorld for SceneLoader { /// Possible errors that can be produced by [`SceneLoader`] #[non_exhaustive] -#[derive(Debug, Error, Display, From)] +#[derive(Debug, Error)] pub enum SceneLoaderError { /// An [IO Error](std::io::Error) - #[display("Error while trying to read the scene file: {_0}")] - Io(std::io::Error), + #[error("Error while trying to read the scene file: {0}")] + Io(#[from] std::io::Error), /// A [RON Error](ron::error::SpannedError) - #[display("Could not parse RON: {_0}")] - RonSpannedError(ron::error::SpannedError), + #[error("Could not parse RON: {0}")] + RonSpannedError(#[from] ron::error::SpannedError), } #[cfg(feature = "serialize")] diff --git a/crates/bevy_scene/src/scene_spawner.rs b/crates/bevy_scene/src/scene_spawner.rs index 910d83fafb..74e4918c22 100644 --- a/crates/bevy_scene/src/scene_spawner.rs +++ b/crates/bevy_scene/src/scene_spawner.rs @@ -10,7 +10,7 @@ use bevy_ecs::{ use bevy_hierarchy::{AddChild, BuildChildren, DespawnRecursiveExt, Parent}; use bevy_reflect::Reflect; use bevy_utils::{HashMap, HashSet}; -use derive_more::derive::{Display, Error}; +use thiserror::Error; use uuid::Uuid; /// Triggered on a scene's parent entity when [`crate::SceneInstance`] becomes ready to use. @@ -75,22 +75,22 @@ pub struct SceneSpawner { } /// Errors that can occur when spawning a scene. -#[derive(Error, Display, Debug)] +#[derive(Error, Debug)] pub enum SceneSpawnError { /// Scene contains an unregistered component type. - #[display("scene contains the unregistered component `{type_path}`. consider adding `#[reflect(Component)]` to your type")] + #[error("scene contains the unregistered component `{type_path}`. consider adding `#[reflect(Component)]` to your type")] UnregisteredComponent { /// Type of the unregistered component. type_path: String, }, /// Scene contains an unregistered resource type. - #[display("scene contains the unregistered resource `{type_path}`. consider adding `#[reflect(Resource)]` to your type")] + #[error("scene contains the unregistered resource `{type_path}`. consider adding `#[reflect(Resource)]` to your type")] UnregisteredResource { /// Type of the unregistered resource. type_path: String, }, /// Scene contains an unregistered type. - #[display( + #[error( "scene contains the unregistered type `{std_type_name}`. \ consider reflecting it with `#[derive(Reflect)]` \ and registering the type using `app.register_type::()`" @@ -100,7 +100,7 @@ pub enum SceneSpawnError { std_type_name: String, }, /// Scene contains an unregistered type which has a `TypePath`. - #[display( + #[error( "scene contains the reflected type `{type_path}` but it was not found in the type registry. \ consider registering the type using `app.register_type::()``" )] @@ -109,19 +109,19 @@ pub enum SceneSpawnError { type_path: String, }, /// Scene contains a proxy without a represented type. - #[display("scene contains dynamic type `{type_path}` without a represented type. consider changing this using `set_represented_type`.")] + #[error("scene contains dynamic type `{type_path}` without a represented type. consider changing this using `set_represented_type`.")] NoRepresentedType { /// The dynamic instance type. type_path: String, }, /// Dynamic scene with the given id does not exist. - #[display("scene does not exist")] + #[error("scene does not exist")] NonExistentScene { /// Id of the non-existent dynamic scene. id: AssetId, }, /// Scene with the given id does not exist. - #[display("scene does not exist")] + #[error("scene does not exist")] NonExistentRealScene { /// Id of the non-existent scene. id: AssetId, diff --git a/crates/bevy_sprite/Cargo.toml b/crates/bevy_sprite/Cargo.toml index 9bbf629ec5..8800f6cb6e 100644 --- a/crates/bevy_sprite/Cargo.toml +++ b/crates/bevy_sprite/Cargo.toml @@ -37,11 +37,8 @@ bevy_derive = { path = "../bevy_derive", version = "0.15.0-dev" } bytemuck = { version = "1", features = ["derive", "must_cast"] } fixedbitset = "0.5" guillotiere = "0.6.0" -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } +derive_more = { version = "1", default-features = false, features = ["from"] } rectangle-pack = "0.4" bitflags = "2.3" radsort = "0.1" diff --git a/crates/bevy_sprite/src/texture_atlas_builder.rs b/crates/bevy_sprite/src/texture_atlas_builder.rs index b59c9423b9..92d62b619d 100644 --- a/crates/bevy_sprite/src/texture_atlas_builder.rs +++ b/crates/bevy_sprite/src/texture_atlas_builder.rs @@ -9,19 +9,19 @@ use bevy_utils::{ tracing::{debug, error, warn}, HashMap, }; -use derive_more::derive::{Display, Error}; use rectangle_pack::{ contains_smallest_box, pack_rects, volume_heuristic, GroupedRectsToPlace, PackedLocation, RectToInsert, TargetBin, }; +use thiserror::Error; use crate::{TextureAtlasLayout, TextureAtlasSources}; -#[derive(Debug, Error, Display)] +#[derive(Debug, Error)] pub enum TextureAtlasBuilderError { - #[display("could not pack textures into an atlas within the given bounds")] + #[error("could not pack textures into an atlas within the given bounds")] NotEnoughSpace, - #[display("added a texture with the wrong format in an atlas")] + #[error("added a texture with the wrong format in an atlas")] WrongFormat, } diff --git a/crates/bevy_text/Cargo.toml b/crates/bevy_text/Cargo.toml index 479ebed5f4..80f89a6e5d 100644 --- a/crates/bevy_text/Cargo.toml +++ b/crates/bevy_text/Cargo.toml @@ -32,11 +32,7 @@ bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev" } # other cosmic-text = { version = "0.12", features = ["shape-run-cache"] } -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } serde = { version = "1", features = ["derive"] } smallvec = "1.13" unicode-bidi = "0.3.13" diff --git a/crates/bevy_text/src/error.rs b/crates/bevy_text/src/error.rs index cd4d884d45..ef9f7ea590 100644 --- a/crates/bevy_text/src/error.rs +++ b/crates/bevy_text/src/error.rs @@ -1,19 +1,17 @@ use cosmic_text::CacheKey; -use derive_more::derive::{Display, Error}; +use thiserror::Error; -#[derive(Debug, PartialEq, Eq, Error, Display)] +#[derive(Debug, PartialEq, Eq, Error)] /// Errors related to the textsystem pub enum TextError { /// Font was not found, this could be that the font has not yet been loaded, or /// that the font failed to load for some other reason - #[display("font not found")] + #[error("font not found")] NoSuchFont, /// Failed to add glyph to a newly created atlas for some reason - #[display("failed to add glyph to newly-created atlas {_0:?}")] - #[error(ignore)] + #[error("failed to add glyph to newly-created atlas {0:?}")] FailedToAddGlyph(u16), /// Failed to get scaled glyph image for cache key - #[display("failed to get scaled glyph image for cache key: {_0:?}")] - #[error(ignore)] + #[error("failed to get scaled glyph image for cache key: {0:?}")] FailedToGetGlyphImage(CacheKey), } diff --git a/crates/bevy_text/src/font_loader.rs b/crates/bevy_text/src/font_loader.rs index fb491f49c2..9e0f2185a2 100644 --- a/crates/bevy_text/src/font_loader.rs +++ b/crates/bevy_text/src/font_loader.rs @@ -1,6 +1,6 @@ use crate::Font; use bevy_asset::{io::Reader, AssetLoader, LoadContext}; -use derive_more::derive::{Display, Error, From}; +use thiserror::Error; #[derive(Default)] /// An [`AssetLoader`] for [`Font`]s, for use by the [`AssetServer`](bevy_asset::AssetServer) @@ -8,12 +8,14 @@ pub struct FontLoader; /// Possible errors that can be produced by [`FontLoader`] #[non_exhaustive] -#[derive(Debug, Error, Display, From)] +#[derive(Debug, Error)] pub enum FontLoaderError { /// The contents that could not be parsed - Content(cosmic_text::ttf_parser::FaceParsingError), + #[error(transparent)] + Content(#[from] cosmic_text::ttf_parser::FaceParsingError), /// An [IO](std::io) Error - Io(std::io::Error), + #[error(transparent)] + Io(#[from] std::io::Error), } impl AssetLoader for FontLoader { diff --git a/crates/bevy_transform/Cargo.toml b/crates/bevy_transform/Cargo.toml index c0ff738f32..fdc02f2386 100644 --- a/crates/bevy_transform/Cargo.toml +++ b/crates/bevy_transform/Cargo.toml @@ -20,11 +20,8 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", features = [ "bevy", ], optional = true } serde = { version = "1", features = ["derive"], optional = true } -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } +derive_more = { version = "1", default-features = false, features = ["from"] } [dev-dependencies] bevy_tasks = { path = "../bevy_tasks", version = "0.15.0-dev" } diff --git a/crates/bevy_transform/src/helper.rs b/crates/bevy_transform/src/helper.rs index 0ecbea9c94..1ae3ca9616 100644 --- a/crates/bevy_transform/src/helper.rs +++ b/crates/bevy_transform/src/helper.rs @@ -6,7 +6,7 @@ use bevy_ecs::{ system::{Query, SystemParam}, }; use bevy_hierarchy::{HierarchyQueryExt, Parent}; -use derive_more::derive::{Display, Error}; +use thiserror::Error; use crate::components::{GlobalTransform, Transform}; @@ -64,20 +64,17 @@ fn map_error(err: QueryEntityError, ancestor: bool) -> ComputeGlobalTransformErr } /// Error returned by [`TransformHelper::compute_global_transform`]. -#[derive(Debug, Error, Display)] +#[derive(Debug, Error)] pub enum ComputeGlobalTransformError { /// The entity or one of its ancestors is missing the [`Transform`] component. - #[display("The entity {_0:?} or one of its ancestors is missing the `Transform` component")] - #[error(ignore)] + #[error("The entity {0:?} or one of its ancestors is missing the `Transform` component")] MissingTransform(Entity), /// The entity does not exist. - #[display("The entity {_0:?} does not exist")] - #[error(ignore)] + #[error("The entity {0:?} does not exist")] NoSuchEntity(Entity), /// An ancestor is missing. /// This probably means that your hierarchy has been improperly maintained. - #[display("The ancestor {_0:?} is missing")] - #[error(ignore)] + #[error("The ancestor {0:?} is missing")] MalformedHierarchy(Entity), } diff --git a/crates/bevy_ui/Cargo.toml b/crates/bevy_ui/Cargo.toml index 321388d63b..70478d8fe7 100644 --- a/crates/bevy_ui/Cargo.toml +++ b/crates/bevy_ui/Cargo.toml @@ -36,11 +36,8 @@ bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev" } taffy = { version = "0.6" } serde = { version = "1", features = ["derive"], optional = true } bytemuck = { version = "1.5", features = ["derive"] } -derive_more = { version = "1", default-features = false, features = [ - "error", - "from", - "display", -] } +thiserror = { version = "2", default-features = false } +derive_more = { version = "1", default-features = false, features = ["from"] } nonmax = "0.5" smallvec = "1.11" accesskit = "0.17" diff --git a/crates/bevy_ui/src/geometry.rs b/crates/bevy_ui/src/geometry.rs index 391085d0dc..3f2d970afd 100644 --- a/crates/bevy_ui/src/geometry.rs +++ b/crates/bevy_ui/src/geometry.rs @@ -1,7 +1,7 @@ use bevy_math::Vec2; use bevy_reflect::{std_traits::ReflectDefault, Reflect}; use core::ops::{Div, DivAssign, Mul, MulAssign, Neg}; -use derive_more::derive::{Display, Error}; +use thiserror::Error; #[cfg(feature = "serialize")] use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; @@ -174,11 +174,11 @@ impl Neg for Val { } } -#[derive(Debug, Eq, PartialEq, Clone, Copy, Error, Display)] +#[derive(Debug, Eq, PartialEq, Clone, Copy, Error)] pub enum ValArithmeticError { - #[display("the variants of the Vals don't match")] + #[error("the variants of the Vals don't match")] NonIdenticalVariants, - #[display("the given variant of Val is not evaluateable (non-numeric)")] + #[error("the given variant of Val is not evaluateable (non-numeric)")] NonEvaluateable, } diff --git a/crates/bevy_ui/src/layout/mod.rs b/crates/bevy_ui/src/layout/mod.rs index 90a3250328..15e1505985 100644 --- a/crates/bevy_ui/src/layout/mod.rs +++ b/crates/bevy_ui/src/layout/mod.rs @@ -19,7 +19,7 @@ use bevy_sprite::BorderRect; use bevy_transform::components::Transform; use bevy_utils::tracing::warn; use bevy_window::{PrimaryWindow, Window, WindowScaleFactorChanged}; -use derive_more::derive::{Display, Error, From}; +use thiserror::Error; use ui_surface::UiSurface; use bevy_text::ComputedTextBlock; @@ -63,11 +63,11 @@ impl Default for LayoutContext { } } -#[derive(Debug, Error, Display, From)] +#[derive(Debug, Error)] pub enum LayoutError { - #[display("Invalid hierarchy")] + #[error("Invalid hierarchy")] InvalidHierarchy, - #[display("Taffy error: {_0}")] + #[error("Taffy error: {0}")] TaffyError(taffy::TaffyError), } diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index 4bdd35192f..34848c7f6b 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -13,8 +13,9 @@ use bevy_transform::components::Transform; use bevy_utils::warn_once; use bevy_window::{PrimaryWindow, WindowRef}; use core::num::NonZero; -use derive_more::derive::{Display, Error, From}; +use derive_more::derive::From; use smallvec::SmallVec; +use thiserror::Error; /// Provides the computed size and layout properties of the node. #[derive(Component, Debug, Copy, Clone, PartialEq, Reflect)] @@ -1944,11 +1945,11 @@ fn try_into_grid_span(span: u16) -> Result>, GridPlacementEr } /// Errors that occur when setting constraints for a `GridPlacement` -#[derive(Debug, Eq, PartialEq, Clone, Copy, Error, Display)] +#[derive(Debug, Eq, PartialEq, Clone, Copy, Error)] pub enum GridPlacementError { - #[display("Zero is not a valid grid position")] + #[error("Zero is not a valid grid position")] InvalidZeroIndex, - #[display("Spans cannot be zero length")] + #[error("Spans cannot be zero length")] InvalidZeroSpan, } diff --git a/deny.toml b/deny.toml index dda02ee289..859d9e5e3e 100644 --- a/deny.toml +++ b/deny.toml @@ -81,3 +81,8 @@ unknown-registry = "deny" unknown-git = "deny" allow-registry = ["https://github.com/rust-lang/crates.io-index"] allow-git = [] + +# thiserror is the preferred way to derive error types +[[bans.features]] +crate = "derive_more" +deny = ["error"]