1use core::fmt::Display;
2
3use crate::{
4 component::{ComponentId, Components},
5 query::{Access, QueryData},
6};
7use bevy_utils::BloomFilter;
8
9const USE_FILTER_THRESHOLD: usize = 4;
15
16#[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
37fn has_conflicts_small<'a, Q: QueryData>(
42 state: &'a Q::State,
43) -> Result<(), AccessConflictError<'a>> {
44 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
58fn has_conflicts_large<'a, Q: QueryData>(
63 state: &'a Q::State,
64) -> Result<(), AccessConflictError<'a>> {
65 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 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#[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 Component(EcsAccessLevel),
115 Access(&'a Access),
117 Empty,
119}
120
121impl<'a> EcsAccessType<'a> {
122 #[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 | (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 (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#[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 Read(ComponentId),
198 Write(ComponentId),
200 ReadAll,
202 WriteAll,
204}
205
206pub 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 (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(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 (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#[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 ComponentNotRegistered,
288 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 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 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 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 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}