feat: improve initialize_bundle error message (#7464)

# Objective

This PR improves message that caused by duplicate components in bundle.

## Solution

Show names of duplicate components.

The solution is not very elegant, in my opinion, I will be happy to listen to suggestions for improving it

Co-authored-by: Саня Череп <41489405+SDesya74@users.noreply.github.com>
This commit is contained in:
Саня Череп 2023-02-15 22:56:22 +00:00
parent 670c4c1852
commit e392e99f7e

View file

@ -3,6 +3,7 @@
//! This module contains the [`Bundle`] trait and some other helper types.
pub use bevy_ecs_macros::Bundle;
use bevy_utils::HashSet;
use crate::{
archetype::{
@ -710,7 +711,7 @@ impl Bundles {
let id = BundleId(bundle_infos.len());
let bundle_info =
// SAFETY: T::component_id ensures info was created
unsafe { initialize_bundle(std::any::type_name::<T>(), component_ids, id) };
unsafe { initialize_bundle(std::any::type_name::<T>(), components, component_ids, id) };
bundle_infos.push(bundle_info);
id
});
@ -724,16 +725,35 @@ impl Bundles {
/// `component_id` must be valid [`ComponentId`]'s
unsafe fn initialize_bundle(
bundle_type_name: &'static str,
components: &Components,
component_ids: Vec<ComponentId>,
id: BundleId,
) -> BundleInfo {
let mut deduped = component_ids.clone();
deduped.sort();
deduped.dedup();
assert!(
deduped.len() == component_ids.len(),
"Bundle {bundle_type_name} has duplicate components",
);
if deduped.len() != component_ids.len() {
// TODO: Replace with `Vec::partition_dedup` once https://github.com/rust-lang/rust/issues/54279 is stabilized
let mut seen = HashSet::new();
let mut dups = Vec::new();
for id in component_ids {
if !seen.insert(id) {
dups.push(id);
}
}
let names = dups
.into_iter()
.map(|id| {
// SAFETY: component_id exists and is therefore valid
unsafe { components.get_info_unchecked(id).name() }
})
.collect::<Vec<_>>()
.join(", ");
panic!("Bundle {bundle_type_name} has duplicate components: {names}");
}
BundleInfo { id, component_ids }
}