Skip to content

Commit 21aa5fe

Browse files
Use TypeIdMap whenever possible (#11684)
Use `TypeIdMap<T>` instead of `HashMap<TypeId, T>` - ~~`TypeIdMap` was in `bevy_ecs`. I've kept it there because of #11478~~ - ~~I haven't swapped `bevy_reflect` over because it doesn't depend on `bevy_ecs`, but I'd also be happy with moving `TypeIdMap` to `bevy_utils` and then adding a dependency to that~~ - ~~this is a slight change in the public API of `DrawFunctionsInternal`, does this need to go in the changelog?~~ ## Changelog - moved `TypeIdMap` to `bevy_utils` - changed `DrawFunctionsInternal::indices` to `TypeIdMap` ## Migration Guide - `TypeIdMap` now lives in `bevy_utils` - `DrawFunctionsInternal::indices` now uses a `TypeIdMap`. --------- Co-authored-by: Alice Cecile <[email protected]>
1 parent 4e9590a commit 21aa5fe

File tree

13 files changed

+79
-81
lines changed

13 files changed

+79
-81
lines changed

crates/bevy_app/src/plugin_group.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::{App, AppError, Plugin};
2-
use bevy_utils::{tracing::debug, tracing::warn, HashMap};
2+
use bevy_utils::{tracing::debug, tracing::warn, TypeIdMap};
33
use std::any::TypeId;
44

55
/// Combines multiple [`Plugin`]s into a single unit.
@@ -33,7 +33,7 @@ impl PluginGroup for PluginGroupBuilder {
3333
/// can be disabled, enabled or reordered.
3434
pub struct PluginGroupBuilder {
3535
group_name: String,
36-
plugins: HashMap<TypeId, PluginEntry>,
36+
plugins: TypeIdMap<PluginEntry>,
3737
order: Vec<TypeId>,
3838
}
3939

crates/bevy_asset/src/server/info.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::{
66
};
77
use bevy_ecs::world::World;
88
use bevy_log::warn;
9-
use bevy_utils::{Entry, HashMap, HashSet};
9+
use bevy_utils::{Entry, HashMap, HashSet, TypeIdMap};
1010
use crossbeam_channel::Sender;
1111
use std::{
1212
any::TypeId,
@@ -61,7 +61,7 @@ impl AssetInfo {
6161

6262
#[derive(Default)]
6363
pub(crate) struct AssetInfos {
64-
path_to_id: HashMap<AssetPath<'static>, HashMap<TypeId, UntypedAssetId>>,
64+
path_to_id: HashMap<AssetPath<'static>, TypeIdMap<UntypedAssetId>>,
6565
infos: HashMap<UntypedAssetId, AssetInfo>,
6666
/// If set to `true`, this informs [`AssetInfos`] to track data relevant to watching for changes (such as `load_dependants`)
6767
/// This should only be set at startup.
@@ -72,10 +72,10 @@ pub(crate) struct AssetInfos {
7272
/// Tracks living labeled assets for a given source asset.
7373
/// This should only be set when watching for changes to avoid unnecessary work.
7474
pub(crate) living_labeled_assets: HashMap<AssetPath<'static>, HashSet<String>>,
75-
pub(crate) handle_providers: HashMap<TypeId, AssetHandleProvider>,
76-
pub(crate) dependency_loaded_event_sender: HashMap<TypeId, fn(&mut World, UntypedAssetId)>,
75+
pub(crate) handle_providers: TypeIdMap<AssetHandleProvider>,
76+
pub(crate) dependency_loaded_event_sender: TypeIdMap<fn(&mut World, UntypedAssetId)>,
7777
pub(crate) dependency_failed_event_sender:
78-
HashMap<TypeId, fn(&mut World, UntypedAssetId, AssetPath<'static>, AssetLoadError)>,
78+
TypeIdMap<fn(&mut World, UntypedAssetId, AssetPath<'static>, AssetLoadError)>,
7979
}
8080

8181
impl std::fmt::Debug for AssetInfos {
@@ -112,7 +112,7 @@ impl AssetInfos {
112112
#[allow(clippy::too_many_arguments)]
113113
fn create_handle_internal(
114114
infos: &mut HashMap<UntypedAssetId, AssetInfo>,
115-
handle_providers: &HashMap<TypeId, AssetHandleProvider>,
115+
handle_providers: &TypeIdMap<AssetHandleProvider>,
116116
living_labeled_assets: &mut HashMap<AssetPath<'static>, HashSet<String>>,
117117
watching_for_changes: bool,
118118
type_id: TypeId,
@@ -205,7 +205,7 @@ impl AssetInfos {
205205
.ok_or(GetOrCreateHandleInternalError::HandleMissingButTypeIdNotSpecified)?;
206206

207207
match handles.entry(type_id) {
208-
Entry::Occupied(entry) => {
208+
bevy_utils::hashbrown::hash_map::Entry::Occupied(entry) => {
209209
let id = *entry.get();
210210
// if there is a path_to_id entry, info always exists
211211
let info = self.infos.get_mut(&id).unwrap();
@@ -246,7 +246,7 @@ impl AssetInfos {
246246
}
247247
}
248248
// The entry does not exist, so this is a "fresh" asset load. We must create a new handle
249-
Entry::Vacant(entry) => {
249+
bevy_utils::hashbrown::hash_map::Entry::Vacant(entry) => {
250250
let should_load = match loading_mode {
251251
HandleLoadingMode::NotLoading => false,
252252
HandleLoadingMode::Request | HandleLoadingMode::Force => true,
@@ -640,7 +640,7 @@ impl AssetInfos {
640640

641641
fn process_handle_drop_internal(
642642
infos: &mut HashMap<UntypedAssetId, AssetInfo>,
643-
path_to_id: &mut HashMap<AssetPath<'static>, HashMap<TypeId, UntypedAssetId>>,
643+
path_to_id: &mut HashMap<AssetPath<'static>, TypeIdMap<UntypedAssetId>>,
644644
loader_dependants: &mut HashMap<AssetPath<'static>, HashSet<AssetPath<'static>>>,
645645
living_labeled_assets: &mut HashMap<AssetPath<'static>, HashSet<String>>,
646646
watching_for_changes: bool,

crates/bevy_asset/src/server/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::{
1919
use bevy_ecs::prelude::*;
2020
use bevy_log::{error, info, warn};
2121
use bevy_tasks::IoTaskPool;
22-
use bevy_utils::{CowArc, HashMap, HashSet};
22+
use bevy_utils::{CowArc, HashMap, HashSet, TypeIdMap};
2323
use crossbeam_channel::{Receiver, Sender};
2424
use futures_lite::StreamExt;
2525
use info::*;
@@ -1238,7 +1238,7 @@ pub fn handle_internal_asset_events(world: &mut World) {
12381238

12391239
#[derive(Default)]
12401240
pub(crate) struct AssetLoaders {
1241-
type_id_to_loader: HashMap<TypeId, MaybeAssetLoader>,
1241+
type_id_to_loader: TypeIdMap<MaybeAssetLoader>,
12421242
extension_to_type_id: HashMap<String, TypeId>,
12431243
type_name_to_type_id: HashMap<&'static str, TypeId>,
12441244
preregistered_loaders: HashMap<&'static str, TypeId>,

crates/bevy_ecs/src/bundle.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! This module contains the [`Bundle`] trait and some other helper types.
44
55
pub use bevy_ecs_macros::Bundle;
6-
use bevy_utils::{HashMap, HashSet};
6+
use bevy_utils::{HashMap, HashSet, TypeIdMap};
77

88
use crate::{
99
archetype::{
@@ -14,7 +14,6 @@ use crate::{
1414
entity::{Entities, Entity, EntityLocation},
1515
query::DebugCheckedUnwrap,
1616
storage::{SparseSetIndex, SparseSets, Storages, Table, TableRow},
17-
TypeIdMap,
1817
};
1918
use bevy_ptr::OwningPtr;
2019
use bevy_utils::all_tuples;

crates/bevy_ecs/src/component.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ use crate::{
66
storage::{SparseSetIndex, Storages},
77
system::{Local, Resource, SystemParam},
88
world::{FromWorld, World},
9-
TypeIdMap,
109
};
1110
pub use bevy_ecs_macros::Component;
1211
use bevy_ptr::{OwningPtr, UnsafeCellDeref};
1312
#[cfg(feature = "bevy_reflect")]
1413
use bevy_reflect::Reflect;
14+
use bevy_utils::TypeIdMap;
1515
use std::cell::UnsafeCell;
1616
use std::{
1717
alloc::Layout,

crates/bevy_ecs/src/lib.rs

-47
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ pub mod storage;
2121
pub mod system;
2222
pub mod world;
2323

24-
use std::any::TypeId;
25-
2624
pub use bevy_ptr as ptr;
2725

2826
/// Most commonly used re-exported types.
@@ -56,34 +54,6 @@ pub mod prelude {
5654

5755
pub use bevy_utils::all_tuples;
5856

59-
/// A specialized hashmap type with Key of [`TypeId`]
60-
type TypeIdMap<V> =
61-
std::collections::HashMap<TypeId, V, std::hash::BuildHasherDefault<NoOpTypeIdHasher>>;
62-
63-
#[doc(hidden)]
64-
#[derive(Default)]
65-
struct NoOpTypeIdHasher(u64);
66-
67-
// TypeId already contains a high-quality hash, so skip re-hashing that hash.
68-
impl std::hash::Hasher for NoOpTypeIdHasher {
69-
fn finish(&self) -> u64 {
70-
self.0
71-
}
72-
73-
fn write(&mut self, bytes: &[u8]) {
74-
// This will never be called: TypeId always just calls write_u64 once!
75-
// This is a known trick and unlikely to change, but isn't officially guaranteed.
76-
// Don't break applications (slower fallback, just check in test):
77-
self.0 = bytes.iter().fold(self.0, |hash, b| {
78-
hash.rotate_left(8).wrapping_add(*b as u64)
79-
});
80-
}
81-
82-
fn write_u64(&mut self, i: u64) {
83-
self.0 = i;
84-
}
85-
}
86-
8757
#[cfg(test)]
8858
mod tests {
8959
use crate as bevy_ecs;
@@ -1755,23 +1725,6 @@ mod tests {
17551725
);
17561726
}
17571727

1758-
#[test]
1759-
fn fast_typeid_hash() {
1760-
struct Hasher;
1761-
1762-
impl std::hash::Hasher for Hasher {
1763-
fn finish(&self) -> u64 {
1764-
0
1765-
}
1766-
fn write(&mut self, _: &[u8]) {
1767-
panic!("Hashing of std::any::TypeId changed");
1768-
}
1769-
fn write_u64(&mut self, _: u64) {}
1770-
}
1771-
1772-
std::hash::Hash::hash(&TypeId::of::<()>(), &mut Hasher);
1773-
}
1774-
17751728
#[derive(Component)]
17761729
struct ComponentA(u32);
17771730

crates/bevy_ecs/src/schedule/stepping.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::{
99
use bevy_utils::{
1010
thiserror::Error,
1111
tracing::{error, info, warn},
12+
TypeIdMap,
1213
};
1314

1415
#[cfg(test)]
@@ -617,7 +618,7 @@ struct ScheduleState {
617618

618619
/// changes to system behavior that should be applied the next time
619620
/// [`ScheduleState::skipped_systems()`] is called
620-
behavior_updates: HashMap<TypeId, Option<SystemBehavior>>,
621+
behavior_updates: TypeIdMap<Option<SystemBehavior>>,
621622

622623
/// This field contains the first steppable system in the schedule.
623624
first: Option<usize>,

crates/bevy_gizmos/src/config.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub use bevy_gizmos_macros::GizmoConfigGroup;
66
use bevy_ecs::{component::Component, system::Resource};
77
use bevy_reflect::{Reflect, TypePath};
88
use bevy_render::view::RenderLayers;
9-
use bevy_utils::HashMap;
9+
use bevy_utils::TypeIdMap;
1010
use core::panic;
1111
use std::{
1212
any::TypeId,
@@ -30,7 +30,7 @@ pub struct DefaultGizmoConfigGroup;
3030
#[derive(Resource, Default)]
3131
pub struct GizmoConfigStore {
3232
// INVARIANT: must map TypeId::of::<T>() to correct type T
33-
store: HashMap<TypeId, (GizmoConfig, Box<dyn Reflect>)>,
33+
store: TypeIdMap<(GizmoConfig, Box<dyn Reflect>)>,
3434
}
3535

3636
impl GizmoConfigStore {

crates/bevy_gizmos/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ use bevy_render::{
7777
renderer::RenderDevice,
7878
Extract, ExtractSchedule, Render, RenderApp, RenderSet,
7979
};
80-
use bevy_utils::HashMap;
80+
use bevy_utils::TypeIdMap;
8181
use config::{
8282
DefaultGizmoConfigGroup, GizmoConfig, GizmoConfigGroup, GizmoConfigStore, GizmoMeshConfig,
8383
};
@@ -206,8 +206,8 @@ impl AppGizmoBuilder for App {
206206

207207
#[derive(Resource, Default)]
208208
struct LineGizmoHandles {
209-
list: HashMap<TypeId, Handle<LineGizmo>>,
210-
strip: HashMap<TypeId, Handle<LineGizmo>>,
209+
list: TypeIdMap<Handle<LineGizmo>>,
210+
strip: TypeIdMap<Handle<LineGizmo>>,
211211
}
212212

213213
fn update_gizmo_meshes<T: GizmoConfigGroup>(

crates/bevy_reflect/src/type_registry.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{serde::Serializable, Reflect, TypeInfo, TypePath, Typed};
22
use bevy_ptr::{Ptr, PtrMut};
3-
use bevy_utils::{HashMap, HashSet};
3+
use bevy_utils::{HashMap, HashSet, TypeIdMap};
44
use downcast_rs::{impl_downcast, Downcast};
55
use serde::Deserialize;
66
use std::{
@@ -22,7 +22,7 @@ use std::{
2222
/// [Registering]: TypeRegistry::register
2323
/// [crate-level documentation]: crate
2424
pub struct TypeRegistry {
25-
registrations: HashMap<TypeId, TypeRegistration>,
25+
registrations: TypeIdMap<TypeRegistration>,
2626
short_path_to_id: HashMap<&'static str, TypeId>,
2727
type_path_to_id: HashMap<&'static str, TypeId>,
2828
ambiguous_names: HashSet<&'static str>,
@@ -318,7 +318,7 @@ impl TypeRegistryArc {
318318
///
319319
/// [crate-level documentation]: crate
320320
pub struct TypeRegistration {
321-
data: HashMap<TypeId, Box<dyn TypeData>>,
321+
data: TypeIdMap<Box<dyn TypeData>>,
322322
type_info: &'static TypeInfo,
323323
}
324324

@@ -373,15 +373,15 @@ impl TypeRegistration {
373373
/// Creates type registration information for `T`.
374374
pub fn of<T: Reflect + Typed + TypePath>() -> Self {
375375
Self {
376-
data: HashMap::default(),
376+
data: Default::default(),
377377
type_info: T::type_info(),
378378
}
379379
}
380380
}
381381

382382
impl Clone for TypeRegistration {
383383
fn clone(&self) -> Self {
384-
let mut data = HashMap::default();
384+
let mut data = TypeIdMap::default();
385385
for (id, type_data) in &self.data {
386386
data.insert(*id, (*type_data).clone_type_data());
387387
}

crates/bevy_render/src/render_phase/draw.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use bevy_ecs::{
66
system::{ReadOnlySystemParam, Resource, SystemParam, SystemParamItem, SystemState},
77
world::World,
88
};
9-
use bevy_utils::{all_tuples, HashMap};
9+
use bevy_utils::{all_tuples, TypeIdMap};
1010
use std::{
1111
any::TypeId,
1212
fmt::Debug,
@@ -47,7 +47,7 @@ pub struct DrawFunctionId(u32);
4747
/// For retrieval, the [`Draw`] functions are mapped to their respective [`TypeId`]s.
4848
pub struct DrawFunctionsInternal<P: PhaseItem> {
4949
pub draw_functions: Vec<Box<dyn Draw<P>>>,
50-
pub indices: HashMap<TypeId, DrawFunctionId>,
50+
pub indices: TypeIdMap<DrawFunctionId>,
5151
}
5252

5353
impl<P: PhaseItem> DrawFunctionsInternal<P> {
@@ -111,7 +111,7 @@ impl<P: PhaseItem> Default for DrawFunctions<P> {
111111
Self {
112112
internal: RwLock::new(DrawFunctionsInternal {
113113
draw_functions: Vec::new(),
114-
indices: HashMap::default(),
114+
indices: Default::default(),
115115
}),
116116
}
117117
}

crates/bevy_scene/src/dynamic_scene.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ use bevy_ecs::{
55
world::World,
66
};
77
use bevy_reflect::{Reflect, TypePath, TypeRegistryArc};
8-
use bevy_utils::{EntityHashMap, HashMap};
9-
use std::any::TypeId;
8+
use bevy_utils::{EntityHashMap, TypeIdMap};
109

1110
#[cfg(feature = "serialize")]
1211
use crate::serde::SceneSerializer;
@@ -97,7 +96,7 @@ impl DynamicScene {
9796
// of which entities in the scene use that component.
9897
// This is so we can update the scene-internal references to references
9998
// of the actual entities in the world.
100-
let mut scene_mappings: HashMap<TypeId, Vec<Entity>> = HashMap::default();
99+
let mut scene_mappings: TypeIdMap<Vec<Entity>> = Default::default();
101100

102101
for scene_entity in &self.entities {
103102
// Fetch the entity with the given entity id from the `entity_map`
@@ -132,7 +131,7 @@ impl DynamicScene {
132131
if registration.data::<ReflectMapEntities>().is_some() {
133132
scene_mappings
134133
.entry(registration.type_id())
135-
.or_insert(Vec::new())
134+
.or_default()
136135
.push(entity);
137136
}
138137

0 commit comments

Comments
 (0)