1use crate::error::{SchemaError, SchemaResult};
23use crate::ids::{ComplexTypeKey, SimpleTypeKey, TypeKey};
24use crate::schema::SchemaSet;
25use std::collections::{HashMap, HashSet, VecDeque};
26
27#[derive(Debug)]
32pub struct DependencyGraph {
33 dependencies: HashMap<TypeKey, Vec<TypeKey>>,
35
36 dependents: HashMap<TypeKey, Vec<TypeKey>>,
38
39 all_types: HashSet<TypeKey>,
41
42 sorted_types: Vec<TypeKey>,
45
46 is_sorted: bool,
48}
49
50impl Default for DependencyGraph {
51 fn default() -> Self {
52 Self::new()
53 }
54}
55
56impl DependencyGraph {
57 pub fn new() -> Self {
59 Self {
60 dependencies: HashMap::new(),
61 dependents: HashMap::new(),
62 all_types: HashSet::new(),
63 sorted_types: Vec::new(),
64 is_sorted: false,
65 }
66 }
67
68 pub fn add_type(&mut self, type_key: TypeKey) {
70 self.all_types.insert(type_key);
71 self.is_sorted = false;
72 }
73
74 pub fn add_dependency(&mut self, derived: TypeKey, base: TypeKey) {
78 self.all_types.insert(derived);
80 self.all_types.insert(base);
81
82 self.dependencies.entry(derived).or_default().push(base);
84
85 self.dependents.entry(base).or_default().push(derived);
87
88 self.is_sorted = false;
89 }
90
91 pub fn type_count(&self) -> usize {
93 self.all_types.len()
94 }
95
96 pub fn edge_count(&self) -> usize {
98 self.dependencies.values().map(|v| v.len()).sum()
99 }
100
101 pub fn has_dependencies(&self, type_key: TypeKey) -> bool {
103 self.dependencies
104 .get(&type_key)
105 .map(|deps| !deps.is_empty())
106 .unwrap_or(false)
107 }
108
109 pub fn get_dependencies(&self, type_key: TypeKey) -> &[TypeKey] {
111 self.dependencies
112 .get(&type_key)
113 .map(|v| v.as_slice())
114 .unwrap_or(&[])
115 }
116
117 pub fn sort(&mut self) -> SchemaResult<()> {
126 if self.is_sorted {
127 return Ok(());
128 }
129
130 let mut in_degree: HashMap<TypeKey, usize> = HashMap::new();
132 for type_key in &self.all_types {
133 let deps = self
134 .dependencies
135 .get(type_key)
136 .map(|v| v.len())
137 .unwrap_or(0);
138 in_degree.insert(*type_key, deps);
139 }
140
141 let mut queue: VecDeque<TypeKey> = in_degree
143 .iter()
144 .filter(|(_, °)| deg == 0)
145 .map(|(&key, _)| key)
146 .collect();
147
148 let mut sorted = Vec::with_capacity(self.all_types.len());
149
150 while let Some(type_key) = queue.pop_front() {
151 sorted.push(type_key);
152
153 if let Some(deps) = self.dependents.get(&type_key) {
155 for dependent in deps {
156 if let Some(deg) = in_degree.get_mut(dependent) {
157 *deg -= 1;
158 if *deg == 0 {
159 queue.push_back(*dependent);
160 }
161 }
162 }
163 }
164 }
165
166 if sorted.len() != self.all_types.len() {
168 let cycle = self.find_cycle()?;
170 return Err(SchemaError::structural(
171 "ct-props-correct.3",
172 format!("Circular type dependency detected: {}", cycle),
173 None,
174 ));
175 }
176
177 self.sorted_types = sorted;
178 self.is_sorted = true;
179 Ok(())
180 }
181
182 pub fn compilation_order(&self) -> &[TypeKey] {
186 &self.sorted_types
187 }
188
189 fn find_cycle(&self) -> SchemaResult<String> {
193 let mut visited = HashSet::new();
194 let mut in_stack = HashSet::new();
195 let mut path = Vec::new();
196
197 for &start in &self.all_types {
198 if !visited.contains(&start) {
199 if let Some(cycle) =
200 self.dfs_find_cycle(start, &mut visited, &mut in_stack, &mut path)
201 {
202 return Ok(cycle);
203 }
204 }
205 }
206
207 Ok("unknown cycle".to_string())
209 }
210
211 fn dfs_find_cycle(
213 &self,
214 node: TypeKey,
215 visited: &mut HashSet<TypeKey>,
216 in_stack: &mut HashSet<TypeKey>,
217 path: &mut Vec<TypeKey>,
218 ) -> Option<String> {
219 visited.insert(node);
220 in_stack.insert(node);
221 path.push(node);
222
223 if let Some(deps) = self.dependencies.get(&node) {
224 for &dep in deps {
225 if !visited.contains(&dep) {
226 if let Some(cycle) = self.dfs_find_cycle(dep, visited, in_stack, path) {
227 return Some(cycle);
228 }
229 } else if in_stack.contains(&dep) {
230 let cycle_start = path.iter().position(|&t| t == dep).unwrap();
232 let cycle_path: Vec<String> = path[cycle_start..]
233 .iter()
234 .map(|t| format!("{:?}", t))
235 .collect();
236 return Some(format!("{} -> {:?}", cycle_path.join(" -> "), dep));
237 }
238 }
239 }
240
241 path.pop();
242 in_stack.remove(&node);
243 None
244 }
245
246 pub fn has_cycle(&self) -> bool {
248 let mut visited = HashSet::new();
249 let mut in_stack = HashSet::new();
250 let mut path = Vec::new();
251
252 for &start in &self.all_types {
253 if !visited.contains(&start)
254 && self
255 .dfs_find_cycle(start, &mut visited, &mut in_stack, &mut path)
256 .is_some()
257 {
258 return true;
259 }
260 }
261
262 false
263 }
264}
265
266#[derive(Debug, Default)]
268pub struct DependencyStats {
269 pub simple_types: usize,
271 pub complex_types: usize,
273 pub dependencies: usize,
275 pub root_types: usize,
277 pub max_depth: usize,
279}
280
281pub fn build_dependency_graph(
294 schema_set: &SchemaSet,
295) -> SchemaResult<(DependencyGraph, DependencyStats)> {
296 let mut graph = DependencyGraph::new();
297 let mut stats = DependencyStats::default();
298
299 let simple_type_keys: Vec<SimpleTypeKey> = schema_set.arenas.simple_types.keys().collect();
301 let complex_type_keys: Vec<ComplexTypeKey> = schema_set.arenas.complex_types.keys().collect();
302
303 let builtin_types = schema_set.builtin_types();
305
306 for key in simple_type_keys {
308 let type_key = TypeKey::Simple(key);
309
310 if is_builtin_simple_type(key, builtin_types) {
312 continue;
313 }
314
315 graph.add_type(type_key);
317 stats.simple_types += 1;
318
319 if let Some(type_def) = schema_set.arenas.simple_types.get(key) {
320 if let Some(base_key) = type_def.resolved_base_type {
322 if !is_builtin_type(base_key, builtin_types) {
323 graph.add_dependency(type_key, base_key);
324 stats.dependencies += 1;
325 }
326 }
327
328 if let Some(item_key) = type_def.resolved_item_type {
330 if !is_builtin_type(item_key, builtin_types) {
331 graph.add_dependency(type_key, item_key);
332 stats.dependencies += 1;
333 }
334 }
335
336 for member_key in &type_def.resolved_member_types {
338 if !is_builtin_type(*member_key, builtin_types) {
339 graph.add_dependency(type_key, *member_key);
340 stats.dependencies += 1;
341 }
342 }
343 }
344 }
345
346 for key in complex_type_keys {
348 let type_key = TypeKey::Complex(key);
349
350 if is_builtin_type(type_key, builtin_types) {
351 continue;
352 }
353
354 graph.add_type(type_key);
356 stats.complex_types += 1;
357
358 if let Some(type_def) = schema_set.arenas.complex_types.get(key) {
359 if let Some(base_key) = type_def.resolved_base_type {
361 if !is_builtin_type(base_key, builtin_types) {
362 graph.add_dependency(type_key, base_key);
363 stats.dependencies += 1;
364 }
365 }
366 }
367 }
368
369 for type_key in graph.all_types.iter() {
371 if !graph.has_dependencies(*type_key) {
372 stats.root_types += 1;
373 }
374 }
375
376 graph.sort()?;
378
379 stats.max_depth = calculate_max_depth(&graph);
381
382 Ok((graph, stats))
383}
384
385fn is_builtin_simple_type(
387 key: SimpleTypeKey,
388 builtin: &crate::types::builtin::BuiltinTypes,
389) -> bool {
390 key == builtin.any_simple_type
394 || key == builtin.string
395 || key == builtin.boolean
396 || key == builtin.decimal
397 || key == builtin.float
398 || key == builtin.double
399 || key == builtin.duration
400 || key == builtin.datetime
401 || key == builtin.time
402 || key == builtin.date
403 || key == builtin.g_year_month
404 || key == builtin.g_year
405 || key == builtin.g_month_day
406 || key == builtin.g_day
407 || key == builtin.g_month
408 || key == builtin.hex_binary
409 || key == builtin.base64_binary
410 || key == builtin.any_uri
411 || key == builtin.xsi_schema_location_type
412 || key == builtin.qname
413 || key == builtin.notation
414 || key == builtin.normalized_string
415 || key == builtin.token
416 || key == builtin.language
417 || key == builtin.nmtoken
418 || key == builtin.nmtokens
419 || key == builtin.name
420 || key == builtin.ncname
421 || key == builtin.id
422 || key == builtin.idref
423 || key == builtin.idrefs
424 || key == builtin.entity
425 || key == builtin.entities
426 || key == builtin.integer
427 || key == builtin.non_positive_integer
428 || key == builtin.negative_integer
429 || key == builtin.long
430 || key == builtin.int
431 || key == builtin.short
432 || key == builtin.byte
433 || key == builtin.non_negative_integer
434 || key == builtin.unsigned_long
435 || key == builtin.unsigned_int
436 || key == builtin.unsigned_short
437 || key == builtin.unsigned_byte
438 || key == builtin.positive_integer
439 || (builtin.any_atomic_type == Some(key))
441 || (builtin.year_month_duration == Some(key))
442 || (builtin.day_time_duration == Some(key))
443 || (builtin.datetime_stamp == Some(key))
444 || (builtin.untyped_atomic == Some(key))
445}
446
447fn is_builtin_type(key: TypeKey, builtin: &crate::types::builtin::BuiltinTypes) -> bool {
449 match key {
450 TypeKey::Simple(simple_key) => is_builtin_simple_type(simple_key, builtin),
451 TypeKey::Complex(complex_key) => complex_key == builtin.any_type,
452 }
453}
454
455fn calculate_max_depth(graph: &DependencyGraph) -> usize {
457 let mut depth_cache: HashMap<TypeKey, usize> = HashMap::new();
458
459 fn get_depth(
460 key: TypeKey,
461 graph: &DependencyGraph,
462 cache: &mut HashMap<TypeKey, usize>,
463 ) -> usize {
464 if let Some(&cached) = cache.get(&key) {
465 return cached;
466 }
467
468 let deps = graph.get_dependencies(key);
469 let depth = if deps.is_empty() {
470 0
471 } else {
472 1 + deps
473 .iter()
474 .map(|&d| get_depth(d, graph, cache))
475 .max()
476 .unwrap_or(0)
477 };
478
479 cache.insert(key, depth);
480 depth
481 }
482
483 graph
484 .all_types
485 .iter()
486 .map(|&key| get_depth(key, graph, &mut depth_cache))
487 .max()
488 .unwrap_or(0)
489}
490
491#[cfg(test)]
492mod tests {
493 use super::*;
494 use slotmap::SlotMap;
495
496 fn make_simple_key(_id: u32) -> TypeKey {
498 thread_local! {
501 static SIMPLE_MAP: std::cell::RefCell<SlotMap<SimpleTypeKey, ()>> =
502 std::cell::RefCell::new(SlotMap::with_key());
503 }
504 SIMPLE_MAP.with(|m| TypeKey::Simple(m.borrow_mut().insert(())))
505 }
506
507 fn make_complex_key(_id: u32) -> TypeKey {
508 thread_local! {
509 static COMPLEX_MAP: std::cell::RefCell<SlotMap<ComplexTypeKey, ()>> =
510 std::cell::RefCell::new(SlotMap::with_key());
511 }
512 COMPLEX_MAP.with(|m| TypeKey::Complex(m.borrow_mut().insert(())))
513 }
514
515 #[test]
516 fn test_empty_graph() {
517 let mut graph = DependencyGraph::new();
518 assert_eq!(graph.type_count(), 0);
519 assert_eq!(graph.edge_count(), 0);
520 assert!(graph.sort().is_ok());
521 assert!(graph.compilation_order().is_empty());
522 }
523
524 #[test]
525 fn test_single_type_no_deps() {
526 let mut graph = DependencyGraph::new();
527 let t1 = make_simple_key(1);
528 graph.add_type(t1);
529
530 assert_eq!(graph.type_count(), 1);
531 assert_eq!(graph.edge_count(), 0);
532 assert!(!graph.has_dependencies(t1));
533
534 assert!(graph.sort().is_ok());
535 assert_eq!(graph.compilation_order().len(), 1);
536 assert_eq!(graph.compilation_order()[0], t1);
537 }
538
539 #[test]
540 fn test_simple_chain() {
541 let mut graph = DependencyGraph::new();
543 let t1 = make_simple_key(1);
544 let t2 = make_simple_key(2);
545 let t3 = make_simple_key(3);
546
547 graph.add_dependency(t2, t1); graph.add_dependency(t3, t2); assert_eq!(graph.type_count(), 3);
551 assert_eq!(graph.edge_count(), 2);
552
553 assert!(graph.sort().is_ok());
554 let order = graph.compilation_order();
555
556 let pos_t1 = order.iter().position(|&t| t == t1).unwrap();
558 let pos_t2 = order.iter().position(|&t| t == t2).unwrap();
559 let pos_t3 = order.iter().position(|&t| t == t3).unwrap();
560
561 assert!(pos_t1 < pos_t2);
562 assert!(pos_t2 < pos_t3);
563 }
564
565 #[test]
566 fn test_diamond_dependency() {
567 let mut graph = DependencyGraph::new();
574 let t1 = make_simple_key(1);
575 let t2 = make_simple_key(2);
576 let t3 = make_simple_key(3);
577 let t4 = make_simple_key(4);
578
579 graph.add_dependency(t2, t1);
580 graph.add_dependency(t3, t1);
581 graph.add_dependency(t4, t2);
582 graph.add_dependency(t4, t3);
583
584 assert_eq!(graph.type_count(), 4);
585 assert_eq!(graph.edge_count(), 4);
586
587 assert!(graph.sort().is_ok());
588 let order = graph.compilation_order();
589
590 let pos_t1 = order.iter().position(|&t| t == t1).unwrap();
592 let pos_t2 = order.iter().position(|&t| t == t2).unwrap();
593 let pos_t3 = order.iter().position(|&t| t == t3).unwrap();
594 let pos_t4 = order.iter().position(|&t| t == t4).unwrap();
595
596 assert!(pos_t1 < pos_t2);
597 assert!(pos_t1 < pos_t3);
598 assert!(pos_t2 < pos_t4);
599 assert!(pos_t3 < pos_t4);
600 }
601
602 #[test]
603 fn test_cycle_detection_simple() {
604 let mut graph = DependencyGraph::new();
606 let t1 = make_simple_key(1);
607 let t2 = make_simple_key(2);
608
609 graph.add_dependency(t1, t2);
610 graph.add_dependency(t2, t1);
611
612 assert!(graph.has_cycle());
613 let result = graph.sort();
614 assert!(result.is_err());
615 }
616
617 #[test]
618 fn test_cycle_detection_triangle() {
619 let mut graph = DependencyGraph::new();
621 let t1 = make_simple_key(1);
622 let t2 = make_simple_key(2);
623 let t3 = make_simple_key(3);
624
625 graph.add_dependency(t1, t2);
626 graph.add_dependency(t2, t3);
627 graph.add_dependency(t3, t1);
628
629 assert!(graph.has_cycle());
630 let result = graph.sort();
631 assert!(result.is_err());
632 }
633
634 #[test]
635 fn test_self_dependency() {
636 let mut graph = DependencyGraph::new();
638 let t1 = make_simple_key(1);
639
640 graph.add_dependency(t1, t1);
641
642 assert!(graph.has_cycle());
643 let result = graph.sort();
644 assert!(result.is_err());
645 }
646
647 #[test]
648 fn test_multiple_independent_chains() {
649 let mut graph = DependencyGraph::new();
653 let t1 = make_simple_key(1);
654 let t2 = make_simple_key(2);
655 let t3 = make_simple_key(3);
656 let t4 = make_simple_key(4);
657
658 graph.add_dependency(t2, t1);
659 graph.add_dependency(t4, t3);
660
661 assert_eq!(graph.type_count(), 4);
662 assert!(!graph.has_cycle());
663 assert!(graph.sort().is_ok());
664
665 let order = graph.compilation_order();
666
667 let pos_t1 = order.iter().position(|&t| t == t1).unwrap();
669 let pos_t2 = order.iter().position(|&t| t == t2).unwrap();
670 let pos_t3 = order.iter().position(|&t| t == t3).unwrap();
671 let pos_t4 = order.iter().position(|&t| t == t4).unwrap();
672
673 assert!(pos_t1 < pos_t2);
674 assert!(pos_t3 < pos_t4);
675 }
676
677 #[test]
678 fn test_mixed_simple_and_complex_types() {
679 let mut graph = DependencyGraph::new();
680 let s1 = make_simple_key(1);
681 let c1 = make_complex_key(1);
682
683 graph.add_dependency(c1, s1);
685
686 assert_eq!(graph.type_count(), 2);
687 assert!(graph.sort().is_ok());
688
689 let order = graph.compilation_order();
690 let pos_s1 = order.iter().position(|&t| t == s1).unwrap();
691 let pos_c1 = order.iter().position(|&t| t == c1).unwrap();
692
693 assert!(pos_s1 < pos_c1);
694 }
695
696 #[test]
697 fn test_repeated_sort() {
698 let mut graph = DependencyGraph::new();
699 let t1 = make_simple_key(1);
700 let t2 = make_simple_key(2);
701
702 graph.add_dependency(t2, t1);
703
704 assert!(graph.sort().is_ok());
706 let first_order = graph.compilation_order().to_vec();
707
708 assert!(graph.sort().is_ok());
709 let second_order = graph.compilation_order().to_vec();
710
711 assert_eq!(first_order, second_order);
713 }
714
715 #[test]
716 fn test_dependency_stats_default() {
717 let stats = DependencyStats::default();
718 assert_eq!(stats.simple_types, 0);
719 assert_eq!(stats.complex_types, 0);
720 assert_eq!(stats.dependencies, 0);
721 assert_eq!(stats.root_types, 0);
722 assert_eq!(stats.max_depth, 0);
723 }
724
725 #[test]
726 fn test_get_dependencies() {
727 let mut graph = DependencyGraph::new();
728 let t1 = make_simple_key(1);
729 let t2 = make_simple_key(2);
730 let t3 = make_simple_key(3);
731
732 graph.add_type(t1);
733 graph.add_dependency(t2, t1);
734 graph.add_dependency(t3, t1);
735 graph.add_dependency(t3, t2);
736
737 assert!(graph.get_dependencies(t1).is_empty());
738 assert_eq!(graph.get_dependencies(t2).len(), 1);
739 assert_eq!(graph.get_dependencies(t3).len(), 2);
740 }
741
742 #[test]
743 fn test_build_dependency_graph_empty_schema() {
744 let schema_set = SchemaSet::new();
745 let result = build_dependency_graph(&schema_set);
746 assert!(result.is_ok());
747
748 let (graph, stats) = result.unwrap();
749 assert_eq!(stats.simple_types, 0);
750 assert_eq!(stats.complex_types, 0);
751 assert_eq!(graph.type_count(), 0);
752 }
753
754 #[test]
755 fn test_build_dependency_graph_with_user_simple_type() {
756 use crate::arenas::SimpleTypeDefData;
757 use crate::parser::frames::SimpleTypeVariety;
758 use crate::schema::model::DerivationSet;
759 use crate::types::facets::FacetSet;
760
761 let mut schema_set = SchemaSet::new();
762
763 let type_name = schema_set.name_table.add("myStringType");
765 let string_key = schema_set.builtin_types().string;
766
767 let simple_data = SimpleTypeDefData {
768 name: Some(type_name),
769 target_namespace: None,
770 variety: SimpleTypeVariety::Atomic,
771 base_type: None,
772 item_type: None,
773 member_types: Vec::new(),
774 facets: FacetSet::new(),
775 final_derivation: DerivationSet::empty(),
776 id: None,
777 derivation_id: None,
778 annotation: None,
779 source: None,
780 resolved_base_type: Some(TypeKey::Simple(string_key)),
782 resolved_item_type: None,
783 resolved_member_types: Vec::new(),
784 redefine_original: None,
785 deferred_item_type_error: None,
786 };
787
788 let _user_type_key = schema_set.arenas.alloc_simple_type(simple_data);
789
790 let result = build_dependency_graph(&schema_set);
792 assert!(result.is_ok());
793
794 let (graph, stats) = result.unwrap();
795 assert_eq!(stats.simple_types, 1);
797 assert_eq!(graph.type_count(), 1);
799 }
800
801 #[test]
802 fn test_build_dependency_graph_chain_of_user_types() {
803 use crate::arenas::SimpleTypeDefData;
804 use crate::parser::frames::SimpleTypeVariety;
805 use crate::schema::model::DerivationSet;
806 use crate::types::facets::FacetSet;
807
808 let mut schema_set = SchemaSet::new();
809
810 let type1_name = schema_set.name_table.add("myType1");
812 let type2_name = schema_set.name_table.add("myType2");
813 let string_key = schema_set.builtin_types().string;
814
815 let type1_data = SimpleTypeDefData {
817 name: Some(type1_name),
818 target_namespace: None,
819 variety: SimpleTypeVariety::Atomic,
820 base_type: None,
821 item_type: None,
822 member_types: Vec::new(),
823 facets: FacetSet::new(),
824 final_derivation: DerivationSet::empty(),
825 id: None,
826 derivation_id: None,
827 annotation: None,
828 source: None,
829 resolved_base_type: Some(TypeKey::Simple(string_key)),
830 resolved_item_type: None,
831 resolved_member_types: Vec::new(),
832 redefine_original: None,
833 deferred_item_type_error: None,
834 };
835 let type1_key = schema_set.arenas.alloc_simple_type(type1_data);
836
837 let type2_data = SimpleTypeDefData {
839 name: Some(type2_name),
840 target_namespace: None,
841 variety: SimpleTypeVariety::Atomic,
842 base_type: None,
843 item_type: None,
844 member_types: Vec::new(),
845 facets: FacetSet::new(),
846 final_derivation: DerivationSet::empty(),
847 id: None,
848 derivation_id: None,
849 annotation: None,
850 source: None,
851 resolved_base_type: Some(TypeKey::Simple(type1_key)),
852 resolved_item_type: None,
853 resolved_member_types: Vec::new(),
854 redefine_original: None,
855 deferred_item_type_error: None,
856 };
857 let type2_key = schema_set.arenas.alloc_simple_type(type2_data);
858
859 let result = build_dependency_graph(&schema_set);
861 assert!(result.is_ok());
862
863 let (graph, stats) = result.unwrap();
864 assert_eq!(stats.simple_types, 2);
866 assert_eq!(stats.dependencies, 1);
868
869 assert!(!graph.has_cycle());
871
872 let order = graph.compilation_order();
874 let pos_type1 = order.iter().position(|&t| t == TypeKey::Simple(type1_key));
875 let pos_type2 = order.iter().position(|&t| t == TypeKey::Simple(type2_key));
876
877 assert!(pos_type1.is_some() && pos_type2.is_some());
878 assert!(pos_type1.unwrap() < pos_type2.unwrap());
879 }
880
881 #[test]
882 fn test_is_builtin_simple_type_xsd11() {
883 use crate::schema::model::XsdVersion;
884
885 let schema_set = SchemaSet::with_version(XsdVersion::V1_1);
886 let builtin = schema_set.builtin_types();
887
888 assert!(is_builtin_simple_type(builtin.string, builtin));
890 assert!(is_builtin_simple_type(builtin.integer, builtin));
891 assert!(is_builtin_simple_type(builtin.any_simple_type, builtin));
892
893 if let Some(year_month_duration) = builtin.year_month_duration {
895 assert!(is_builtin_simple_type(year_month_duration, builtin));
896 }
897 if let Some(day_time_duration) = builtin.day_time_duration {
898 assert!(is_builtin_simple_type(day_time_duration, builtin));
899 }
900 if let Some(datetime_stamp) = builtin.datetime_stamp {
901 assert!(is_builtin_simple_type(datetime_stamp, builtin));
902 }
903 if let Some(untyped_atomic) = builtin.untyped_atomic {
904 assert!(is_builtin_simple_type(untyped_atomic, builtin));
905 }
906 if let Some(any_atomic_type) = builtin.any_atomic_type {
907 assert!(is_builtin_simple_type(any_atomic_type, builtin));
908 }
909 }
910}