bevy_ecs/query/
error.rs

1use derive_more::derive::{Display, Error};
2
3use crate::{entity::Entity, world::unsafe_world_cell::UnsafeWorldCell};
4
5/// An error that occurs when retrieving a specific [`Entity`]'s query result from [`Query`](crate::system::Query) or [`QueryState`](crate::query::QueryState).
6// TODO: return the type_name as part of this error
7#[derive(Clone, Copy)]
8pub enum QueryEntityError<'w> {
9    /// The given [`Entity`]'s components do not match the query.
10    ///
11    /// Either it does not have a requested component, or it has a component which the query filters out.
12    QueryDoesNotMatch(Entity, UnsafeWorldCell<'w>),
13    /// The given [`Entity`] does not exist.
14    NoSuchEntity(Entity),
15    /// The [`Entity`] was requested mutably more than once.
16    ///
17    /// See [`QueryState::get_many_mut`](crate::query::QueryState::get_many_mut) for an example.
18    AliasedMutability(Entity),
19}
20
21impl<'w> core::error::Error for QueryEntityError<'w> {}
22
23impl<'w> core::fmt::Display for QueryEntityError<'w> {
24    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
25        match *self {
26            Self::QueryDoesNotMatch(entity, world) => {
27                write!(
28                    f,
29                    "The query does not match the entity {entity}, which has components "
30                )?;
31                format_archetype(f, world, entity)
32            }
33            Self::NoSuchEntity(entity) => write!(f, "The entity {entity} does not exist"),
34            Self::AliasedMutability(entity) => write!(
35                f,
36                "The entity {entity} was requested mutably more than once"
37            ),
38        }
39    }
40}
41
42impl<'w> core::fmt::Debug for QueryEntityError<'w> {
43    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
44        match *self {
45            Self::QueryDoesNotMatch(entity, world) => {
46                write!(f, "QueryDoesNotMatch({entity} with components ")?;
47                format_archetype(f, world, entity)?;
48                write!(f, ")")
49            }
50            Self::NoSuchEntity(entity) => write!(f, "NoSuchEntity({entity})"),
51            Self::AliasedMutability(entity) => write!(f, "AliasedMutability({entity})"),
52        }
53    }
54}
55
56fn format_archetype(
57    f: &mut core::fmt::Formatter<'_>,
58    world: UnsafeWorldCell<'_>,
59    entity: Entity,
60) -> core::fmt::Result {
61    // We know entity is still alive
62    let entity = world
63        .get_entity(entity)
64        .expect("entity does not belong to world");
65    for (i, component_id) in entity.archetype().components().enumerate() {
66        if i > 0 {
67            write!(f, ", ")?;
68        }
69        let name = world
70            .components()
71            .get_name(component_id)
72            .expect("entity does not belong to world");
73        write!(f, "{}", disqualified::ShortName(name))?;
74    }
75    Ok(())
76}
77
78impl<'w> PartialEq for QueryEntityError<'w> {
79    fn eq(&self, other: &Self) -> bool {
80        match (self, other) {
81            (Self::QueryDoesNotMatch(e1, _), Self::QueryDoesNotMatch(e2, _)) if e1 == e2 => true,
82            (Self::NoSuchEntity(e1), Self::NoSuchEntity(e2)) if e1 == e2 => true,
83            (Self::AliasedMutability(e1), Self::AliasedMutability(e2)) if e1 == e2 => true,
84            _ => false,
85        }
86    }
87}
88
89impl<'w> Eq for QueryEntityError<'w> {}
90
91/// An error that occurs when evaluating a [`Query`](crate::system::Query) or [`QueryState`](crate::query::QueryState) as a single expected result via
92/// [`get_single`](crate::system::Query::get_single) or [`get_single_mut`](crate::system::Query::get_single_mut).
93#[derive(Debug, Error, Display)]
94pub enum QuerySingleError {
95    /// No entity fits the query.
96    #[display("No entities fit the query {_0}")]
97    #[error(ignore)]
98    NoEntities(&'static str),
99    /// Multiple entities fit the query.
100    #[display("Multiple entities fit the query {_0}")]
101    #[error(ignore)]
102    MultipleEntities(&'static str),
103}
104
105#[cfg(test)]
106mod test {
107    use crate as bevy_ecs;
108    use crate::prelude::World;
109    use bevy_ecs_macros::Component;
110
111    #[test]
112    fn query_does_not_match() {
113        let mut world = World::new();
114
115        #[derive(Component)]
116        struct Present1;
117        #[derive(Component)]
118        struct Present2;
119        #[derive(Component, Debug)]
120        struct NotPresent;
121
122        let entity = world.spawn((Present1, Present2)).id();
123
124        let err = world
125            .query::<&NotPresent>()
126            .get(&world, entity)
127            .unwrap_err();
128
129        assert_eq!(
130            format!("{err:?}"),
131            "QueryDoesNotMatch(0v1 with components Present1, Present2)"
132        );
133    }
134}