Skip to content

Commit 3ac8850

Browse files
tim-blackbirdalice-i-cecilecart
authored andcommitted
Make Resource trait opt-in, requiring #[derive(Resource)] V2 (bevyengine#5577)
*This PR description is an edited copy of bevyengine#5007, written by @alice-i-cecile.* # Objective Follow-up to bevyengine#2254. The `Resource` trait currently has a blanket implementation for all types that meet its bounds. While ergonomic, this results in several drawbacks: * it is possible to make confusing, silent mistakes such as inserting a function pointer (Foo) rather than a value (Foo::Bar) as a resource * it is challenging to discover if a type is intended to be used as a resource * we cannot later add customization options (see the [RFC](https://github.com/bevyengine/rfcs/blob/main/rfcs/27-derive-component.md) for the equivalent choice for Component). * dependencies can use the same Rust type as a resource in invisibly conflicting ways * raw Rust types used as resources cannot preserve privacy appropriately, as anyone able to access that type can read and write to internal values * we cannot capture a definitive list of possible resources to display to users in an editor ## Notes to reviewers * Review this commit-by-commit; there's effectively no back-tracking and there's a lot of churn in some of these commits. *ira: My commits are not as well organized :')* * I've relaxed the bound on Local to Send + Sync + 'static: I don't think these concerns apply there, so this can keep things simple. Storing e.g. a u32 in a Local is fine, because there's a variable name attached explaining what it does. * I think this is a bad place for the Resource trait to live, but I've left it in place to make reviewing easier. IMO that's best tackled with bevyengine#4981. ## Changelog `Resource` is no longer automatically implemented for all matching types. Instead, use the new `#[derive(Resource)]` macro. ## Migration Guide Add `#[derive(Resource)]` to all types you are using as a resource. If you are using a third party type as a resource, wrap it in a tuple struct to bypass orphan rules. Consider deriving `Deref` and `DerefMut` to improve ergonomics. `ClearColor` no longer implements `Component`. Using `ClearColor` as a component in 0.8 did nothing. Use the `ClearColorConfig` in the `Camera3d` and `Camera2d` components instead. Co-authored-by: Alice <[email protected]> Co-authored-by: Alice Cecile <[email protected]> Co-authored-by: devil-ira <[email protected]> Co-authored-by: Carter Anderson <[email protected]>
1 parent 12c85a0 commit 3ac8850

File tree

133 files changed

+804
-524
lines changed

Some content is hidden

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

133 files changed

+804
-524
lines changed

benches/benches/bevy_ecs/scheduling/run_criteria.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use bevy_ecs::{
22
component::Component,
3-
prelude::{ParallelSystemDescriptorCoercion, Res, RunCriteriaDescriptorCoercion},
3+
prelude::{ParallelSystemDescriptorCoercion, Res, Resource, RunCriteriaDescriptorCoercion},
44
schedule::{ShouldRun, Stage, SystemStage},
55
system::Query,
66
world::World,
@@ -136,7 +136,7 @@ pub fn run_criteria_no_with_labels(criterion: &mut Criterion) {
136136
group.finish();
137137
}
138138

139-
#[derive(Component)]
139+
#[derive(Component, Resource)]
140140
struct TestBool(pub bool);
141141

142142
pub fn run_criteria_yes_with_query(criterion: &mut Criterion) {

crates/bevy_app/src/app.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::{CoreStage, Plugin, PluginGroup, PluginGroupBuilder, StartupSchedule, StartupStage};
22
pub use bevy_derive::AppLabel;
3+
use bevy_derive::{Deref, DerefMut};
34
use bevy_ecs::{
45
event::{Event, Events},
56
prelude::{FromWorld, IntoExclusiveSystem},
@@ -22,6 +23,11 @@ bevy_utils::define_label!(
2223
AppLabelId,
2324
);
2425

26+
/// The [`Resource`] that stores the [`App`]'s [`TypeRegistry`](bevy_reflect::TypeRegistry).
27+
#[cfg(feature = "bevy_reflect")]
28+
#[derive(Resource, Clone, Deref, DerefMut, Default)]
29+
pub struct AppTypeRegistry(pub bevy_reflect::TypeRegistryArc);
30+
2531
#[allow(clippy::needless_doctest_main)]
2632
/// A container of app logic and data.
2733
///
@@ -74,7 +80,7 @@ impl Default for App {
7480
fn default() -> Self {
7581
let mut app = App::empty();
7682
#[cfg(feature = "bevy_reflect")]
77-
app.init_resource::<bevy_reflect::TypeRegistryArc>();
83+
app.init_resource::<AppTypeRegistry>();
7884

7985
app.add_default_stages()
8086
.add_event::<AppExit>()
@@ -647,7 +653,9 @@ impl App {
647653
///
648654
/// ```
649655
/// # use bevy_app::prelude::*;
656+
/// # use bevy_ecs::prelude::*;
650657
/// #
658+
/// #[derive(Resource)]
651659
/// struct MyCounter {
652660
/// counter: usize,
653661
/// }
@@ -660,15 +668,16 @@ impl App {
660668
self
661669
}
662670

663-
/// Inserts a non-send [`Resource`] to the app.
671+
/// Inserts a non-send resource to the app.
664672
///
665673
/// You usually want to use [`insert_resource`](Self::insert_resource),
666-
/// but there are some special cases when a [`Resource`] cannot be sent across threads.
674+
/// but there are some special cases when a resource cannot be sent across threads.
667675
///
668676
/// # Examples
669677
///
670678
/// ```
671679
/// # use bevy_app::prelude::*;
680+
/// # use bevy_ecs::prelude::*;
672681
/// #
673682
/// struct MyCounter {
674683
/// counter: usize,
@@ -694,7 +703,9 @@ impl App {
694703
///
695704
/// ```
696705
/// # use bevy_app::prelude::*;
706+
/// # use bevy_ecs::prelude::*;
697707
/// #
708+
/// #[derive(Resource)]
698709
/// struct MyCounter {
699710
/// counter: usize,
700711
/// }
@@ -873,7 +884,7 @@ impl App {
873884
#[cfg(feature = "bevy_reflect")]
874885
pub fn register_type<T: bevy_reflect::GetTypeRegistration>(&mut self) -> &mut Self {
875886
{
876-
let registry = self.world.resource_mut::<bevy_reflect::TypeRegistryArc>();
887+
let registry = self.world.resource_mut::<AppTypeRegistry>();
877888
registry.write().register::<T>();
878889
}
879890
self
@@ -906,7 +917,7 @@ impl App {
906917
&mut self,
907918
) -> &mut Self {
908919
{
909-
let registry = self.world.resource_mut::<bevy_reflect::TypeRegistryArc>();
920+
let registry = self.world.resource_mut::<AppTypeRegistry>();
910921
registry.write().register_type_data::<T, D>();
911922
}
912923
self

crates/bevy_app/src/ci_testing.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
use crate::{app::AppExit, App};
22
use serde::Deserialize;
33

4+
use bevy_ecs::prelude::Resource;
45
use bevy_utils::tracing::info;
56

67
/// A configuration struct for automated CI testing.
78
///
89
/// It gets used when the `bevy_ci_testing` feature is enabled to automatically
910
/// exit a Bevy app when run through the CI. This is needed because otherwise
1011
/// Bevy apps would be stuck in the game loop and wouldn't allow the CI to progress.
11-
#[derive(Deserialize)]
12+
#[derive(Deserialize, Resource)]
1213
pub struct CiTestingConfig {
1314
/// The number of frames after which Bevy should exit.
1415
pub exit_after: Option<u32>,

crates/bevy_app/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ pub use schedule_runner::*;
1818

1919
#[allow(missing_docs)]
2020
pub mod prelude {
21+
#[cfg(feature = "bevy_reflect")]
22+
#[doc(hidden)]
23+
pub use crate::AppTypeRegistry;
2124
#[doc(hidden)]
2225
pub use crate::{
2326
app::App, CoreStage, DynamicPlugin, Plugin, PluginGroup, StartupSchedule, StartupStage,

crates/bevy_app/src/schedule_runner.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::{
33
plugin::Plugin,
44
};
55
use bevy_ecs::event::{Events, ManualEventReader};
6+
use bevy_ecs::prelude::Resource;
67
use bevy_utils::{Duration, Instant};
78

89
#[cfg(target_arch = "wasm32")]
@@ -34,7 +35,7 @@ impl Default for RunMode {
3435
/// The configuration information for the [`ScheduleRunnerPlugin`].
3536
///
3637
/// It gets added as a [`Resource`](bevy_ecs::system::Resource) inside of the [`ScheduleRunnerPlugin`].
37-
#[derive(Copy, Clone, Default)]
38+
#[derive(Copy, Clone, Default, Resource)]
3839
pub struct ScheduleRunnerSettings {
3940
/// Determines whether the [`Schedule`](bevy_ecs::schedule::Schedule) is run once or repeatedly.
4041
pub run_mode: RunMode,

crates/bevy_asset/src/asset_server.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
RefChange, RefChangeChannel, SourceInfo, SourceMeta,
66
};
77
use anyhow::Result;
8-
use bevy_ecs::system::{Res, ResMut};
8+
use bevy_ecs::system::{Res, ResMut, Resource};
99
use bevy_log::warn;
1010
use bevy_tasks::IoTaskPool;
1111
use bevy_utils::{Entry, HashMap, Uuid};
@@ -102,7 +102,7 @@ pub struct AssetServerInternal {
102102
/// See the [`asset_loading`] example for more information.
103103
///
104104
/// [`asset_loading`]: https://github.com/bevyengine/bevy/tree/latest/examples/asset/asset_loading.rs
105-
#[derive(Clone)]
105+
#[derive(Clone, Resource)]
106106
pub struct AssetServer {
107107
pub(crate) server: Arc<AssetServerInternal>,
108108
}

crates/bevy_asset/src/assets.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
use bevy_app::App;
66
use bevy_ecs::{
77
event::{EventWriter, Events},
8-
system::ResMut,
8+
system::{ResMut, Resource},
99
world::FromWorld,
1010
};
1111
use bevy_utils::HashMap;
@@ -66,7 +66,7 @@ impl<T: Asset> Debug for AssetEvent<T> {
6666
/// Remember, if there are no Strong handles for an asset (i.e. they have all been dropped), the
6767
/// asset will unload. Make sure you always have a Strong handle when you want to keep an asset
6868
/// loaded!
69-
#[derive(Debug)]
69+
#[derive(Debug, Resource)]
7070
pub struct Assets<T: Asset> {
7171
assets: HashMap<HandleId, T>,
7272
events: Events<AssetEvent<T>>,

crates/bevy_asset/src/debug_asset_server.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use bevy_app::{App, Plugin};
66
use bevy_ecs::{
77
event::Events,
88
schedule::SystemLabel,
9-
system::{NonSendMut, Res, ResMut, SystemState},
9+
system::{NonSendMut, Res, ResMut, Resource, SystemState},
1010
};
1111
use bevy_tasks::{IoTaskPool, TaskPoolBuilder};
1212
use bevy_utils::HashMap;
@@ -52,6 +52,7 @@ pub struct DebugAssetServerPlugin;
5252

5353
/// A collection that maps internal assets in a [`DebugAssetApp`]'s asset server to their mirrors in
5454
/// the main [`App`].
55+
#[derive(Resource)]
5556
pub struct HandleMap<T: Asset> {
5657
/// The collection of asset handles.
5758
pub handles: HashMap<Handle<T>, Handle<T>>,

crates/bevy_asset/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ pub use loader::*;
4343
pub use path::*;
4444

4545
use bevy_app::{prelude::Plugin, App};
46-
use bevy_ecs::schedule::{StageLabel, SystemStage};
46+
use bevy_ecs::{
47+
schedule::{StageLabel, SystemStage},
48+
system::Resource,
49+
};
4750

4851
/// The names of asset stages in an [`App`] schedule.
4952
#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)]
@@ -62,6 +65,7 @@ pub enum AssetStage {
6265
pub struct AssetPlugin;
6366

6467
/// [`AssetServer`] settings.
68+
#[derive(Resource)]
6569
pub struct AssetServerSettings {
6670
/// The base folder where assets are loaded from, relative to the executable.
6771
pub asset_folder: String,

crates/bevy_audio/src/audio.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use crate::{AudioSink, AudioSource, Decodable};
22
use bevy_asset::{Asset, Handle, HandleId};
3+
use bevy_ecs::system::Resource;
34
use parking_lot::RwLock;
45
use std::{collections::VecDeque, fmt};
56

6-
/// Use this resource to play audio
7+
/// Use this [`Resource`] to play audio.
78
///
89
/// ```
910
/// # use bevy_ecs::system::Res;
@@ -13,6 +14,7 @@ use std::{collections::VecDeque, fmt};
1314
/// audio.play(asset_server.load("my_sound.ogg"));
1415
/// }
1516
/// ```
17+
#[derive(Resource)]
1618
pub struct Audio<Source = AudioSource>
1719
where
1820
Source: Asset + Decodable,

0 commit comments

Comments
 (0)