diff --git a/crates/bevy_ecs/src/lib.rs b/crates/bevy_ecs/src/lib.rs index bd0a9f3463..9b5fee4810 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -67,11 +67,13 @@ impl std::hash::Hasher for NoOpTypeIdHasher { self.0 } - fn write(&mut self, _bytes: &[u8]) { + fn write(&mut self, bytes: &[u8]) { // This will never be called: TypeId always just calls write_u64 once! - // This is unlikely to ever change, but as it isn't officially guaranteed, - // panicking will let us detect this as fast as possible. - unimplemented!("Hashing of std::any::TypeId changed"); + // This is a known trick and unlikely to change, but isn't officially guaranteed. + // Don't break applications (slower fallback, just check in test): + self.0 = bytes.iter().fold(self.0, |hash, b| { + hash.rotate_left(8).wrapping_add(*b as u64) + }); } fn write_u64(&mut self, i: u64) { @@ -1750,6 +1752,23 @@ mod tests { ); } + #[test] + fn fast_typeid_hash() { + struct Hasher; + + impl std::hash::Hasher for Hasher { + fn finish(&self) -> u64 { + 0 + } + fn write(&mut self, _: &[u8]) { + panic!("Hashing of std::any::TypeId changed"); + } + fn write_u64(&mut self, _: u64) {} + } + + std::hash::Hash::hash(&TypeId::of::<()>(), &mut Hasher); + } + #[derive(Component)] struct ComponentA(u32);