diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index 7fa43e3308..072eec311d 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -71,8 +71,8 @@ where ListIter::new(self) } - fn drain(self: Box) -> Vec> { - self.into_iter() + fn drain(&mut self) -> Vec> { + self.drain(..) .map(|value| Box::new(value) as Box) .collect() } diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index dba41e003f..74791e7b22 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -442,8 +442,8 @@ macro_rules! impl_reflect_for_veclike { } #[inline] - fn drain(self: Box) -> Vec> { - self.into_iter() + fn drain(&mut self) -> Vec> { + self.drain(..) .map(|value| Box::new(value) as Box) .collect() } @@ -619,8 +619,8 @@ macro_rules! impl_reflect_for_hashmap { MapIter::new(self) } - fn drain(self: Box) -> Vec<(Box, Box)> { - self.into_iter() + fn drain(&mut self) -> Vec<(Box, Box)> { + self.drain() .map(|(key, value)| { ( Box::new(key) as Box, @@ -856,8 +856,8 @@ macro_rules! impl_reflect_for_hashset { Box::new(iter) } - fn drain(self: Box) -> Vec> { - self.into_iter() + fn drain(&mut self) -> Vec> { + self.drain() .map(|value| Box::new(value) as Box) .collect() } @@ -1092,15 +1092,18 @@ where MapIter::new(self) } - fn drain(self: Box) -> Vec<(Box, Box)> { - self.into_iter() - .map(|(key, value)| { - ( - Box::new(key) as Box, - Box::new(value) as Box, - ) - }) - .collect() + fn drain(&mut self) -> Vec<(Box, Box)> { + // BTreeMap doesn't have a `drain` function. See + // https://github.com/rust-lang/rust/issues/81074. So we have to fake one by popping + // elements off one at a time. + let mut result = Vec::with_capacity(self.len()); + while let Some((k, v)) = self.pop_first() { + result.push(( + Box::new(k) as Box, + Box::new(v) as Box, + )); + } + result } fn clone_dynamic(&self) -> DynamicMap { @@ -1686,12 +1689,10 @@ impl List ListIter::new(self) } - fn drain(self: Box) -> Vec> { - // into_owned() is not unnecessary here because it avoids cloning whenever you have a Cow::Owned already - #[allow(clippy::unnecessary_to_owned)] - self.into_owned() - .into_iter() - .map(|value| value.clone_value()) + fn drain(&mut self) -> Vec> { + self.to_mut() + .drain(..) + .map(|value| Box::new(value) as Box) .collect() } } diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 021971a33a..033459917f 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1460,7 +1460,7 @@ mod tests { assert!(fields[0].reflect_partial_eq(&123_i32).unwrap_or_default()); assert!(fields[1].reflect_partial_eq(&321_i32).unwrap_or_default()); - let list_value: Box = Box::new(vec![123_i32, 321_i32]); + let mut list_value: Box = Box::new(vec![123_i32, 321_i32]); let fields = list_value.drain(); assert!(fields[0].reflect_partial_eq(&123_i32).unwrap_or_default()); assert!(fields[1].reflect_partial_eq(&321_i32).unwrap_or_default()); @@ -1470,7 +1470,7 @@ mod tests { assert!(fields[0].reflect_partial_eq(&123_i32).unwrap_or_default()); assert!(fields[1].reflect_partial_eq(&321_i32).unwrap_or_default()); - let map_value: Box = Box::new(HashMap::from([(123_i32, 321_i32)])); + let mut map_value: Box = Box::new(HashMap::from([(123_i32, 321_i32)])); let fields = map_value.drain(); assert!(fields[0].0.reflect_partial_eq(&123_i32).unwrap_or_default()); assert!(fields[0].1.reflect_partial_eq(&321_i32).unwrap_or_default()); diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 3844605b0b..c4cffc6650 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -96,7 +96,10 @@ pub trait List: PartialReflect { fn iter(&self) -> ListIter; /// Drain the elements of this list to get a vector of owned values. - fn drain(self: Box) -> Vec>; + /// + /// After calling this function, `self` will be empty. The order of items in the returned + /// [`Vec`] will match the order of items in `self`. + fn drain(&mut self) -> Vec>; /// Clones the list, producing a [`DynamicList`]. fn clone_dynamic(&self) -> DynamicList { @@ -229,8 +232,8 @@ impl List for DynamicList { ListIter::new(self) } - fn drain(self: Box) -> Vec> { - self.values + fn drain(&mut self) -> Vec> { + self.values.drain(..).collect() } fn clone_dynamic(&self) -> DynamicList { diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index ee6fab4ff0..887c92e24e 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -75,7 +75,9 @@ pub trait Map: PartialReflect { fn iter(&self) -> MapIter; /// Drain the key-value pairs of this map to get a vector of owned values. - fn drain(self: Box) -> Vec<(Box, Box)>; + /// + /// After calling this function, `self` will be empty. + fn drain(&mut self) -> Vec<(Box, Box)>; /// Clones the map, producing a [`DynamicMap`]. fn clone_dynamic(&self) -> DynamicMap; @@ -286,8 +288,8 @@ impl Map for DynamicMap { MapIter::new(self) } - fn drain(self: Box) -> Vec<(Box, Box)> { - self.values + fn drain(&mut self) -> Vec<(Box, Box)> { + self.values.drain(..).collect() } fn clone_dynamic(&self) -> DynamicMap { diff --git a/crates/bevy_reflect/src/set.rs b/crates/bevy_reflect/src/set.rs index f15730071a..a52181878e 100644 --- a/crates/bevy_reflect/src/set.rs +++ b/crates/bevy_reflect/src/set.rs @@ -61,7 +61,9 @@ pub trait Set: PartialReflect { fn iter(&self) -> Box + '_>; /// Drain the values of this set to get a vector of owned values. - fn drain(self: Box) -> Vec>; + /// + /// After calling this function, `self` will be empty. + fn drain(&mut self) -> Vec>; /// Clones the set, producing a [`DynamicSet`]. fn clone_dynamic(&self) -> DynamicSet; @@ -187,8 +189,8 @@ impl Set for DynamicSet { Box::new(iter) } - fn drain(self: Box) -> Vec> { - self.hash_table.into_iter().collect::>() + fn drain(&mut self) -> Vec> { + self.hash_table.drain().collect::>() } fn clone_dynamic(&self) -> DynamicSet {