diff --git a/Cargo.toml b/Cargo.toml index 3cd87c291c..ce588d5a60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ keywords = ["game", "engine", "gamedev", "graphics", "bevy"] license = "MIT OR Apache-2.0" repository = "https://github.com/bevyengine/bevy" documentation = "https://docs.rs/bevy" -rust-version = "1.85.0" +rust-version = "1.86.0" [workspace] resolver = "2" diff --git a/crates/bevy_derive/src/lib.rs b/crates/bevy_derive/src/lib.rs index 2636ffc57d..e446d0f50d 100644 --- a/crates/bevy_derive/src/lib.rs +++ b/crates/bevy_derive/src/lib.rs @@ -205,8 +205,6 @@ pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream { pub fn derive_app_label(input: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(input as syn::DeriveInput); let mut trait_path = BevyManifest::shared().get_path("bevy_app"); - let mut dyn_eq_path = trait_path.clone(); trait_path.segments.push(format_ident!("AppLabel").into()); - dyn_eq_path.segments.push(format_ident!("DynEq").into()); - derive_label(input, "AppLabel", &trait_path, &dyn_eq_path) + derive_label(input, "AppLabel", &trait_path) } diff --git a/crates/bevy_dev_tools/src/picking_debug.rs b/crates/bevy_dev_tools/src/picking_debug.rs index 8e4ee7ae86..79c1c8fff4 100644 --- a/crates/bevy_dev_tools/src/picking_debug.rs +++ b/crates/bevy_dev_tools/src/picking_debug.rs @@ -1,7 +1,6 @@ //! Text and on-screen debugging tools use bevy_app::prelude::*; -use bevy_asset::prelude::*; use bevy_color::prelude::*; use bevy_ecs::prelude::*; use bevy_picking::backend::HitData; @@ -248,25 +247,18 @@ pub fn debug_draw( pointers: Query<(Entity, &PointerId, &PointerDebug)>, scale: Res, ) { - let font_handle: Handle = Default::default(); - for (entity, id, debug) in pointers.iter() { + for (entity, id, debug) in &pointers { let Some(pointer_location) = &debug.location else { continue; }; let text = format!("{id:?}\n{debug}"); - for camera in camera_query - .iter() - .map(|(entity, camera)| { - ( - entity, - camera.target.normalize(primary_window.single().ok()), - ) - }) - .filter_map(|(entity, target)| Some(entity).zip(target)) - .filter(|(_entity, target)| target == &pointer_location.target) - .map(|(cam_entity, _target)| cam_entity) - { + for (camera, _) in camera_query.iter().filter(|(_, camera)| { + camera + .target + .normalize(primary_window.single().ok()) + .is_some_and(|target| target == pointer_location.target) + }) { let mut pointer_pos = pointer_location.position; if let Some(viewport) = camera_query .get(camera) @@ -278,23 +270,21 @@ pub fn debug_draw( commands .entity(entity) + .despawn_related::() .insert(( - Text::new(text.clone()), - TextFont { - font: font_handle.clone(), - font_size: 12.0, - ..Default::default() - }, - TextColor(Color::WHITE), Node { position_type: PositionType::Absolute, left: Val::Px(pointer_pos.x + 5.0) / scale.0, top: Val::Px(pointer_pos.y + 5.0) / scale.0, + padding: UiRect::px(10.0, 10.0, 8.0, 6.0), ..Default::default() }, - )) - .insert(Pickable::IGNORE) - .insert(UiTargetCamera(camera)); + BackgroundColor(Color::BLACK.with_alpha(0.75)), + GlobalZIndex(i32::MAX), + Pickable::IGNORE, + UiTargetCamera(camera), + children![(Text::new(text.clone()), TextFont::from_font_size(12.0))], + )); } } } diff --git a/crates/bevy_ecs/Cargo.toml b/crates/bevy_ecs/Cargo.toml index ce08e1a486..bf71d217d4 100644 --- a/crates/bevy_ecs/Cargo.toml +++ b/crates/bevy_ecs/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/bevyengine/bevy" license = "MIT OR Apache-2.0" keywords = ["ecs", "game", "bevy"] categories = ["game-engines", "data-structures"] -rust-version = "1.85.0" +rust-version = "1.86.0" [features] default = ["std", "bevy_reflect", "async_executor", "backtrace"] diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index a1898b1328..ea4908ef3f 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -503,12 +503,10 @@ pub fn derive_schedule_label(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); let mut trait_path = bevy_ecs_path(); trait_path.segments.push(format_ident!("schedule").into()); - let mut dyn_eq_path = trait_path.clone(); trait_path .segments .push(format_ident!("ScheduleLabel").into()); - dyn_eq_path.segments.push(format_ident!("DynEq").into()); - derive_label(input, "ScheduleLabel", &trait_path, &dyn_eq_path) + derive_label(input, "ScheduleLabel", &trait_path) } /// Derive macro generating an impl of the trait `SystemSet`. @@ -519,10 +517,8 @@ pub fn derive_system_set(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); let mut trait_path = bevy_ecs_path(); trait_path.segments.push(format_ident!("schedule").into()); - let mut dyn_eq_path = trait_path.clone(); trait_path.segments.push(format_ident!("SystemSet").into()); - dyn_eq_path.segments.push(format_ident!("DynEq").into()); - derive_label(input, "SystemSet", &trait_path, &dyn_eq_path) + derive_label(input, "SystemSet", &trait_path) } pub(crate) fn bevy_ecs_path() -> syn::Path { diff --git a/crates/bevy_ecs/src/label.rs b/crates/bevy_ecs/src/label.rs index c404c563bd..9d3f6f838d 100644 --- a/crates/bevy_ecs/src/label.rs +++ b/crates/bevy_ecs/src/label.rs @@ -12,9 +12,6 @@ pub use alloc::boxed::Box; /// An object safe version of [`Eq`]. This trait is automatically implemented /// for any `'static` type that implements `Eq`. pub trait DynEq: Any { - /// Casts the type to `dyn Any`. - fn as_any(&self) -> &dyn Any; - /// This method tests for `self` and `other` values to be equal. /// /// Implementers should avoid returning `true` when the underlying types are @@ -29,12 +26,8 @@ impl DynEq for T where T: Any + Eq, { - fn as_any(&self) -> &dyn Any { - self - } - fn dyn_eq(&self, other: &dyn DynEq) -> bool { - if let Some(other) = other.as_any().downcast_ref::() { + if let Some(other) = (other as &dyn Any).downcast_ref::() { return self == other; } false @@ -44,9 +37,6 @@ where /// An object safe version of [`Hash`]. This trait is automatically implemented /// for any `'static` type that implements `Hash`. pub trait DynHash: DynEq { - /// Casts the type to `dyn Any`. - fn as_dyn_eq(&self) -> &dyn DynEq; - /// Feeds this value into the given [`Hasher`]. fn dyn_hash(&self, state: &mut dyn Hasher); } @@ -58,10 +48,6 @@ impl DynHash for T where T: DynEq + Hash, { - fn as_dyn_eq(&self) -> &dyn DynEq { - self - } - fn dyn_hash(&self, mut state: &mut dyn Hasher) { T::hash(self, &mut state); self.type_id().hash(&mut state); @@ -120,7 +106,7 @@ macro_rules! define_label { ) => { $(#[$label_attr])* - pub trait $label_trait_name: 'static + Send + Sync + ::core::fmt::Debug { + pub trait $label_trait_name: Send + Sync + ::core::fmt::Debug + $crate::label::DynEq + $crate::label::DynHash { $($trait_extra_methods)* @@ -129,12 +115,6 @@ macro_rules! define_label { ///`. fn dyn_clone(&self) -> $crate::label::Box; - /// Casts this value to a form where it can be compared with other type-erased values. - fn as_dyn_eq(&self) -> &dyn $crate::label::DynEq; - - /// Feeds this value into the given [`Hasher`]. - fn dyn_hash(&self, state: &mut dyn ::core::hash::Hasher); - /// Returns an [`Interned`] value corresponding to `self`. fn intern(&self) -> $crate::intern::Interned where Self: Sized { @@ -151,15 +131,6 @@ macro_rules! define_label { (**self).dyn_clone() } - /// Casts this value to a form where it can be compared with other type-erased values. - fn as_dyn_eq(&self) -> &dyn $crate::label::DynEq { - (**self).as_dyn_eq() - } - - fn dyn_hash(&self, state: &mut dyn ::core::hash::Hasher) { - (**self).dyn_hash(state); - } - fn intern(&self) -> Self { *self } @@ -167,7 +138,7 @@ macro_rules! define_label { impl PartialEq for dyn $label_trait_name { fn eq(&self, other: &Self) -> bool { - self.as_dyn_eq().dyn_eq(other.as_dyn_eq()) + self.dyn_eq(other) } } @@ -188,7 +159,7 @@ macro_rules! define_label { use ::core::ptr; // Test that both the type id and pointer address are equivalent. - self.as_dyn_eq().type_id() == other.as_dyn_eq().type_id() + self.type_id() == other.type_id() && ptr::addr_eq(ptr::from_ref::(self), ptr::from_ref::(other)) } @@ -196,7 +167,7 @@ macro_rules! define_label { use ::core::{hash::Hash, ptr}; // Hash the type id... - self.as_dyn_eq().type_id().hash(state); + self.type_id().hash(state); // ...and the pointer address. // Cast to a unit `()` first to discard any pointer metadata. diff --git a/crates/bevy_ecs/src/schedule/set.rs b/crates/bevy_ecs/src/schedule/set.rs index a652cd6df3..4974be5d43 100644 --- a/crates/bevy_ecs/src/schedule/set.rs +++ b/crates/bevy_ecs/src/schedule/set.rs @@ -147,15 +147,6 @@ impl SystemSet for SystemTypeSet { fn dyn_clone(&self) -> Box { Box::new(*self) } - - fn as_dyn_eq(&self) -> &dyn DynEq { - self - } - - fn dyn_hash(&self, mut state: &mut dyn Hasher) { - TypeId::of::().hash(&mut state); - self.hash(&mut state); - } } /// A [`SystemSet`] implicitly created when using @@ -178,15 +169,6 @@ impl SystemSet for AnonymousSet { fn dyn_clone(&self) -> Box { Box::new(*self) } - - fn as_dyn_eq(&self) -> &dyn DynEq { - self - } - - fn dyn_hash(&self, mut state: &mut dyn Hasher) { - TypeId::of::().hash(&mut state); - self.hash(&mut state); - } } /// Types that can be converted into a [`SystemSet`]. diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 14c3feb664..f2774116f0 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -1675,7 +1675,7 @@ unsafe impl<'a> SystemParam for &'a Bundles { /// Component change ticks that are more recent than `last_run` will be detected by the system. /// Those can be read by calling [`last_changed`](crate::change_detection::DetectChanges::last_changed) /// on a [`Mut`](crate::change_detection::Mut) or [`ResMut`](ResMut). -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub struct SystemChangeTick { last_run: Tick, this_run: Tick, @@ -2510,10 +2510,7 @@ impl DynSystemParamState { } /// Allows a [`SystemParam::State`] to be used as a trait object for implementing [`DynSystemParam`]. -trait DynParamState: Sync + Send { - /// Casts the underlying `ParamState` to an `Any` so it can be downcast. - fn as_any_mut(&mut self) -> &mut dyn Any; - +trait DynParamState: Sync + Send + Any { /// For the specified [`Archetype`], registers the components accessed by this [`SystemParam`] (if applicable).a /// /// # Safety @@ -2544,10 +2541,6 @@ trait DynParamState: Sync + Send { struct ParamState(T::State); impl DynParamState for ParamState { - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } - unsafe fn new_archetype(&mut self, archetype: &Archetype, system_meta: &mut SystemMeta) { // SAFETY: The caller ensures that `archetype` is from the World the state was initialized from in `init_state`. unsafe { T::new_archetype(&mut self.0, archetype, system_meta) }; @@ -2597,18 +2590,11 @@ unsafe impl SystemParam for DynSystemParam<'_, '_> { change_tick: Tick, ) -> Self::Item<'world, 'state> { // SAFETY: - // - `state.0` is a boxed `ParamState`, and its implementation of `as_any_mut` returns `self`. + // - `state.0` is a boxed `ParamState`. // - The state was obtained from `SystemParamBuilder::build()`, which registers all [`World`] accesses used // by [`SystemParam::get_param`] with the provided [`system_meta`](SystemMeta). // - The caller ensures that the provided world is the same and has the required access. - unsafe { - DynSystemParam::new( - state.0.as_any_mut(), - world, - system_meta.clone(), - change_tick, - ) - } + unsafe { DynSystemParam::new(state.0.as_mut(), world, system_meta.clone(), change_tick) } } unsafe fn new_archetype( diff --git a/crates/bevy_macro_utils/src/label.rs b/crates/bevy_macro_utils/src/label.rs index 1fc540c9c4..7669f85f1a 100644 --- a/crates/bevy_macro_utils/src/label.rs +++ b/crates/bevy_macro_utils/src/label.rs @@ -58,7 +58,6 @@ pub fn derive_label( input: syn::DeriveInput, trait_name: &str, trait_path: &syn::Path, - dyn_eq_path: &syn::Path, ) -> TokenStream { if let syn::Data::Union(_) = &input.data { let message = format!("Cannot derive {trait_name} for unions."); @@ -89,16 +88,6 @@ pub fn derive_label( fn dyn_clone(&self) -> alloc::boxed::Box { alloc::boxed::Box::new(::core::clone::Clone::clone(self)) } - - fn as_dyn_eq(&self) -> &dyn #dyn_eq_path { - self - } - - fn dyn_hash(&self, mut state: &mut dyn ::core::hash::Hasher) { - let ty_id = ::core::any::TypeId::of::(); - ::core::hash::Hash::hash(&ty_id, &mut state); - ::core::hash::Hash::hash(self, &mut state); - } } }; } diff --git a/crates/bevy_render/macros/src/lib.rs b/crates/bevy_render/macros/src/lib.rs index 7a04932bcd..75cbdfa959 100644 --- a/crates/bevy_render/macros/src/lib.rs +++ b/crates/bevy_render/macros/src/lib.rs @@ -80,12 +80,10 @@ pub fn derive_render_label(input: TokenStream) -> TokenStream { trait_path .segments .push(format_ident!("render_graph").into()); - let mut dyn_eq_path = trait_path.clone(); trait_path .segments .push(format_ident!("RenderLabel").into()); - dyn_eq_path.segments.push(format_ident!("DynEq").into()); - derive_label(input, "RenderLabel", &trait_path, &dyn_eq_path) + derive_label(input, "RenderLabel", &trait_path) } /// Derive macro generating an impl of the trait `RenderSubGraph`. @@ -98,10 +96,8 @@ pub fn derive_render_sub_graph(input: TokenStream) -> TokenStream { trait_path .segments .push(format_ident!("render_graph").into()); - let mut dyn_eq_path = trait_path.clone(); trait_path .segments .push(format_ident!("RenderSubGraph").into()); - dyn_eq_path.segments.push(format_ident!("DynEq").into()); - derive_label(input, "RenderSubGraph", &trait_path, &dyn_eq_path) + derive_label(input, "RenderSubGraph", &trait_path) } diff --git a/release-content/migration-guides/interned-labels-cleanup.md b/release-content/migration-guides/interned-labels-cleanup.md new file mode 100644 index 0000000000..281787d2fc --- /dev/null +++ b/release-content/migration-guides/interned-labels-cleanup.md @@ -0,0 +1,8 @@ +--- +title: Interned labels cleanup +pull_requests: [18984] +--- + +- `DynEq::as_any` has been removed. Use `&value as &dyn Any` instead. +- `DynHash::as_dyn_eq` has been removed. Use `&value as &dyn DynEq` instead. +- `as_dyn_eq` has been removed from 'label' types such as `ScheduleLabel` and `SystemSet`. Call `DynEq::dyn_eq` directly on the label instead.