Skip to content

Commit 77cb9da

Browse files
committed
Add on_unimplemented Diagnostics to Most Public Traits
1 parent bfc1338 commit 77cb9da

File tree

101 files changed

+500
-13
lines changed

Some content is hidden

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

101 files changed

+500
-13
lines changed

Cargo.toml

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

1515
[workspace]
1616
exclude = [

crates/bevy_animation/src/animatable.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ pub struct BlendInput<T> {
1616
}
1717

1818
/// An animatable value type.
19+
#[diagnostic::on_unimplemented(
20+
message = "`{Self}` can not be animated",
21+
label = "Invalid Animatable"
22+
)]
1923
pub trait Animatable: Reflect + Sized + Send + Sync + 'static {
2024
/// Interpolates between `a` and `b` with a interpolation factor of `time`.
2125
///

crates/bevy_app/src/plugin.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ use std::any::Any;
5454
/// }
5555
/// }
5656
/// # fn damp_flickering() {}
57-
/// ````
57+
/// ```
58+
#[diagnostic::on_unimplemented(message = "`{Self}` is not a plugin", label = "Invalid Plugin")]
5859
pub trait Plugin: Downcast + Any + Send + Sync {
5960
/// Configures the [`App`] to which this plugin is added.
6061
fn build(&self, app: &mut App);
@@ -130,6 +131,10 @@ pub type CreatePlugin = unsafe fn() -> *mut dyn Plugin;
130131
///
131132
/// This is implemented for all types which implement [`Plugin`],
132133
/// [`PluginGroup`](super::PluginGroup), and tuples over [`Plugins`].
134+
#[diagnostic::on_unimplemented(
135+
message = "`{Self}` is not a set of plugins",
136+
label = "Invalid Plugin Set"
137+
)]
133138
pub trait Plugins<Marker>: sealed::Plugins<Marker> {}
134139

135140
impl<Marker, T> Plugins<Marker> for T where T: sealed::Plugins<Marker> {}

crates/bevy_app/src/plugin_group.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ use bevy_utils::{tracing::debug, tracing::warn, TypeIdMap};
33
use std::any::TypeId;
44

55
/// Combines multiple [`Plugin`]s into a single unit.
6+
#[diagnostic::on_unimplemented(
7+
message = "`{Self}` is not a plugin group",
8+
label = "Invalid Plugin Group"
9+
)]
610
pub trait PluginGroup: Sized {
711
/// Configures the [`Plugin`]s that are to be added.
812
fn build(self) -> PluginGroupBuilder;

crates/bevy_asset/src/direct_access_ext.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use bevy_ecs::world::World;
55

66
use crate::{meta::Settings, Asset, AssetPath, AssetServer, Assets, Handle};
77

8+
#[diagnostic::on_unimplemented(message = "`{Self}` is not a World", label = "Invalid World")]
89
pub trait DirectAssetAccessExt {
910
/// Insert an asset similarly to [`Assets::add`].
1011
fn add_asset<A: Asset>(&mut self, asset: impl Into<A>) -> Handle<A>;

crates/bevy_asset/src/io/mod.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ impl From<std::io::Error> for AssetReaderError {
7272
}
7373
}
7474

75+
#[diagnostic::on_unimplemented(
76+
message = "`{Self}` is not an asynchronous and seekable reader",
77+
label = "Invalid Reader"
78+
)]
7579
pub trait AsyncReadAndSeek: AsyncRead + AsyncSeek {}
7680

7781
impl<T: AsyncRead + AsyncSeek> AsyncReadAndSeek for T {}
@@ -83,6 +87,10 @@ pub type Reader<'a> = dyn AsyncReadAndSeek + Unpin + Send + Sync + 'a;
8387
/// `path`. This trait is not object safe, if needed use a dyn [`ErasedAssetReader`] instead.
8488
///
8589
/// Also see [`AssetWriter`].
90+
#[diagnostic::on_unimplemented(
91+
message = "`{Self}` is not an asset reader",
92+
label = "Invalid Asset Reader"
93+
)]
8694
pub trait AssetReader: Send + Sync + 'static {
8795
/// Returns a future to load the full file data at the provided path.
8896
fn read<'a>(
@@ -121,6 +129,10 @@ pub trait AssetReader: Send + Sync + 'static {
121129

122130
/// Equivalent to an [`AssetReader`] but using boxed futures, necessary eg. when using a `dyn AssetReader`,
123131
/// as [`AssetReader`] isn't currently object safe.
132+
#[diagnostic::on_unimplemented(
133+
message = "`{Self}` is not an erasable asset reader",
134+
label = "Invalid Asset Reader"
135+
)]
124136
pub trait ErasedAssetReader: Send + Sync + 'static {
125137
/// Returns a future to load the full file data at the provided path.
126138
fn read<'a>(&'a self, path: &'a Path)
@@ -192,6 +204,10 @@ pub enum AssetWriterError {
192204
/// `path`. This trait is not object safe, if needed use a dyn [`ErasedAssetWriter`] instead.
193205
///
194206
/// Also see [`AssetReader`].
207+
#[diagnostic::on_unimplemented(
208+
message = "`{Self}` is not an asset writer",
209+
label = "Invalid Asset Writer"
210+
)]
195211
pub trait AssetWriter: Send + Sync + 'static {
196212
/// Writes the full asset bytes at the provided path.
197213
fn write<'a>(
@@ -274,6 +290,10 @@ pub trait AssetWriter: Send + Sync + 'static {
274290

275291
/// Equivalent to an [`AssetWriter`] but using boxed futures, necessary eg. when using a `dyn AssetWriter`,
276292
/// as [`AssetWriter`] isn't currently object safe.
293+
#[diagnostic::on_unimplemented(
294+
message = "`{Self}` is not an erasable asset writer",
295+
label = "Invalid Asset Writer"
296+
)]
277297
pub trait ErasedAssetWriter: Send + Sync + 'static {
278298
/// Writes the full asset bytes at the provided path.
279299
fn write<'a>(&'a self, path: &'a Path) -> BoxedFuture<Result<Box<Writer>, AssetWriterError>>;
@@ -429,6 +449,10 @@ pub enum AssetSourceEvent {
429449

430450
/// A handle to an "asset watcher" process, that will listen for and emit [`AssetSourceEvent`] values for as long as
431451
/// [`AssetWatcher`] has not been dropped.
452+
#[diagnostic::on_unimplemented(
453+
message = "`{Self}` is not an asset watcher",
454+
label = "Invalid Asset Watcher"
455+
)]
432456
pub trait AssetWatcher: Send + Sync + 'static {}
433457

434458
/// An [`AsyncRead`] implementation capable of reading a [`Vec<u8>`].

crates/bevy_asset/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,17 @@ impl Plugin for AssetPlugin {
223223
}
224224
}
225225

226+
#[diagnostic::on_unimplemented(
227+
message = "`{Self}` is not an asset",
228+
label = "Invalid Asset",
229+
note = "Try using `#[derive(Asset)]`"
230+
)]
226231
pub trait Asset: VisitAssetDependencies + TypePath + Send + Sync + 'static {}
227232

233+
#[diagnostic::on_unimplemented(
234+
message = "Can not visit dependencies on `{Self}`",
235+
label = "Invalid Asset"
236+
)]
228237
pub trait VisitAssetDependencies {
229238
fn visit_dependencies(&self, visit: &mut impl FnMut(UntypedAssetId));
230239
}
@@ -274,6 +283,7 @@ impl VisitAssetDependencies for Vec<UntypedHandle> {
274283
}
275284

276285
/// Adds asset-related builder methods to [`App`].
286+
#[diagnostic::on_unimplemented(message = "`{Self}` is not an App", label = "Invalid App")]
277287
pub trait AssetApp {
278288
/// Registers the given `loader` in the [`App`]'s [`AssetServer`].
279289
fn register_asset_loader<L: AssetLoader>(&mut self, loader: L) -> &mut Self;

crates/bevy_asset/src/loader.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ use thiserror::Error;
2222

2323
/// Loads an [`Asset`] from a given byte [`Reader`]. This can accept [`AssetLoader::Settings`], which configure how the [`Asset`]
2424
/// should be loaded.
25+
#[diagnostic::on_unimplemented(
26+
message = "`{Self}` is not an asset loader",
27+
label = "Invalid Asset Loader"
28+
)]
2529
pub trait AssetLoader: Send + Sync + 'static {
2630
/// The top level [`Asset`] loaded by this [`AssetLoader`].
2731
type Asset: crate::Asset;
@@ -45,6 +49,10 @@ pub trait AssetLoader: Send + Sync + 'static {
4549
}
4650

4751
/// Provides type-erased access to an [`AssetLoader`].
52+
#[diagnostic::on_unimplemented(
53+
message = "`{Self}` is not an erasable asset loader",
54+
label = "Invalid Asset Loader"
55+
)]
4856
pub trait ErasedAssetLoader: Send + Sync + 'static {
4957
/// Asynchronously loads the asset(s) from the bytes provided by [`Reader`].
5058
fn load<'a>(
@@ -231,6 +239,10 @@ impl ErasedLoadedAsset {
231239
}
232240

233241
/// A type erased container for an [`Asset`] value that is capable of inserting the [`Asset`] into a [`World`]'s [`Assets`] collection.
242+
#[diagnostic::on_unimplemented(
243+
message = "`{Self}` is not an asset container",
244+
label = "Invalid Container"
245+
)]
234246
pub trait AssetContainer: Downcast + Any + Send + Sync + 'static {
235247
fn insert(self: Box<Self>, id: UntypedAssetId, world: &mut World);
236248
fn asset_type_name(&self) -> &'static str;

crates/bevy_asset/src/meta.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ pub struct ProcessedInfoMinimal {
114114

115115
/// A dynamic type-erased counterpart to [`AssetMeta`] that enables passing around and interacting with [`AssetMeta`] without knowing
116116
/// its type.
117+
#[diagnostic::on_unimplemented(
118+
message = "`{Self}` can not be used as an erased AssetMeta",
119+
label = "Invalid Asset Meta"
120+
)]
117121
pub trait AssetMetaDyn: Downcast + Send + Sync {
118122
/// Returns a reference to the [`AssetLoader`] settings, if they exist.
119123
fn loader_settings(&self) -> Option<&dyn Settings>;
@@ -160,6 +164,10 @@ impl_downcast!(AssetMetaDyn);
160164
/// Settings used by the asset system, such as by [`AssetLoader`], [`Process`], and [`AssetSaver`]
161165
///
162166
/// [`AssetSaver`]: crate::saver::AssetSaver
167+
#[diagnostic::on_unimplemented(
168+
message = "`{Self}` can not be used as an asset setting",
169+
label = "Invalid Settings"
170+
)]
163171
pub trait Settings: Downcast + Send + Sync + 'static {}
164172

165173
impl<T: 'static> Settings for T where T: Send + Sync {}

crates/bevy_asset/src/processor/process.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ use thiserror::Error;
2121
///
2222
/// This is a "low level", maximally flexible interface. Most use cases are better served by the [`LoadTransformAndSave`] implementation
2323
/// of [`Process`].
24+
#[diagnostic::on_unimplemented(
25+
message = "`{Self}` can not process assets",
26+
label = "Invalid Asset Process"
27+
)]
2428
pub trait Process: Send + Sync + Sized + 'static {
2529
/// The configuration / settings used to process the asset. This will be stored in the [`AssetMeta`] and is user-configurable per-asset.
2630
type Settings: Settings + Default + Serialize + for<'a> Deserialize<'a>;
@@ -243,6 +247,10 @@ impl<Loader: AssetLoader, Saver: AssetSaver<Asset = Loader::Asset>> Process
243247

244248
/// A type-erased variant of [`Process`] that enables interacting with processor implementations without knowing
245249
/// their type.
250+
#[diagnostic::on_unimplemented(
251+
message = "`{Self}` can not be erased",
252+
label = "Invalid Asset Process"
253+
)]
246254
pub trait ErasedProcessor: Send + Sync {
247255
/// Type-erased variant of [`Process::process`].
248256
fn process<'a>(

crates/bevy_asset/src/saver.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ use std::{borrow::Borrow, hash::Hash, ops::Deref};
77

88
/// Saves an [`Asset`] of a given [`AssetSaver::Asset`] type. [`AssetSaver::OutputLoader`] will then be used to load the saved asset
99
/// in the final deployed application. The saver should produce asset bytes in a format that [`AssetSaver::OutputLoader`] can read.
10+
#[diagnostic::on_unimplemented(
11+
message = "`{Self}` is not an asset saver",
12+
label = "Invalid Asset Saver"
13+
)]
1014
pub trait AssetSaver: Send + Sync + 'static {
1115
/// The top level [`Asset`] saved by this [`AssetSaver`].
1216
type Asset: Asset;
@@ -30,6 +34,10 @@ pub trait AssetSaver: Send + Sync + 'static {
3034
}
3135

3236
/// A type-erased dynamic variant of [`AssetSaver`] that allows callers to save assets without knowing the actual type of the [`AssetSaver`].
37+
#[diagnostic::on_unimplemented(
38+
message = "`{Self}` is not an erasable asset saver",
39+
label = "Invalid Asset Saver"
40+
)]
3341
pub trait ErasedAssetSaver: Send + Sync + 'static {
3442
/// Saves the given runtime [`ErasedLoadedAsset`] by writing it to a byte format using `writer`. The passed in `settings` can influence how the
3543
/// `asset` is saved.

crates/bevy_asset/src/transformer.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ use std::{
88
};
99

1010
/// Transforms an [`Asset`] of a given [`AssetTransformer::AssetInput`] type to an [`Asset`] of [`AssetTransformer::AssetOutput`] type.
11+
#[diagnostic::on_unimplemented(
12+
message = "`{Self}` is not an asset transformer",
13+
label = "Invalid Asset Transformer"
14+
)]
1115
pub trait AssetTransformer: Send + Sync + 'static {
1216
/// The [`Asset`] type which this [`AssetTransformer`] takes as and input.
1317
type AssetInput: Asset;

crates/bevy_audio/src/audio_source.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ impl AssetLoader for AudioLoader {
8080
/// Types that implement this trait usually contain raw sound data that can be converted into an iterator of samples.
8181
/// This trait is implemented for [`AudioSource`].
8282
/// Check the example [`decodable`](https://github.com/bevyengine/bevy/blob/latest/examples/audio/decodable.rs) for how to implement this trait on a custom type.
83+
#[diagnostic::on_unimplemented(
84+
message = "`{Self}` is not a decodable audio source",
85+
label = "Invalid Source"
86+
)]
8387
pub trait Decodable: Send + Sync + 'static {
8488
/// The type of the audio samples.
8589
/// Usually a [`u16`], [`i16`] or [`f32`], as those implement [`rodio::Sample`].
@@ -106,6 +110,7 @@ impl Decodable for AudioSource {
106110

107111
/// A trait that allows adding a custom audio source to the object.
108112
/// This is implemented for [`App`][bevy_app::App] to allow registering custom [`Decodable`] types.
113+
#[diagnostic::on_unimplemented(message = "`{Self}` is not an App", label = "Invalid App")]
109114
pub trait AddAudioSource {
110115
/// Registers an audio source.
111116
/// The type must implement [`Decodable`],

crates/bevy_audio/src/sinks.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ use bevy_transform::prelude::Transform;
44
use rodio::{Sink, SpatialSink};
55

66
/// Common interactions with an audio sink.
7+
#[diagnostic::on_unimplemented(
8+
message = "`{Self}` is not an audio sink",
9+
label = "Invalid Audio Sink"
10+
)]
711
pub trait AudioSinkPlayback {
812
/// Gets the volume of the sound.
913
///

crates/bevy_color/src/color_difference.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
33
/// Calculate the distance between this and another color as if they were coordinates
44
/// in a Euclidean space. Alpha is not considered in the distance calculation.
5+
#[diagnostic::on_unimplemented(
6+
message = "`{Self}` does not have a definition for distance",
7+
label = "Invalid Color Model"
8+
)]
59
pub trait EuclideanDistance: Sized {
610
/// Distance from `self` to `other`.
711
fn distance(&self, other: &Self) -> f32 {

crates/bevy_color/src/color_ops.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ use bevy_math::{Vec3, Vec4};
33
/// Methods for changing the luminance of a color. Note that these methods are not
44
/// guaranteed to produce consistent results across color spaces,
55
/// but will be within a given space.
6+
#[diagnostic::on_unimplemented(
7+
message = "`{Self}` does not have a definition of luminance",
8+
label = "Non-Luminance Color Model"
9+
)]
610
pub trait Luminance: Sized {
711
/// Return the luminance of this color (0.0 - 1.0).
812
fn luminance(&self) -> f32;
@@ -30,6 +34,10 @@ pub trait Luminance: Sized {
3034
}
3135

3236
/// Linear interpolation of two colors within a given color space.
37+
#[diagnostic::on_unimplemented(
38+
message = "`{Self}` can not be mixed",
39+
label = "Unmixable Color Model"
40+
)]
3341
pub trait Mix: Sized {
3442
/// Linearly interpolate between this and another color, by factor.
3543
/// Factor should be between 0.0 and 1.0.
@@ -43,6 +51,10 @@ pub trait Mix: Sized {
4351
}
4452

4553
/// Methods for manipulating alpha values.
54+
#[diagnostic::on_unimplemented(
55+
message = "`{Self}` does not have an alpha channel",
56+
label = "Opaque Color Model"
57+
)]
4658
pub trait Alpha: Sized {
4759
/// Return a new version of this color with the given alpha value.
4860
fn with_alpha(&self, alpha: f32) -> Self;
@@ -65,6 +77,10 @@ pub trait Alpha: Sized {
6577
}
6678

6779
/// Trait for manipulating the hue of a color.
80+
#[diagnostic::on_unimplemented(
81+
message = "`{Self}` does not have a definition of hue",
82+
label = "Non-Hue Color Model"
83+
)]
6884
pub trait Hue: Sized {
6985
/// Return a new version of this color with the hue channel set to the given value.
7086
fn with_hue(&self, hue: f32) -> Self;
@@ -83,6 +99,10 @@ pub trait Hue: Sized {
8399
}
84100

85101
/// Trait with methods for converting colors to non-color types
102+
#[diagnostic::on_unimplemented(
103+
message = "`{Self}` cannot be decomposed into color components",
104+
label = "Invalid Color Model"
105+
)]
86106
pub trait ColorToComponents {
87107
/// Convert to an f32 array
88108
fn to_f32_array(self) -> [f32; 4];

crates/bevy_color/src/color_range.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ use crate::Mix;
77
/// implements [`Mix`].
88
///
99
/// This is useful for defining gradients or animated color transitions.
10+
#[diagnostic::on_unimplemented(
11+
message = "`{Self}` is not a valid color range",
12+
label = "Invalid Color Range"
13+
)]
1014
pub trait ColorRange<T: Mix> {
1115
/// Get the color value at the given interpolation factor, which should be between 0.0 (start)
1216
/// and 1.0 (end).

crates/bevy_diagnostic/src/diagnostic.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ impl SystemBuffer for DiagnosticsBuffer {
382382
}
383383

384384
/// Extend [`App`] with new `register_diagnostic` function.
385+
#[diagnostic::on_unimplemented(message = "`{Self}` is not an App", label = "Invalid App")]
385386
pub trait RegisterDiagnostic {
386387
/// Register a new [`Diagnostic`] with an [`App`].
387388
///

crates/bevy_dynamic_plugin/src/loader.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ pub unsafe fn dynamically_load_plugin<P: AsRef<OsStr>>(
5151
}
5252

5353
/// An extension trait for [`App`] that allows loading dynamic plugins.
54+
#[diagnostic::on_unimplemented(message = "`{Self}` is not an App", label = "Invalid App")]
5455
pub trait DynamicPluginExt {
5556
/// Dynamically links a plugin at the given path, registering the plugin.
5657
///

crates/bevy_ecs/src/bundle.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ pub unsafe trait Bundle: DynamicBundle + Send + Sync + 'static {
165165
}
166166

167167
/// The parts from [`Bundle`] that don't require statically knowing the components of the bundle.
168+
#[diagnostic::on_unimplemented(
169+
message = "`{Self}` is not a dynamic component bundle",
170+
label = "Invalid Bundle"
171+
)]
168172
pub trait DynamicBundle {
169173
// SAFETY:
170174
// The `StorageType` argument passed into [`Bundle::get_components`] must be correct for the

0 commit comments

Comments
 (0)