Skip to content

Commit dd4479e

Browse files
authored
Fix PartialReflect::apply for maps, remove get_at/_mut from Map trait (#19802)
# Objective - Fixes #14328 - `DynamicMap::drain` was broken (indices weren't cleared, causing a panic when reading later) - `PartialReflect::apply` was broken for maps and sets, because they don't remove entries from the `self` map that aren't in the applied map. - I discovered this bug when implementing MapEntities on a Component containing a `HashMap<Entity, _>`. Because `apply` is used to reapply the changes to the reflected map, the map ended up littered with a ton of outdated entries. ## Solution - Remove the separate `Vec` in `DynamicMap` and use the `HashTable` directly, like it is in `DynamicSet`. - Replace `MapIter` by `Box<dyn Iterator>` (like for `DynamicSet`), and `Map::get_at` and `Map::get_at_mut` which are now unused. - Now assume `DynamicMap` types are unordered and adjust documentation accordingly. - Fix documentation of `DynamicSet` (ordered -> unordered) - Added `Map::retain` and `Set::retain`, and use them to remove excess entries in `PartialReflect::apply` implementations. ## Testing - Added `map::tests::apply` and `set::tests::apply` to validate `<DynamicMap as PartialReflect>::apply` and `<DynamicSet as PartialReflect>::apply`
1 parent 97dcb27 commit dd4479e

File tree

8 files changed

+143
-267
lines changed

8 files changed

+143
-267
lines changed

crates/bevy_reflect/src/impls/alloc/collections/btree/map.rs

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::{
22
error::ReflectCloneError,
33
generics::{Generics, TypeParamInfo},
44
kind::{ReflectKind, ReflectMut, ReflectOwned, ReflectRef},
5-
map::{map_apply, map_partial_eq, map_try_apply, Map, MapInfo, MapIter},
5+
map::{map_apply, map_partial_eq, map_try_apply, Map, MapInfo},
66
prelude::*,
77
reflect::{impl_full_reflect, ApplyError},
88
type_info::{MaybeTyped, TypeInfo, Typed},
@@ -31,27 +31,15 @@ where
3131
.map(|value| value as &mut dyn PartialReflect)
3232
}
3333

34-
fn get_at(&self, index: usize) -> Option<(&dyn PartialReflect, &dyn PartialReflect)> {
35-
self.iter()
36-
.nth(index)
37-
.map(|(key, value)| (key as &dyn PartialReflect, value as &dyn PartialReflect))
38-
}
39-
40-
fn get_at_mut(
41-
&mut self,
42-
index: usize,
43-
) -> Option<(&dyn PartialReflect, &mut dyn PartialReflect)> {
44-
self.iter_mut()
45-
.nth(index)
46-
.map(|(key, value)| (key as &dyn PartialReflect, value as &mut dyn PartialReflect))
47-
}
48-
4934
fn len(&self) -> usize {
5035
Self::len(self)
5136
}
5237

53-
fn iter(&self) -> MapIter {
54-
MapIter::new(self)
38+
fn iter(&self) -> Box<dyn Iterator<Item = (&dyn PartialReflect, &dyn PartialReflect)> + '_> {
39+
Box::new(
40+
self.iter()
41+
.map(|(k, v)| (k as &dyn PartialReflect, v as &dyn PartialReflect)),
42+
)
5543
}
5644

5745
fn drain(&mut self) -> Vec<(Box<dyn PartialReflect>, Box<dyn PartialReflect>)> {
@@ -68,6 +56,10 @@ where
6856
result
6957
}
7058

59+
fn retain(&mut self, f: &mut dyn FnMut(&dyn PartialReflect, &mut dyn PartialReflect) -> bool) {
60+
self.retain(move |k, v| f(k, v));
61+
}
62+
7163
fn insert_boxed(
7264
&mut self,
7365
key: Box<dyn PartialReflect>,

crates/bevy_reflect/src/impls/macros/map.rs

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,12 @@ macro_rules! impl_reflect_for_hashmap {
1919
.map(|value| value as &mut dyn $crate::reflect::PartialReflect)
2020
}
2121

22-
fn get_at(&self, index: usize) -> Option<(&dyn $crate::reflect::PartialReflect, &dyn $crate::reflect::PartialReflect)> {
23-
self.iter()
24-
.nth(index)
25-
.map(|(key, value)| (key as &dyn $crate::reflect::PartialReflect, value as &dyn $crate::reflect::PartialReflect))
26-
}
27-
28-
fn get_at_mut(
29-
&mut self,
30-
index: usize,
31-
) -> Option<(&dyn $crate::reflect::PartialReflect, &mut dyn $crate::reflect::PartialReflect)> {
32-
self.iter_mut().nth(index).map(|(key, value)| {
33-
(key as &dyn $crate::reflect::PartialReflect, value as &mut dyn $crate::reflect::PartialReflect)
34-
})
35-
}
36-
3722
fn len(&self) -> usize {
3823
Self::len(self)
3924
}
4025

41-
fn iter(&self) -> $crate::map::MapIter {
42-
$crate::map::MapIter::new(self)
26+
fn iter(&self) -> bevy_platform::prelude::Box<dyn Iterator<Item = (&dyn $crate::reflect::PartialReflect, &dyn $crate::reflect::PartialReflect)> + '_> {
27+
bevy_platform::prelude::Box::new(self.iter().map(|(k, v)| (k as &dyn $crate::reflect::PartialReflect, v as &dyn $crate::reflect::PartialReflect)))
4328
}
4429

4530
fn drain(&mut self) -> bevy_platform::prelude::Vec<(bevy_platform::prelude::Box<dyn $crate::reflect::PartialReflect>, bevy_platform::prelude::Box<dyn $crate::reflect::PartialReflect>)> {
@@ -53,6 +38,10 @@ macro_rules! impl_reflect_for_hashmap {
5338
.collect()
5439
}
5540

41+
fn retain(&mut self, f: &mut dyn FnMut(&dyn $crate::reflect::PartialReflect, &mut dyn $crate::reflect::PartialReflect) -> bool) {
42+
self.retain(move |key, value| f(key, value));
43+
}
44+
5645
fn to_dynamic_map(&self) -> $crate::map::DynamicMap {
5746
let mut dynamic_map = $crate::map::DynamicMap::default();
5847
dynamic_map.set_represented_type($crate::reflect::PartialReflect::get_represented_type_info(self));

crates/bevy_reflect/src/impls/macros/set.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ macro_rules! impl_reflect_for_hashset {
2828
.collect()
2929
}
3030

31+
fn retain(&mut self, f: &mut dyn FnMut(&dyn $crate::reflect::PartialReflect) -> bool) {
32+
self.retain(move |value| f(value));
33+
}
34+
3135
fn insert_boxed(&mut self, value: bevy_platform::prelude::Box<dyn $crate::reflect::PartialReflect>) -> bool {
3236
let value = V::take_from_reflect(value).unwrap_or_else(|value| {
3337
panic!(

crates/bevy_reflect/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1583,7 +1583,6 @@ mod tests {
15831583
foo.apply(&foo_patch);
15841584

15851585
let mut hash_map = <HashMap<_, _>>::default();
1586-
hash_map.insert(1, 1);
15871586
hash_map.insert(2, 3);
15881587
hash_map.insert(3, 4);
15891588

0 commit comments

Comments
 (0)