Skip to main content

bevy_ecs/query/
access_iter.rs

1use core::fmt::Display;
2
3use crate::{
4    component::{ComponentId, Components},
5    query::{Access, QueryData},
6};
7use bevy_utils::BloomFilter;
8
9// found by benchmarking
10// too low, and smaller queries do unnecessary work
11// maintaining the bloom filter for a handful of checks
12// too high, and the benefit of a simpler loop
13// is outweighed by the n^2 check
14const USE_FILTER_THRESHOLD: usize = 4;
15
16/// Check if `Q` has any internal conflicts.
17#[inline(never)]
18pub fn has_conflicts<Q: QueryData>(components: &Components) -> Result<(), QueryAccessError> {
19    let Some(state) = Q::get_state(components) else {
20        return Err(QueryAccessError::ComponentNotRegistered);
21    };
22
23    let result = if let Some(size) = Q::iter_access(&state).size_hint().1
24        && size <= USE_FILTER_THRESHOLD
25    {
26        has_conflicts_small::<Q>(&state)
27    } else {
28        has_conflicts_large::<Q>(&state)
29    };
30    if let Err(e) = result {
31        { ::core::panicking::panic_fmt(format_args!("{0}", e)); };panic!("{e}");
32    }
33
34    Ok(())
35}
36
37/// Check if `Q` has any internal conflicts by checking all pairs of accesses.
38///
39/// This is intended for queries with fewer components than [`USE_FILTER_THRESHOLD`].
40/// Split from [`has_conflicts`] for easier testing.
41fn has_conflicts_small<'a, Q: QueryData>(
42    state: &'a Q::State,
43) -> Result<(), AccessConflictError<'a>> {
44    // we can optimize small sizes by caching the iteration result in an array on the stack
45    let mut inner_access = [EcsAccessType::Empty; USE_FILTER_THRESHOLD];
46    for (i, access) in Q::iter_access(state).enumerate() {
47        for access_other in inner_access.iter().take(i) {
48            if access.is_compatible(*access_other).is_err() {
49                return Err(AccessConflictError(access, *access_other));
50            }
51        }
52        inner_access[i] = access;
53    }
54
55    Ok(())
56}
57
58/// Check if `Q` has any internal conflicts using a bloom filter for efficiency.
59///
60/// This is intended for queries with more components than [`USE_FILTER_THRESHOLD`].
61/// Split from [`has_conflicts`] for easier testing.
62fn has_conflicts_large<'a, Q: QueryData>(
63    state: &'a Q::State,
64) -> Result<(), AccessConflictError<'a>> {
65    // use a bloom filter as a linear time check if we need to run the longer, exact check
66    let mut filter = BloomFilter::<8, 2>::new();
67    for (i, access) in Q::iter_access(state).enumerate() {
68        let needs_check = match access {
69            EcsAccessType::Component(EcsAccessLevel::Read(component_id))
70            | EcsAccessType::Component(EcsAccessLevel::Write(component_id)) => {
71                filter.check_insert(&component_id.index())
72            }
73            EcsAccessType::Component(EcsAccessLevel::ReadAll)
74            | EcsAccessType::Component(EcsAccessLevel::WriteAll) => true,
75            EcsAccessType::Access(access) => {
76                if let Ok(component_iter) = access.try_iter_access() {
77                    let mut needs_check = false;
78                    for kind in component_iter {
79                        let index = match kind {
80                            crate::query::ComponentAccessKind::Shared(id)
81                            | crate::query::ComponentAccessKind::Exclusive(id)
82                            | crate::query::ComponentAccessKind::Archetypal(id) => id.index(),
83                        };
84                        if filter.check_insert(&index) {
85                            needs_check = true;
86                        }
87                    }
88                    needs_check
89                } else {
90                    true
91                }
92            }
93            EcsAccessType::Empty => continue,
94        };
95        if needs_check {
96            // we MIGHT have a conflict, fallback to slow check
97            for (j, access_other) in Q::iter_access(state).enumerate() {
98                if i == j {
99                    continue;
100                }
101                if access.is_compatible(access_other).is_err() {
102                    return Err(AccessConflictError(access, access_other));
103                }
104            }
105        }
106    }
107    Ok(())
108}
109
110/// The data storage type that is being accessed.
111#[derive(#[automatically_derived]
impl<'a> ::core::marker::Copy for EcsAccessType<'a> { }Copy, #[automatically_derived]
impl<'a> ::core::clone::Clone for EcsAccessType<'a> {
    #[inline]
    fn clone(&self) -> EcsAccessType<'a> {
        let _: ::core::clone::AssertParamIsClone<EcsAccessLevel>;
        let _: ::core::clone::AssertParamIsClone<&'a Access>;
        *self
    }
}Clone, #[automatically_derived]
impl<'a> ::core::fmt::Debug for EcsAccessType<'a> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            EcsAccessType::Component(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Component", &__self_0),
            EcsAccessType::Access(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Access",
                    &__self_0),
            EcsAccessType::Empty =>
                ::core::fmt::Formatter::write_str(f, "Empty"),
        }
    }
}Debug, #[automatically_derived]
impl<'a> ::core::cmp::PartialEq for EcsAccessType<'a> {
    #[inline]
    fn eq(&self, other: &EcsAccessType<'a>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (EcsAccessType::Component(__self_0),
                    EcsAccessType::Component(__arg1_0)) => __self_0 == __arg1_0,
                (EcsAccessType::Access(__self_0),
                    EcsAccessType::Access(__arg1_0)) => __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl<'a> ::core::hash::Hash for EcsAccessType<'a> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            EcsAccessType::Component(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            EcsAccessType::Access(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash)]
112pub enum EcsAccessType<'a> {
113    /// Accesses [`Component`](crate::prelude::Component) data
114    Component(EcsAccessLevel),
115    /// borrowed access from [`WorldQuery::State`](crate::query::WorldQuery)
116    Access(&'a Access),
117    /// Does not access any data that can conflict.
118    Empty,
119}
120
121impl<'a> EcsAccessType<'a> {
122    /// Returns `Ok(())` if `self` and `other` are compatible. Returns a [`AccessConflictError`] otherwise.
123    #[inline(never)]
124    pub fn is_compatible(&self, other: Self) -> Result<(), AccessConflictError<'_>> {
125        use EcsAccessLevel::*;
126        use EcsAccessType::*;
127
128        match (*self, other) {
129            (Component(ReadAll), Component(Write(_)))
130            | (Component(Write(_)), Component(ReadAll))
131            | (Component(_), Component(WriteAll))
132            | (Component(WriteAll), Component(_)) => Err(AccessConflictError(*self, other)),
133
134            (Empty, _)
135            | (_, Empty)
136            // read only access doesn't conflict
137            | (Component(Read(_)), Component(Read(_)))
138            | (Component(ReadAll), Component(Read(_)))
139            | (Component(Read(_)), Component(ReadAll))
140            | (Component(ReadAll), Component(ReadAll))
141             => {
142                Ok(())
143            }
144
145            (Component(Read(id)), Component(Write(id_other)))
146            | (Component(Write(id)), Component(Read(id_other)))
147            | (Component(Write(id)), Component(Write(id_other)))
148 => if id == id_other {
149                Err(AccessConflictError(*self, other))
150            } else {
151                Ok(())
152            },
153
154            // Borrowed Access
155            (Component(Read(component_id)), Access(access))
156            | (Access(access), Component(Read(component_id))) => if access.has_write(component_id) {
157                Err(AccessConflictError(*self, other))
158            } else {
159                Ok(())
160            },
161
162            (Component(Write(component_id)), Access(access))
163            | (Access(access), Component(Write(component_id))) => if access.has_read(component_id) {
164                Err(AccessConflictError(*self, other))
165            } else {
166                Ok(())
167            },
168
169            (Component(ReadAll), Access(access))
170            | (Access(access), Component(ReadAll)) => if access.has_any_write() {
171                Err(AccessConflictError(*self, other))
172            } else {
173                Ok(())
174            },
175
176            (Component(WriteAll), Access(access))
177            | (Access(access), Component(WriteAll))=> if access.has_any_read() {
178                Err(AccessConflictError(*self, other))
179            } else {
180                Ok(())
181            },
182
183            (Access(access), Access(other_access)) => if access.is_compatible(other_access) {
184                Ok(())
185            } else {
186                Err(AccessConflictError(*self, other))
187            },
188        }
189    }
190}
191
192/// The way the data will be accessed and whether we take access on all the components on
193/// an entity or just one component.
194#[derive(#[automatically_derived]
impl ::core::clone::Clone for EcsAccessLevel {
    #[inline]
    fn clone(&self) -> EcsAccessLevel {
        let _: ::core::clone::AssertParamIsClone<ComponentId>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for EcsAccessLevel { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for EcsAccessLevel {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            EcsAccessLevel::Read(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Read",
                    &__self_0),
            EcsAccessLevel::Write(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Write",
                    &__self_0),
            EcsAccessLevel::ReadAll =>
                ::core::fmt::Formatter::write_str(f, "ReadAll"),
            EcsAccessLevel::WriteAll =>
                ::core::fmt::Formatter::write_str(f, "WriteAll"),
        }
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for EcsAccessLevel {
    #[inline]
    fn eq(&self, other: &EcsAccessLevel) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (EcsAccessLevel::Read(__self_0),
                    EcsAccessLevel::Read(__arg1_0)) => __self_0 == __arg1_0,
                (EcsAccessLevel::Write(__self_0),
                    EcsAccessLevel::Write(__arg1_0)) => __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for EcsAccessLevel {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            EcsAccessLevel::Read(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            EcsAccessLevel::Write(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash)]
195pub enum EcsAccessLevel {
196    /// Reads [`Component`](crate::prelude::Component) with [`ComponentId`]
197    Read(ComponentId),
198    /// Writes [`Component`](crate::prelude::Component) with [`ComponentId`]
199    Write(ComponentId),
200    /// Potentially reads all [`Component`](crate::prelude::Component)'s in the [`World`](crate::prelude::World)
201    ReadAll,
202    /// Potentially writes all [`Component`](crate::prelude::Component)'s in the [`World`](crate::prelude::World)
203    WriteAll,
204}
205
206/// Error returned from [`EcsAccessType::is_compatible`]
207pub struct AccessConflictError<'a>(EcsAccessType<'a>, EcsAccessType<'a>);
208
209impl Display for AccessConflictError<'_> {
210    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
211        use EcsAccessLevel::*;
212        use EcsAccessType::*;
213
214        let AccessConflictError(a, b) = self;
215        match (a, b) {
216            // ReadAll/WriteAll + Component conflicts
217            (Component(ReadAll), Component(Write(id)))
218            | (Component(Write(id)), Component(ReadAll)) => {
219                f.write_fmt(format_args!("Component read all access conflicts with component {0:?} write.",
        id))write!(
220                    f,
221                    "Component read all access conflicts with component {id:?} write."
222                )
223            }
224            (Component(WriteAll), Component(Write(id)))
225            | (Component(Write(id)), Component(WriteAll)) => {
226                f.write_fmt(format_args!("Component write all access conflicts with component {0:?} write.",
        id))write!(
227                    f,
228                    "Component write all access conflicts with component {id:?} write."
229                )
230            }
231            (Component(WriteAll), Component(Read(id)))
232            | (Component(Read(id)), Component(WriteAll)) => {
233                f.write_fmt(format_args!("Component write all access conflicts with component {0:?} read.",
        id))write!(
234                    f,
235                    "Component write all access conflicts with component {id:?} read."
236                )
237            }
238            (Component(WriteAll), Component(ReadAll))
239            | (Component(ReadAll), Component(WriteAll)) => {
240                f.write_fmt(format_args!("Component write all conflicts with component read all."))write!(f, "Component write all conflicts with component read all.")
241            }
242            (Component(WriteAll), Component(WriteAll)) => {
243                f.write_fmt(format_args!("Component write all conflicts with component write all."))write!(f, "Component write all conflicts with component write all.")
244            }
245
246            // Component + Component conflicts
247            (Component(Read(id)), Component(Write(id_other)))
248            | (Component(Write(id_other)), Component(Read(id))) => f.write_fmt(format_args!("Component {0:?} read conflicts with component {1:?} write.",
        id, id_other))write!(
249                f,
250                "Component {id:?} read conflicts with component {id_other:?} write."
251            ),
252            (Component(Write(id)), Component(Write(id_other))) => f.write_fmt(format_args!("Component {0:?} write conflicts with component {1:?} write.",
        id, id_other))write!(
253                f,
254                "Component {id:?} write conflicts with component {id_other:?} write."
255            ),
256
257            // Borrowed Access conflicts
258            (Access(_), Component(Read(id))) | (Component(Read(id)), Access(_)) => f.write_fmt(format_args!("Access has a write that conflicts with component {0:?} read.",
        id))write!(
259                f,
260                "Access has a write that conflicts with component {id:?} read."
261            ),
262            (Access(_), Component(Write(id))) | (Component(Write(id)), Access(_)) => f.write_fmt(format_args!("Access has a read that conflicts with component {0:?} write.",
        id))write!(
263                f,
264                "Access has a read that conflicts with component {id:?} write."
265            ),
266            (Access(_), Component(ReadAll)) | (Component(ReadAll), Access(_)) => f.write_fmt(format_args!("Access has a write that conflicts with component read all"))write!(
267                f,
268                "Access has a write that conflicts with component read all"
269            ),
270            (Access(_), Component(WriteAll)) | (Component(WriteAll), Access(_)) => f.write_fmt(format_args!("Access has a read that conflicts with component write all"))write!(
271                f,
272                "Access has a read that conflicts with component write all"
273            ),
274            (Access(_), Access(_)) => f.write_fmt(format_args!("Access conflicts with other Access"))write!(f, "Access conflicts with other Access"),
275
276            _ => {
277                {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("Other accesses should be compatible")));
};unreachable!("Other accesses should be compatible");
278            }
279        }
280    }
281}
282
283/// Error returned from [`has_conflicts`].
284#[derive(#[automatically_derived]
impl ::core::clone::Clone for QueryAccessError {
    #[inline]
    fn clone(&self) -> QueryAccessError { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for QueryAccessError { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for QueryAccessError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                QueryAccessError::ComponentNotRegistered =>
                    "ComponentNotRegistered",
                QueryAccessError::EntityDoesNotMatch => "EntityDoesNotMatch",
            })
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for QueryAccessError {
    #[inline]
    fn eq(&self, other: &QueryAccessError) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq)]
285pub enum QueryAccessError {
286    /// Component was not registered on world
287    ComponentNotRegistered,
288    /// Entity did not have the requested components
289    EntityDoesNotMatch,
290}
291
292impl core::error::Error for QueryAccessError {}
293
294impl Display for QueryAccessError {
295    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
296        match *self {
297            QueryAccessError::ComponentNotRegistered => {
298                f.write_fmt(format_args!("At least one component in Q was not registered in world.\n                    Consider calling `World::register_component`"))write!(
299                    f,
300                    "At least one component in Q was not registered in world.
301                    Consider calling `World::register_component`"
302                )
303            }
304            QueryAccessError::EntityDoesNotMatch => {
305                f.write_fmt(format_args!("Entity does not match Q"))write!(f, "Entity does not match Q")
306            }
307        }
308    }
309}
310
311#[cfg(test)]
312mod tests {
313    use super::*;
314    use crate::{
315        prelude::Component,
316        query::WorldQuery,
317        world::{EntityMut, EntityMutExcept, EntityRef, EntityRefExcept, World},
318    };
319
320    #[derive(Component)]
321    struct C1;
322
323    #[derive(Component)]
324    struct C2;
325
326    fn setup_world() -> World {
327        let world = World::new();
328        let mut world = world;
329        world.register_component::<C1>();
330        world.register_component::<C2>();
331        world
332    }
333
334    #[test]
335    fn simple_compatible() {
336        let world = setup_world();
337        let c = world.components();
338
339        // Compatible
340        let state = <&mut C1 as WorldQuery>::get_state(c).unwrap();
341        assert!(has_conflicts_small::<&mut C1>(&state).is_ok());
342        assert!(has_conflicts_large::<&mut C1>(&state).is_ok());
343        assert!(has_conflicts::<&mut C1>(c).is_ok());
344
345        let state = <&C1 as WorldQuery>::get_state(c).unwrap();
346        assert!(has_conflicts_small::<&C1>(&state).is_ok());
347        assert!(has_conflicts_large::<&C1>(&state).is_ok());
348        assert!(has_conflicts::<&C1>(c).is_ok());
349
350        let state = <(&C1, &C1) as WorldQuery>::get_state(c).unwrap();
351        assert!(has_conflicts_small::<(&C1, &C1)>(&state).is_ok());
352        assert!(has_conflicts_large::<(&C1, &C1)>(&state).is_ok());
353        assert!(has_conflicts::<(&C1, &C1)>(c).is_ok());
354    }
355
356    #[test]
357    #[should_panic(expected = "conflicts")]
358    fn conflict_component_read_conflicts_write() {
359        let world = setup_world();
360        let c = world.components();
361        let state = <(&C1, &mut C1) as WorldQuery>::get_state(c).unwrap();
362        assert!(has_conflicts_small::<(&C1, &mut C1)>(&state).is_err());
363        assert!(has_conflicts_large::<(&C1, &mut C1)>(&state).is_err());
364        let _ = has_conflicts::<(&C1, &mut C1)>(c);
365    }
366
367    #[test]
368    #[should_panic(expected = "conflicts")]
369    fn conflict_component_write_conflicts_read() {
370        let world = setup_world();
371        let c = world.components();
372        let state = <(&mut C1, &C1) as WorldQuery>::get_state(c).unwrap();
373        assert!(has_conflicts_small::<(&mut C1, &C1)>(&state).is_err());
374        assert!(has_conflicts_large::<(&mut C1, &C1)>(&state).is_err());
375        let _ = has_conflicts::<(&mut C1, &C1)>(c);
376    }
377
378    #[test]
379    #[should_panic(expected = "conflicts")]
380    fn conflict_component_write_conflicts_write() {
381        let world = setup_world();
382        let c = world.components();
383        let state = <(&mut C1, &mut C1) as WorldQuery>::get_state(c).unwrap();
384        assert!(has_conflicts_small::<(&mut C1, &mut C1)>(&state).is_err());
385        assert!(has_conflicts_large::<(&mut C1, &mut C1)>(&state).is_err());
386        let _ = has_conflicts::<(&mut C1, &mut C1)>(c);
387    }
388
389    #[test]
390    fn entity_ref_compatible() {
391        let world = setup_world();
392        let c = world.components();
393
394        // Compatible
395        let state = <(EntityRef, &C1) as WorldQuery>::get_state(c).unwrap();
396        assert!(has_conflicts_small::<(EntityRef, &C1)>(&state).is_ok());
397        assert!(has_conflicts_large::<(EntityRef, &C1)>(&state).is_ok());
398        assert!(has_conflicts::<(EntityRef, &C1)>(c).is_ok());
399
400        let state = <(&C1, EntityRef) as WorldQuery>::get_state(c).unwrap();
401        assert!(has_conflicts_small::<(&C1, EntityRef)>(&state).is_ok());
402        assert!(has_conflicts_large::<(&C1, EntityRef)>(&state).is_ok());
403        assert!(has_conflicts::<(&C1, EntityRef)>(c).is_ok());
404
405        let state = <(EntityRef, EntityRef) as WorldQuery>::get_state(c).unwrap();
406        assert!(has_conflicts_small::<(EntityRef, EntityRef)>(&state).is_ok());
407        assert!(has_conflicts_large::<(EntityRef, EntityRef)>(&state).is_ok());
408        assert!(has_conflicts::<(EntityRef, EntityRef)>(c).is_ok());
409    }
410
411    #[test]
412    #[should_panic(expected = "conflicts")]
413    fn entity_ref_conflicts_component_write() {
414        let world = setup_world();
415        let c = world.components();
416        let state = <(EntityRef, &mut C1) as WorldQuery>::get_state(c).unwrap();
417        assert!(has_conflicts_small::<(EntityRef, &mut C1)>(&state).is_err());
418        assert!(has_conflicts_large::<(EntityRef, &mut C1)>(&state).is_err());
419        let _ = has_conflicts::<(EntityRef, &mut C1)>(c);
420    }
421
422    #[test]
423    #[should_panic(expected = "conflicts")]
424    fn component_write_conflicts_entity_ref() {
425        let world = setup_world();
426        let c = world.components();
427        let state = <(&mut C1, EntityRef) as WorldQuery>::get_state(c).unwrap();
428        assert!(has_conflicts_small::<(&mut C1, EntityRef)>(&state).is_err());
429        assert!(has_conflicts_large::<(&mut C1, EntityRef)>(&state).is_err());
430        let _ = has_conflicts::<(&mut C1, EntityRef)>(c);
431    }
432
433    #[test]
434    #[should_panic(expected = "conflicts")]
435    fn entity_mut_conflicts_component_read() {
436        let world = setup_world();
437        let c = world.components();
438        let state = <(EntityMut, &C1) as WorldQuery>::get_state(c).unwrap();
439        assert!(has_conflicts_small::<(EntityMut, &C1)>(&state).is_err());
440        assert!(has_conflicts_large::<(EntityMut, &C1)>(&state).is_err());
441        let _ = has_conflicts::<(EntityMut, &C1)>(c);
442    }
443
444    #[test]
445    #[should_panic(expected = "conflicts")]
446    fn component_read_conflicts_entity_mut() {
447        let world = setup_world();
448        let c = world.components();
449        let state = <(&C1, EntityMut) as WorldQuery>::get_state(c).unwrap();
450        assert!(has_conflicts_small::<(&C1, EntityMut)>(&state).is_err());
451        assert!(has_conflicts_large::<(&C1, EntityMut)>(&state).is_err());
452        let _ = has_conflicts::<(&C1, EntityMut)>(c);
453    }
454
455    #[test]
456    #[should_panic(expected = "conflicts")]
457    fn entity_mut_conflicts_component_write() {
458        let world = setup_world();
459        let c = world.components();
460        let state = <(EntityMut, &mut C1) as WorldQuery>::get_state(c).unwrap();
461        assert!(has_conflicts_small::<(EntityMut, &mut C1)>(&state).is_err());
462        assert!(has_conflicts_large::<(EntityMut, &mut C1)>(&state).is_err());
463        let _ = has_conflicts::<(EntityMut, &mut C1)>(c);
464    }
465
466    #[test]
467    #[should_panic(expected = "conflicts")]
468    fn component_write_conflicts_entity_mut() {
469        let world = setup_world();
470        let c = world.components();
471        let state = <(&mut C1, EntityMut) as WorldQuery>::get_state(c).unwrap();
472        assert!(has_conflicts_small::<(&mut C1, EntityMut)>(&state).is_err());
473        assert!(has_conflicts_large::<(&mut C1, EntityMut)>(&state).is_err());
474        let _ = has_conflicts::<(&mut C1, EntityMut)>(c);
475    }
476
477    #[test]
478    #[should_panic(expected = "conflicts")]
479    fn entity_mut_conflicts_entity_ref() {
480        let world = setup_world();
481        let c = world.components();
482        let state = <(EntityMut, EntityRef) as WorldQuery>::get_state(c).unwrap();
483        assert!(has_conflicts_small::<(EntityMut, EntityRef)>(&state).is_err());
484        assert!(has_conflicts_large::<(EntityMut, EntityRef)>(&state).is_err());
485        let _ = has_conflicts::<(EntityMut, EntityRef)>(c);
486    }
487
488    #[test]
489    #[should_panic(expected = "conflicts")]
490    fn entity_ref_conflicts_entity_mut() {
491        let world = setup_world();
492        let c = world.components();
493        let state = <(EntityRef, EntityMut) as WorldQuery>::get_state(c).unwrap();
494        assert!(has_conflicts_small::<(EntityRef, EntityMut)>(&state).is_err());
495        assert!(has_conflicts_large::<(EntityRef, EntityMut)>(&state).is_err());
496        let _ = has_conflicts::<(EntityRef, EntityMut)>(c);
497    }
498
499    #[test]
500    fn entity_ref_except_compatible() {
501        let world = setup_world();
502        let c = world.components();
503
504        // Compatible
505        let state = <(EntityRefExcept<C1>, &mut C1) as WorldQuery>::get_state(c).unwrap();
506        assert!(has_conflicts_small::<(EntityRefExcept<C1>, &mut C1)>(&state).is_ok());
507        assert!(has_conflicts_large::<(EntityRefExcept<C1>, &mut C1)>(&state).is_ok());
508        assert!(has_conflicts::<(EntityRefExcept<C1>, &mut C1)>(c).is_ok());
509
510        let state = <(&mut C1, EntityRefExcept<C1>) as WorldQuery>::get_state(c).unwrap();
511        assert!(has_conflicts_small::<(&mut C1, EntityRefExcept<C1>)>(&state).is_ok());
512        assert!(has_conflicts_large::<(&mut C1, EntityRefExcept<C1>)>(&state).is_ok());
513        assert!(has_conflicts::<(&mut C1, EntityRefExcept<C1>)>(c).is_ok());
514
515        let state = <(&C2, EntityRefExcept<C1>) as WorldQuery>::get_state(c).unwrap();
516        assert!(has_conflicts_small::<(&C2, EntityRefExcept<C1>)>(&state).is_ok());
517        assert!(has_conflicts_large::<(&C2, EntityRefExcept<C1>)>(&state).is_ok());
518        assert!(has_conflicts::<(&C2, EntityRefExcept<C1>)>(c).is_ok());
519
520        let state = <(&mut C1, EntityRefExcept<(C1, C2)>) as WorldQuery>::get_state(c).unwrap();
521        assert!(has_conflicts_small::<(&mut C1, EntityRefExcept<(C1, C2)>)>(&state).is_ok());
522        assert!(has_conflicts_large::<(&mut C1, EntityRefExcept<(C1, C2)>)>(&state).is_ok());
523        assert!(has_conflicts::<(&mut C1, EntityRefExcept<(C1, C2)>)>(c).is_ok());
524
525        let state = <(EntityRefExcept<(C1, C2)>, &mut C1) as WorldQuery>::get_state(c).unwrap();
526        assert!(has_conflicts_small::<(EntityRefExcept<(C1, C2)>, &mut C1)>(&state).is_ok());
527        assert!(has_conflicts_large::<(EntityRefExcept<(C1, C2)>, &mut C1)>(&state).is_ok());
528        assert!(has_conflicts::<(EntityRefExcept<(C1, C2)>, &mut C1)>(c).is_ok());
529
530        let state =
531            <(&mut C1, &mut C2, EntityRefExcept<(C1, C2)>) as WorldQuery>::get_state(c).unwrap();
532        assert!(
533            has_conflicts_small::<(&mut C1, &mut C2, EntityRefExcept<(C1, C2)>)>(&state).is_ok()
534        );
535        assert!(
536            has_conflicts_large::<(&mut C1, &mut C2, EntityRefExcept<(C1, C2)>)>(&state).is_ok()
537        );
538        assert!(has_conflicts::<(&mut C1, &mut C2, EntityRefExcept<(C1, C2)>)>(c).is_ok());
539
540        let state =
541            <(&mut C1, EntityRefExcept<(C1, C2)>, &mut C2) as WorldQuery>::get_state(c).unwrap();
542        assert!(
543            has_conflicts_small::<(&mut C1, EntityRefExcept<(C1, C2)>, &mut C2)>(&state).is_ok()
544        );
545        assert!(
546            has_conflicts_large::<(&mut C1, EntityRefExcept<(C1, C2)>, &mut C2)>(&state).is_ok()
547        );
548        assert!(has_conflicts::<(&mut C1, EntityRefExcept<(C1, C2)>, &mut C2)>(c).is_ok());
549
550        let state =
551            <(EntityRefExcept<(C1, C2)>, &mut C1, &mut C2) as WorldQuery>::get_state(c).unwrap();
552        assert!(
553            has_conflicts_small::<(EntityRefExcept<(C1, C2)>, &mut C1, &mut C2)>(&state).is_ok()
554        );
555        assert!(
556            has_conflicts_large::<(EntityRefExcept<(C1, C2)>, &mut C1, &mut C2)>(&state).is_ok()
557        );
558        assert!(has_conflicts::<(EntityRefExcept<(C1, C2)>, &mut C1, &mut C2)>(c).is_ok());
559    }
560
561    #[test]
562    #[should_panic(expected = "conflicts")]
563    fn entity_ref_except_conflicts_component_write() {
564        let world = setup_world();
565        let c = world.components();
566        let state = <(EntityRefExcept<C1>, &mut C2) as WorldQuery>::get_state(c).unwrap();
567        assert!(has_conflicts_small::<(EntityRefExcept<C1>, &mut C2)>(&state).is_err());
568        assert!(has_conflicts_large::<(EntityRefExcept<C1>, &mut C2)>(&state).is_err());
569        let _ = has_conflicts::<(EntityRefExcept<C1>, &mut C2)>(c);
570    }
571
572    #[test]
573    #[should_panic(expected = "conflicts")]
574    fn component_write_conflicts_entity_ref_except() {
575        let world = setup_world();
576        let c = world.components();
577        let state = <(&mut C2, EntityRefExcept<C1>) as WorldQuery>::get_state(c).unwrap();
578        assert!(has_conflicts_small::<(&mut C2, EntityRefExcept<C1>)>(&state).is_err());
579        assert!(has_conflicts_large::<(&mut C2, EntityRefExcept<C1>)>(&state).is_err());
580        let _ = has_conflicts::<(&mut C2, EntityRefExcept<C1>)>(c);
581    }
582
583    #[test]
584    fn entity_mut_except_compatible() {
585        let world = setup_world();
586        let c = world.components();
587
588        // Compatible
589        let state = <(EntityMutExcept<C1>, &mut C1) as WorldQuery>::get_state(c).unwrap();
590        assert!(has_conflicts_small::<(EntityMutExcept<C1>, &mut C1)>(&state).is_ok());
591        assert!(has_conflicts_large::<(EntityMutExcept<C1>, &mut C1)>(&state).is_ok());
592        assert!(has_conflicts::<(EntityMutExcept<C1>, &mut C1)>(c).is_ok());
593
594        let state = <(&mut C1, EntityMutExcept<C1>) as WorldQuery>::get_state(c).unwrap();
595        assert!(has_conflicts_small::<(&mut C1, EntityMutExcept<C1>)>(&state).is_ok());
596        assert!(has_conflicts_large::<(&mut C1, EntityMutExcept<C1>)>(&state).is_ok());
597        assert!(has_conflicts::<(&mut C1, EntityMutExcept<C1>)>(c).is_ok());
598
599        let state = <(&mut C1, EntityMutExcept<(C1, C2)>) as WorldQuery>::get_state(c).unwrap();
600        assert!(has_conflicts_small::<(&mut C1, EntityMutExcept<(C1, C2)>)>(&state).is_ok());
601        assert!(has_conflicts_large::<(&mut C1, EntityMutExcept<(C1, C2)>)>(&state).is_ok());
602        assert!(has_conflicts::<(&mut C1, EntityMutExcept<(C1, C2)>)>(c).is_ok());
603
604        let state = <(EntityMutExcept<(C1, C2)>, &mut C1) as WorldQuery>::get_state(c).unwrap();
605        assert!(has_conflicts_small::<(EntityMutExcept<(C1, C2)>, &mut C1)>(&state).is_ok());
606        assert!(has_conflicts_large::<(EntityMutExcept<(C1, C2)>, &mut C1)>(&state).is_ok());
607        assert!(has_conflicts::<(EntityMutExcept<(C1, C2)>, &mut C1)>(c).is_ok());
608
609        let state =
610            <(&mut C1, &mut C2, EntityMutExcept<(C1, C2)>) as WorldQuery>::get_state(c).unwrap();
611        assert!(
612            has_conflicts_small::<(&mut C1, &mut C2, EntityMutExcept<(C1, C2)>)>(&state).is_ok()
613        );
614        assert!(
615            has_conflicts_large::<(&mut C1, &mut C2, EntityMutExcept<(C1, C2)>)>(&state).is_ok()
616        );
617        assert!(has_conflicts::<(&mut C1, &mut C2, EntityMutExcept<(C1, C2)>)>(c).is_ok());
618
619        let state =
620            <(&mut C1, EntityMutExcept<(C1, C2)>, &mut C2) as WorldQuery>::get_state(c).unwrap();
621        assert!(
622            has_conflicts_small::<(&mut C1, EntityMutExcept<(C1, C2)>, &mut C2)>(&state).is_ok()
623        );
624        assert!(
625            has_conflicts_large::<(&mut C1, EntityMutExcept<(C1, C2)>, &mut C2)>(&state).is_ok()
626        );
627        assert!(has_conflicts::<(&mut C1, EntityMutExcept<(C1, C2)>, &mut C2)>(c).is_ok());
628
629        let state =
630            <(EntityMutExcept<(C1, C2)>, &mut C1, &mut C2) as WorldQuery>::get_state(c).unwrap();
631        assert!(
632            has_conflicts_small::<(EntityMutExcept<(C1, C2)>, &mut C1, &mut C2)>(&state).is_ok()
633        );
634        assert!(
635            has_conflicts_large::<(EntityMutExcept<(C1, C2)>, &mut C1, &mut C2)>(&state).is_ok()
636        );
637        assert!(has_conflicts::<(EntityMutExcept<(C1, C2)>, &mut C1, &mut C2)>(c).is_ok());
638    }
639
640    #[test]
641    #[should_panic(expected = "conflicts")]
642    fn entity_mut_except_conflicts_component_read() {
643        let world = setup_world();
644        let c = world.components();
645        let state = <(EntityMutExcept<C1>, &C2) as WorldQuery>::get_state(c).unwrap();
646        assert!(has_conflicts_small::<(EntityMutExcept<C1>, &C2)>(&state).is_err());
647        assert!(has_conflicts_large::<(EntityMutExcept<C1>, &C2)>(&state).is_err());
648        let _ = has_conflicts::<(EntityMutExcept<C1>, &C2)>(c);
649    }
650
651    #[test]
652    #[should_panic(expected = "conflicts")]
653    fn component_read_conflicts_entity_mut_except() {
654        let world = setup_world();
655        let c = world.components();
656        let state = <(&C2, EntityMutExcept<C1>) as WorldQuery>::get_state(c).unwrap();
657        assert!(has_conflicts_small::<(&C2, EntityMutExcept<C1>)>(&state).is_err());
658        assert!(has_conflicts_large::<(&C2, EntityMutExcept<C1>)>(&state).is_err());
659        let _ = has_conflicts::<(&C2, EntityMutExcept<C1>)>(c);
660    }
661
662    #[test]
663    #[should_panic(expected = "conflicts")]
664    fn entity_mut_except_conflicts_component_write() {
665        let world = setup_world();
666        let c = world.components();
667        let state = <(EntityMutExcept<C1>, &mut C2) as WorldQuery>::get_state(c).unwrap();
668        assert!(has_conflicts_small::<(EntityMutExcept<C1>, &mut C2)>(&state).is_err());
669        assert!(has_conflicts_large::<(EntityMutExcept<C1>, &mut C2)>(&state).is_err());
670        let _ = has_conflicts::<(EntityMutExcept<C1>, &mut C2)>(c);
671    }
672
673    #[test]
674    #[should_panic(expected = "conflicts")]
675    fn component_write_conflicts_entity_mut_except() {
676        let world = setup_world();
677        let c = world.components();
678        let state = <(&mut C2, EntityMutExcept<C1>) as WorldQuery>::get_state(c).unwrap();
679        assert!(has_conflicts_small::<(&mut C2, EntityMutExcept<C1>)>(&state).is_err());
680        assert!(has_conflicts_large::<(&mut C2, EntityMutExcept<C1>)>(&state).is_err());
681        let _ = has_conflicts::<(&mut C2, EntityMutExcept<C1>)>(c);
682    }
683}