1use std::{
2 cmp::Ordering,
3 collections::{BTreeMap, BTreeSet, HashMap, HashSet},
4 fmt,
5 hash::{DefaultHasher, Hash, Hasher},
6 sync::Arc,
7};
8
9use sway_error::{
10 error::CompileError,
11 handler::{ErrorEmitted, Handler},
12};
13use sway_types::{integer_bits::IntegerBits, BaseIdent, Ident, Span, Spanned};
14
15use crate::{
16 decl_engine::{
17 parsed_id::ParsedDeclId, DeclEngineGet, DeclEngineGetParsedDeclId, DeclEngineInsert,
18 },
19 engine_threading::*,
20 language::{
21 parsed::{EnumDeclaration, ImplItem, StructDeclaration},
22 ty::{self, TyDecl, TyImplItem, TyTraitItem},
23 CallPath,
24 },
25 type_system::{SubstTypes, TypeId},
26 GenericArgument, IncludeSelf, SubstTypesContext, TraitConstraint, TypeEngine, TypeInfo,
27 TypeSubstMap, UnifyCheck,
28};
29
30use super::Module;
31
32#[derive(Debug, Clone)]
35pub enum TryInsertingTraitImplOnFailure {
36 Yes,
37 No,
38}
39
40#[derive(Clone)]
41pub enum CodeBlockFirstPass {
42 Yes,
43 No,
44}
45
46impl From<bool> for CodeBlockFirstPass {
47 fn from(value: bool) -> Self {
48 if value {
49 CodeBlockFirstPass::Yes
50 } else {
51 CodeBlockFirstPass::No
52 }
53 }
54}
55
56#[derive(Clone, Debug)]
57pub(crate) struct TraitSuffix {
58 pub(crate) name: Ident,
59 pub(crate) args: Vec<GenericArgument>,
60}
61impl PartialEqWithEngines for TraitSuffix {
62 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
63 self.name == other.name && self.args.eq(&other.args, ctx)
64 }
65}
66impl OrdWithEngines for TraitSuffix {
67 fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> std::cmp::Ordering {
68 self.name
69 .cmp(&other.name)
70 .then_with(|| self.args.cmp(&other.args, ctx))
71 }
72}
73
74impl DisplayWithEngines for TraitSuffix {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
76 let res = write!(f, "{}", self.name.as_str());
77 if !self.args.is_empty() {
78 write!(
79 f,
80 "<{}>",
81 self.args
82 .iter()
83 .map(|i| engines.help_out(i.type_id()).to_string())
84 .collect::<Vec<_>>()
85 .join(", ")
86 )
87 } else {
88 res
89 }
90 }
91}
92
93impl DebugWithEngines for TraitSuffix {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
95 write!(f, "{}", engines.help_out(self))
96 }
97}
98
99type TraitName = Arc<CallPath<TraitSuffix>>;
100
101#[derive(Clone, Debug)]
102pub(crate) struct TraitKey {
103 pub(crate) name: TraitName,
104 pub(crate) type_id: TypeId,
105 pub(crate) impl_type_parameters: Vec<TypeId>,
106 pub(crate) trait_decl_span: Option<Span>,
107}
108
109impl OrdWithEngines for TraitKey {
110 fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> std::cmp::Ordering {
111 self.name.cmp(&other.name, ctx).then_with(|| {
112 self.type_id
113 .cmp(&other.type_id)
114 .then_with(|| self.impl_type_parameters.cmp(&other.impl_type_parameters))
115 })
116 }
117}
118
119#[derive(Clone, Debug)]
120pub enum ResolvedTraitImplItem {
121 Parsed(ImplItem),
122 Typed(TyImplItem),
123}
124
125impl DebugWithEngines for ResolvedTraitImplItem {
126 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
127 match self {
128 ResolvedTraitImplItem::Parsed(_) => panic!(),
129 ResolvedTraitImplItem::Typed(ty) => write!(f, "{:?}", engines.help_out(ty)),
130 }
131 }
132}
133
134impl ResolvedTraitImplItem {
135 fn expect_typed(self) -> TyImplItem {
136 match self {
137 ResolvedTraitImplItem::Parsed(_) => panic!(),
138 ResolvedTraitImplItem::Typed(ty) => ty,
139 }
140 }
141
142 pub fn span(&self, engines: &Engines) -> Span {
143 match self {
144 ResolvedTraitImplItem::Parsed(item) => item.span(engines),
145 ResolvedTraitImplItem::Typed(item) => item.span(),
146 }
147 }
148}
149
150type TraitItems = BTreeMap<String, ResolvedTraitImplItem>;
152
153#[derive(Clone, Debug)]
154pub(crate) struct TraitValue {
155 pub(crate) trait_items: TraitItems,
156 pub(crate) impl_span: Span,
158}
159
160#[derive(Clone, Debug)]
161pub(crate) struct TraitEntry {
162 pub(crate) key: TraitKey,
163 pub(crate) value: TraitValue,
164}
165
166#[derive(Clone, Debug)]
167pub(crate) struct SharedTraitEntry {
168 pub(crate) inner: Arc<TraitEntry>,
169}
170
171impl SharedTraitEntry {
172 pub fn fork_if_non_unique(&mut self) -> &mut Self {
173 match Arc::get_mut(&mut self.inner) {
174 Some(_) => {}
175 None => {
176 let data = TraitEntry::clone(&self.inner);
177 self.inner = Arc::new(data);
178 }
179 }
180
181 self
182 }
183
184 pub fn get_mut(&mut self) -> &mut TraitEntry {
185 Arc::get_mut(&mut self.inner).unwrap()
186 }
187}
188
189pub(crate) type TraitImpls = BTreeMap<TypeRootFilter, Vec<SharedTraitEntry>>;
193
194#[derive(Clone, Hash, Eq, PartialOrd, Ord, PartialEq, Debug)]
195pub(crate) enum TypeRootFilter {
196 Unknown,
197 Never,
198 Placeholder,
199 StringSlice,
200 StringArray,
201 U8,
202 U16,
203 U32,
204 U64,
205 U256,
206 Bool,
207 Custom(String),
208 B256,
209 Contract,
210 ErrorRecovery,
211 Tuple(usize),
212 Enum(ParsedDeclId<EnumDeclaration>),
213 Struct(ParsedDeclId<StructDeclaration>),
214 ContractCaller(String),
215 Array,
216 RawUntypedPtr,
217 RawUntypedSlice,
218 Ptr,
219 Slice,
220 TraitType(String),
221}
222
223#[derive(Clone, Debug, Default)]
228pub struct TraitMap {
229 pub(crate) trait_impls: TraitImpls,
230 satisfied_cache: HashSet<u64>,
231}
232
233pub(crate) enum IsImplSelf {
234 Yes,
235 No,
236}
237
238pub(crate) enum IsExtendingExistingImpl {
239 Yes,
240 No,
241}
242
243impl TraitMap {
244 #[allow(clippy::too_many_arguments)]
252 pub(crate) fn insert(
253 &mut self,
254 handler: &Handler,
255 trait_name: CallPath,
256 trait_type_args: Vec<GenericArgument>,
257 type_id: TypeId,
258 impl_type_parameters: Vec<TypeId>,
259 items: &[ResolvedTraitImplItem],
260 impl_span: &Span,
261 trait_decl_span: Option<Span>,
262 is_impl_self: IsImplSelf,
263 is_extending_existing_impl: IsExtendingExistingImpl,
264 engines: &Engines,
265 ) -> Result<(), ErrorEmitted> {
266 let unaliased_type_id = engines.te().get_unaliased_type_id(type_id);
267
268 handler.scope(|handler| {
269 let mut trait_items: TraitItems = BTreeMap::new();
270 for item in items.iter() {
271 match item {
272 ResolvedTraitImplItem::Parsed(_) => todo!(),
273 ResolvedTraitImplItem::Typed(ty_item) => match ty_item {
274 TyImplItem::Fn(decl_ref) => {
275 if trait_items
276 .insert(decl_ref.name().clone().to_string(), item.clone())
277 .is_some()
278 {
279 handler.emit_err(CompileError::MultipleDefinitionsOfName {
281 name: decl_ref.name().clone(),
282 span: decl_ref.span(),
283 });
284 }
285 }
286 TyImplItem::Constant(decl_ref) => {
287 trait_items.insert(decl_ref.name().to_string(), item.clone());
288 }
289 TyImplItem::Type(decl_ref) => {
290 trait_items.insert(decl_ref.name().to_string(), item.clone());
291 }
292 },
293 }
294 }
295
296 let trait_impls = self.get_impls_mut(engines, unaliased_type_id);
297
298 for entry in trait_impls.iter() {
300 let TraitEntry {
301 key:
302 TraitKey {
303 name: map_trait_name,
304 type_id: map_type_id,
305 trait_decl_span: _,
306 impl_type_parameters: _,
307 },
308 value:
309 TraitValue {
310 trait_items: map_trait_items,
311 impl_span: existing_impl_span,
312 },
313 } = entry.inner.as_ref();
314 let CallPath {
315 suffix:
316 TraitSuffix {
317 name: map_trait_name_suffix,
318 args: map_trait_type_args,
319 },
320 ..
321 } = &*map_trait_name.clone();
322
323 let unify_checker = UnifyCheck::non_generic_constraint_subset(engines);
324
325 let types_are_subset = unify_checker.check(unaliased_type_id, *map_type_id)
329 && is_unified_type_subset(engines.te(), unaliased_type_id, *map_type_id);
330
331 fn is_unified_type_subset(
337 type_engine: &TypeEngine,
338 mut left: TypeId,
339 mut right: TypeId,
340 ) -> bool {
341 loop {
344 let left_ty_info = &*type_engine.get_unaliased(left);
345 let right_ty_info = &*type_engine.get_unaliased(right);
346 match (left_ty_info, right_ty_info) {
347 (
348 TypeInfo::Ref {
349 to_mutable_value: l_to_mut,
350 ..
351 },
352 TypeInfo::Ref {
353 to_mutable_value: r_to_mut,
354 ..
355 },
356 ) if *l_to_mut != *r_to_mut => return false, (
358 TypeInfo::Ref {
359 referenced_type: l_ty,
360 ..
361 },
362 TypeInfo::Ref {
363 referenced_type: r_ty,
364 ..
365 },
366 ) => {
367 left = l_ty.type_id();
368 right = r_ty.type_id();
369 }
370 _ => return true,
371 }
372 }
373 }
374
375 let mut traits_are_subset = true;
376 if *map_trait_name_suffix != trait_name.suffix
377 || map_trait_type_args.len() != trait_type_args.len()
378 {
379 traits_are_subset = false;
380 } else {
381 for (map_arg_type, arg_type) in
382 map_trait_type_args.iter().zip(trait_type_args.iter())
383 {
384 if !unify_checker.check(arg_type.type_id(), map_arg_type.type_id()) {
385 traits_are_subset = false;
386 }
387 }
388 }
389
390 if matches!(is_extending_existing_impl, IsExtendingExistingImpl::No)
391 && types_are_subset
392 && traits_are_subset
393 && matches!(is_impl_self, IsImplSelf::No)
394 {
395 handler.emit_err(CompileError::ConflictingImplsForTraitAndType {
396 trait_name: trait_name.to_string_with_args(engines, &trait_type_args),
397 type_implementing_for: engines.help_out(type_id).to_string(),
398 type_implementing_for_unaliased: engines
399 .help_out(unaliased_type_id)
400 .to_string(),
401 existing_impl_span: existing_impl_span.clone(),
402 second_impl_span: impl_span.clone(),
403 });
404 } else if types_are_subset
405 && (traits_are_subset || matches!(is_impl_self, IsImplSelf::Yes))
406 {
407 for name in trait_items.keys() {
408 let item = &trait_items[name];
409 match item {
410 ResolvedTraitImplItem::Parsed(_item) => todo!(),
411 ResolvedTraitImplItem::Typed(item) => match item {
412 ty::TyTraitItem::Fn(decl_ref) => {
413 if let Some(existing_item) = map_trait_items.get(name) {
414 handler.emit_err(
415 CompileError::DuplicateDeclDefinedForType {
416 decl_kind: "method".into(),
417 decl_name: decl_ref.name().to_string(),
418 type_implementing_for: engines
419 .help_out(type_id)
420 .to_string(),
421 type_implementing_for_unaliased: engines
422 .help_out(unaliased_type_id)
423 .to_string(),
424 existing_impl_span: existing_item
425 .span(engines)
426 .clone(),
427 second_impl_span: decl_ref.name().span(),
428 },
429 );
430 }
431 }
432 ty::TyTraitItem::Constant(decl_ref) => {
433 if let Some(existing_item) = map_trait_items.get(name) {
434 handler.emit_err(
435 CompileError::DuplicateDeclDefinedForType {
436 decl_kind: "constant".into(),
437 decl_name: decl_ref.name().to_string(),
438 type_implementing_for: engines
439 .help_out(type_id)
440 .to_string(),
441 type_implementing_for_unaliased: engines
442 .help_out(unaliased_type_id)
443 .to_string(),
444 existing_impl_span: existing_item
445 .span(engines)
446 .clone(),
447 second_impl_span: decl_ref.name().span(),
448 },
449 );
450 }
451 }
452 ty::TyTraitItem::Type(decl_ref) => {
453 if let Some(existing_item) = map_trait_items.get(name) {
454 handler.emit_err(
455 CompileError::DuplicateDeclDefinedForType {
456 decl_kind: "type".into(),
457 decl_name: decl_ref.name().to_string(),
458 type_implementing_for: engines
459 .help_out(type_id)
460 .to_string(),
461 type_implementing_for_unaliased: engines
462 .help_out(unaliased_type_id)
463 .to_string(),
464 existing_impl_span: existing_item
465 .span(engines)
466 .clone(),
467 second_impl_span: decl_ref.name().span(),
468 },
469 );
470 }
471 }
472 },
473 }
474 }
475 }
476 }
477 let trait_name: TraitName = Arc::new(CallPath {
478 prefixes: trait_name.prefixes,
479 suffix: TraitSuffix {
480 name: trait_name.suffix,
481 args: trait_type_args,
482 },
483 callpath_type: trait_name.callpath_type,
484 });
485
486 self.insert_inner(
488 trait_name,
489 impl_span.clone(),
490 trait_decl_span,
491 unaliased_type_id,
492 impl_type_parameters,
493 trait_items,
494 engines,
495 );
496
497 Ok(())
498 })
499 }
500
501 #[allow(clippy::too_many_arguments)]
502 fn insert_inner(
503 &mut self,
504 trait_name: TraitName,
505 impl_span: Span,
506 trait_decl_span: Option<Span>,
507 type_id: TypeId,
508 impl_type_parameters: Vec<TypeId>,
509 trait_methods: TraitItems,
510 engines: &Engines,
511 ) {
512 let key = TraitKey {
513 name: trait_name,
514 type_id,
515 trait_decl_span,
516 impl_type_parameters,
517 };
518 let value = TraitValue {
519 trait_items: trait_methods,
520 impl_span,
521 };
522 let mut trait_impls: TraitImpls = BTreeMap::new();
523 let type_root_filter = Self::get_type_root_filter(engines, type_id);
524 let entry = TraitEntry { key, value };
525 let impls_vector = vec![SharedTraitEntry {
526 inner: Arc::new(entry),
527 }];
528 trait_impls.insert(type_root_filter, impls_vector);
529
530 let trait_map = TraitMap {
531 trait_impls,
532 satisfied_cache: HashSet::default(),
533 };
534
535 self.extend(trait_map, engines);
536 }
537
538 pub(crate) fn extend(&mut self, other: TraitMap, engines: &Engines) {
541 for impls_key in other.trait_impls.keys() {
542 let oe_vec = &other.trait_impls[impls_key];
543 let self_vec = if let Some(self_vec) = self.trait_impls.get_mut(impls_key) {
544 self_vec
545 } else {
546 self.trait_impls.insert(impls_key.clone(), Vec::<_>::new());
547 self.trait_impls.get_mut(impls_key).unwrap()
548 };
549
550 for oe in oe_vec.iter() {
551 let pos = self_vec.binary_search_by(|se| {
552 se.inner
553 .key
554 .cmp(&oe.inner.key, &OrdWithEnginesContext::new(engines))
555 });
556
557 match pos {
558 Ok(pos) => self_vec[pos]
559 .fork_if_non_unique()
560 .get_mut()
561 .value
562 .trait_items
563 .extend(oe.inner.value.trait_items.clone()),
564 Err(pos) => self_vec.insert(pos, oe.clone()),
565 }
566 }
567 }
568 }
569
570 pub(crate) fn get_traits_types(
571 &self,
572 traits_types: &mut HashMap<CallPath, Vec<TypeId>>,
573 ) -> Result<(), ErrorEmitted> {
574 for key in self.trait_impls.keys() {
575 for self_entry in self.trait_impls[key].iter() {
576 let callpath = CallPath {
577 prefixes: self_entry.inner.key.name.prefixes.clone(),
578 suffix: self_entry.inner.key.name.suffix.name.clone(),
579 callpath_type: self_entry.inner.key.name.callpath_type,
580 };
581 if let Some(vec) = traits_types.get_mut(&callpath) {
582 vec.push(self_entry.inner.key.type_id);
583 } else {
584 traits_types.insert(callpath, vec![self_entry.inner.key.type_id]);
585 }
586 }
587 }
588 Ok(())
589 }
590
591 pub(crate) fn filter_by_trait_decl_span(&self, trait_decl_span: Span) -> TraitMap {
594 let mut trait_map = TraitMap::default();
595 for key in self.trait_impls.keys() {
596 let vec = &self.trait_impls[key];
597 for entry in vec {
598 if entry.inner.key.trait_decl_span.as_ref() == Some(&trait_decl_span) {
599 let trait_map_vec =
600 if let Some(trait_map_vec) = trait_map.trait_impls.get_mut(key) {
601 trait_map_vec
602 } else {
603 trait_map.trait_impls.insert(key.clone(), Vec::<_>::new());
604 trait_map.trait_impls.get_mut(key).unwrap()
605 };
606
607 trait_map_vec.push(entry.clone());
608 }
609 }
610 }
611 trait_map
612 }
613
614 pub(crate) fn filter_by_type_item_import(
673 &self,
674 type_id: TypeId,
675 engines: &Engines,
676 ) -> TraitMap {
677 let unify_checker = UnifyCheck::constraint_subset(engines);
678 let unify_checker_for_item_import = UnifyCheck::non_generic_constraint_subset(engines);
679
680 let decider = |left: TypeId, right: TypeId| {
682 unify_checker.check(left, right) || unify_checker_for_item_import.check(right, left)
683 };
684 let mut trait_map = self.filter_by_type_inner(engines, vec![type_id], decider);
685 let all_types = type_id
686 .extract_inner_types(engines, IncludeSelf::No)
687 .into_iter()
688 .collect::<Vec<_>>();
689 let decider2 = |left: TypeId, right: TypeId| unify_checker.check(left, right);
691
692 trait_map.extend(
693 self.filter_by_type_inner(engines, all_types, decider2),
694 engines,
695 );
696 trait_map
697 }
698
699 fn filter_by_type_inner(
700 &self,
701 engines: &Engines,
702 mut all_types: Vec<TypeId>,
703 decider: impl Fn(TypeId, TypeId) -> bool,
704 ) -> TraitMap {
705 let type_engine = engines.te();
706 let mut trait_map = TraitMap::default();
707 for type_id in all_types.iter_mut() {
708 let type_info = type_engine.get(*type_id);
709 self.for_each_impls(engines, *type_id, true, |entry| {
710 let TraitEntry {
711 key:
712 TraitKey {
713 name: map_trait_name,
714 type_id: map_type_id,
715 trait_decl_span: map_trait_decl_span,
716 impl_type_parameters: map_impl_type_parameters,
717 },
718 value:
719 TraitValue {
720 trait_items: map_trait_items,
721 impl_span,
722 },
723 } = entry.inner.as_ref();
724
725 if !type_engine.is_type_changeable(engines, &type_info) && *type_id == *map_type_id
726 {
727 trait_map.insert_inner(
728 map_trait_name.clone(),
729 impl_span.clone(),
730 map_trait_decl_span.clone(),
731 *type_id,
732 map_impl_type_parameters.clone(),
733 map_trait_items.clone(),
734 engines,
735 );
736 } else if decider(*type_id, *map_type_id) {
737 trait_map.insert_inner(
738 map_trait_name.clone(),
739 impl_span.clone(),
740 map_trait_decl_span.clone(),
741 *map_type_id,
742 map_impl_type_parameters.clone(),
743 Self::filter_dummy_methods(
744 map_trait_items,
745 *type_id,
746 *map_type_id,
747 engines,
748 )
749 .map(|(name, item)| (name.to_string(), item))
750 .collect(),
751 engines,
752 );
753 }
754 });
755 }
756 trait_map
757 }
758
759 fn filter_dummy_methods<'a>(
760 map_trait_items: &'a TraitItems,
761 type_id: TypeId,
762 map_type_id: TypeId,
763 engines: &'a Engines,
764 ) -> impl Iterator<Item = (&'a str, ResolvedTraitImplItem)> + 'a {
765 let maybe_is_from_type_parameter = engines.te().map(map_type_id, |x| match x {
766 TypeInfo::UnknownGeneric {
767 is_from_type_parameter,
768 ..
769 } => Some(*is_from_type_parameter),
770 _ => None,
771 });
772 let insertable = if let Some(is_from_type_parameter) = maybe_is_from_type_parameter {
773 !is_from_type_parameter
774 || matches!(*engines.te().get(type_id), TypeInfo::UnknownGeneric { .. })
775 } else {
776 true
777 };
778
779 map_trait_items
780 .iter()
781 .filter_map(move |(name, item)| match item {
782 ResolvedTraitImplItem::Parsed(_item) => todo!(),
783 ResolvedTraitImplItem::Typed(item) => match item {
784 ty::TyTraitItem::Fn(decl_ref) => engines.de().map(decl_ref.id(), |decl| {
785 if decl.is_trait_method_dummy && !insertable {
786 None
787 } else {
788 Some((
789 name.as_str(),
790 ResolvedTraitImplItem::Typed(TyImplItem::Fn(decl_ref.clone())),
791 ))
792 }
793 }),
794 ty::TyTraitItem::Constant(decl_ref) => Some((
795 name.as_str(),
796 ResolvedTraitImplItem::Typed(TyImplItem::Constant(decl_ref.clone())),
797 )),
798 ty::TyTraitItem::Type(decl_ref) => Some((
799 name.as_str(),
800 ResolvedTraitImplItem::Typed(TyImplItem::Type(decl_ref.clone())),
801 )),
802 },
803 })
804 }
805
806 fn make_item_for_type_mapping(
807 engines: &Engines,
808 item: ResolvedTraitImplItem,
809 mut type_mapping: TypeSubstMap,
810 type_id: TypeId,
811 code_block_first_pass: CodeBlockFirstPass,
812 ) -> ResolvedTraitImplItem {
813 let decl_engine = engines.de();
814 match &item {
815 ResolvedTraitImplItem::Parsed(_item) => todo!(),
816 ResolvedTraitImplItem::Typed(item) => match item {
817 ty::TyTraitItem::Fn(decl_ref) => {
818 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
819 if let Some(decl_implementing_for_typeid) = decl.implementing_for_typeid {
820 type_mapping.insert(decl_implementing_for_typeid, type_id);
821 }
822 decl.subst(&SubstTypesContext::new(
823 engines,
824 &type_mapping,
825 matches!(code_block_first_pass, CodeBlockFirstPass::No),
826 ));
827
828 let new_ref = decl_engine
829 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref())
830 .with_parent(decl_engine, decl_ref.id().into());
831
832 ResolvedTraitImplItem::Typed(TyImplItem::Fn(new_ref))
833 }
834 ty::TyTraitItem::Constant(decl_ref) => {
835 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
836 decl.subst(&SubstTypesContext::new(
837 engines,
838 &type_mapping,
839 matches!(code_block_first_pass, CodeBlockFirstPass::No),
840 ));
841 let new_ref = decl_engine
842 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref());
843 ResolvedTraitImplItem::Typed(TyImplItem::Constant(new_ref))
844 }
845 ty::TyTraitItem::Type(decl_ref) => {
846 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
847 decl.subst(&SubstTypesContext::new(
848 engines,
849 &type_mapping,
850 matches!(code_block_first_pass, CodeBlockFirstPass::No),
851 ));
852 let new_ref = decl_engine
853 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref());
854 ResolvedTraitImplItem::Typed(TyImplItem::Type(new_ref))
855 }
856 },
857 }
858 }
859
860 pub(crate) fn append_items_for_type(
870 module: &Module,
871 engines: &Engines,
872 type_id: TypeId,
873 items: &mut Vec<ResolvedTraitImplItem>,
874 ) {
875 TraitMap::find_items_and_trait_key_for_type(module, engines, type_id, &mut |item, _| {
876 items.push(item);
877 });
878 }
879
880 pub(crate) fn find_items_and_trait_key_for_type(
881 module: &Module,
882 engines: &Engines,
883 type_id: TypeId,
884 callback: &mut impl FnMut(ResolvedTraitImplItem, TraitKey),
885 ) {
886 let type_engine = engines.te();
887 let type_id = engines.te().get_unaliased_type_id(type_id);
888
889 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
891 return;
892 }
893
894 let unify_check = UnifyCheck::constraint_subset(engines);
895
896 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
897 lexical_scope.items.implemented_traits.for_each_impls(
898 engines,
899 type_id,
900 true,
901 |entry| {
902 if unify_check.check(type_id, entry.inner.key.type_id) {
903 let trait_items = Self::filter_dummy_methods(
904 &entry.inner.value.trait_items,
905 type_id,
906 entry.inner.key.type_id,
907 engines,
908 )
909 .map(|(_, i)| (i, entry.inner.key.clone()));
910
911 for i in trait_items {
912 callback(i.0, i.1);
913 }
914 }
915 },
916 );
917
918 Ok(None::<()>)
919 });
920 }
921
922 pub fn get_impl_spans_for_type(
932 module: &Module,
933 engines: &Engines,
934 type_id: &TypeId,
935 ) -> Vec<Span> {
936 let type_engine = engines.te();
937 let unify_check = UnifyCheck::constraint_subset(engines);
938
939 let type_id = &engines.te().get_unaliased_type_id(*type_id);
940
941 let mut spans = vec![];
942 if matches!(&*type_engine.get(*type_id), TypeInfo::ErrorRecovery(_)) {
944 return spans;
945 }
946 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
947 lexical_scope.items.implemented_traits.for_each_impls(
948 engines,
949 *type_id,
950 false,
951 |entry| {
952 if unify_check.check(*type_id, entry.inner.key.type_id) {
953 spans.push(entry.inner.value.impl_span.clone());
954 }
955 },
956 );
957
958 Ok(None::<()>)
959 });
960
961 spans
962 }
963
964 pub fn get_impl_spans_for_decl(
966 module: &Module,
967 engines: &Engines,
968 ty_decl: &TyDecl,
969 ) -> Vec<Span> {
970 let handler = Handler::default();
971 ty_decl
972 .return_type(&handler, engines)
973 .map(|type_id| TraitMap::get_impl_spans_for_type(module, engines, &type_id))
974 .unwrap_or_default()
975 }
976
977 pub fn get_impl_spans_for_trait_name(module: &Module, trait_name: &CallPath) -> Vec<Span> {
980 let mut spans = vec![];
981 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
982 spans.push(
983 lexical_scope
984 .items
985 .implemented_traits
986 .trait_impls
987 .values()
988 .map(|impls| {
989 impls
990 .iter()
991 .filter_map(|entry| {
992 let map_trait_name = CallPath {
993 prefixes: entry.inner.key.name.prefixes.clone(),
994 suffix: entry.inner.key.name.suffix.name.clone(),
995 callpath_type: entry.inner.key.name.callpath_type,
996 };
997 if &map_trait_name == trait_name {
998 Some(entry.inner.value.impl_span.clone())
999 } else {
1000 None
1001 }
1002 })
1003 .collect::<Vec<Span>>()
1004 })
1005 .collect::<Vec<Vec<Span>>>()
1006 .concat(),
1007 );
1008 Ok(None::<()>)
1009 });
1010
1011 spans.concat()
1012 }
1013
1014 pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments(
1025 module: &Module,
1026 engines: &Engines,
1027 type_id: TypeId,
1028 trait_name: &CallPath,
1029 trait_type_args: &[GenericArgument],
1030 ) -> Vec<ResolvedTraitImplItem> {
1031 let type_id = engines.te().get_unaliased_type_id(type_id);
1032
1033 let type_engine = engines.te();
1034 let unify_check = UnifyCheck::constraint_subset(engines);
1035 let mut items = vec![];
1036 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1038 return items;
1039 }
1040 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1041 lexical_scope
1042 .items
1043 .implemented_traits
1044 .for_each_impls(engines, type_id, false, |e| {
1045 let map_trait_name = CallPath {
1046 prefixes: e.inner.key.name.prefixes.clone(),
1047 suffix: e.inner.key.name.suffix.name.clone(),
1048 callpath_type: e.inner.key.name.callpath_type,
1049 };
1050 if &map_trait_name == trait_name
1051 && unify_check.check(type_id, e.inner.key.type_id)
1052 && trait_type_args.len() == e.inner.key.name.suffix.args.len()
1053 && trait_type_args
1054 .iter()
1055 .zip(e.inner.key.name.suffix.args.iter())
1056 .all(|(t1, t2)| unify_check.check(t1.type_id(), t2.type_id()))
1057 {
1058 let type_mapping = TypeSubstMap::from_superset_and_subset(
1059 engines,
1060 e.inner.key.type_id,
1061 type_id,
1062 );
1063
1064 let mut trait_items = Self::filter_dummy_methods(
1065 &e.inner.value.trait_items,
1066 type_id,
1067 e.inner.key.type_id,
1068 engines,
1069 )
1070 .map(|(_, i)| {
1071 Self::make_item_for_type_mapping(
1072 engines,
1073 i,
1074 type_mapping.clone(),
1075 type_id,
1076 CodeBlockFirstPass::No,
1077 )
1078 })
1079 .collect::<Vec<_>>();
1080
1081 items.append(&mut trait_items);
1082 }
1083 });
1084 Ok(None::<()>)
1085 });
1086 items
1087 }
1088
1089 pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments_typed(
1100 module: &Module,
1101 engines: &Engines,
1102 type_id: TypeId,
1103 trait_name: &CallPath,
1104 trait_type_args: &[GenericArgument],
1105 ) -> Vec<ty::TyTraitItem> {
1106 TraitMap::get_items_for_type_and_trait_name_and_trait_type_arguments(
1107 module,
1108 engines,
1109 type_id,
1110 trait_name,
1111 trait_type_args,
1112 )
1113 .into_iter()
1114 .map(|item| item.expect_typed())
1115 .collect::<Vec<_>>()
1116 }
1117
1118 pub(crate) fn get_trait_names_and_type_arguments_for_type(
1119 module: &Module,
1120 engines: &Engines,
1121 type_id: TypeId,
1122 ) -> Vec<(CallPath, Vec<GenericArgument>)> {
1123 let type_id = engines.te().get_unaliased_type_id(type_id);
1124
1125 let type_engine = engines.te();
1126 let unify_check = UnifyCheck::constraint_subset(engines);
1127 let mut trait_names = vec![];
1128 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1130 return trait_names;
1131 }
1132 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1133 lexical_scope.items.implemented_traits.for_each_impls(
1134 engines,
1135 type_id,
1136 false,
1137 |entry| {
1138 if unify_check.check(type_id, entry.inner.key.type_id) {
1139 let trait_call_path = CallPath {
1140 prefixes: entry.inner.key.name.prefixes.clone(),
1141 suffix: entry.inner.key.name.suffix.name.clone(),
1142 callpath_type: entry.inner.key.name.callpath_type,
1143 };
1144 trait_names
1145 .push((trait_call_path, entry.inner.key.name.suffix.args.clone()));
1146 }
1147 },
1148 );
1149 Ok(None::<()>)
1150 });
1151 trait_names
1152 }
1153
1154 pub(crate) fn type_implements_trait<F: Fn(&SharedTraitEntry) -> bool>(
1157 module: &Module,
1158 engines: &Engines,
1159 type_id: TypeId,
1160 predicate: F,
1161 ) -> bool {
1162 let type_id = engines.te().get_unaliased_type_id(type_id);
1163
1164 if matches!(&*engines.te().get(type_id), TypeInfo::ErrorRecovery(_)) {
1166 return false;
1167 }
1168
1169 let unify_check = UnifyCheck::constraint_subset(engines);
1170 let mut implements_trait = false;
1171 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1172 lexical_scope.items.implemented_traits.for_each_impls(
1173 engines,
1174 type_id,
1175 false,
1176 |entry| {
1177 if !implements_trait
1180 && unify_check.check(type_id, entry.inner.key.type_id)
1181 && predicate(entry)
1182 {
1183 implements_trait = true;
1184 }
1185 },
1186 );
1187 Ok(None::<()>)
1188 });
1189 implements_trait
1190 }
1191
1192 pub(crate) fn get_trait_item_for_type(
1193 module: &Module,
1194 handler: &Handler,
1195 engines: &Engines,
1196 symbol: &Ident,
1197 type_id: TypeId,
1198 as_trait: Option<CallPath>,
1199 ) -> Result<ResolvedTraitImplItem, ErrorEmitted> {
1200 let type_id = engines.te().get_unaliased_type_id(type_id);
1201
1202 let mut candidates = HashMap::<String, ResolvedTraitImplItem>::new();
1203
1204 TraitMap::find_items_and_trait_key_for_type(
1205 module,
1206 engines,
1207 type_id,
1208 &mut |trait_item, trait_key| match trait_item {
1209 ResolvedTraitImplItem::Parsed(impl_item) => match impl_item {
1210 ImplItem::Fn(fn_ref) => {
1211 let decl = engines.pe().get_function(&fn_ref);
1212 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1213 if decl.name.as_str() == symbol.as_str()
1214 && (as_trait.is_none()
1215 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1216 {
1217 candidates.insert(
1218 trait_call_path_string,
1219 ResolvedTraitImplItem::Parsed(ImplItem::Fn(fn_ref)),
1220 );
1221 }
1222 }
1223 ImplItem::Constant(const_ref) => {
1224 let decl = engines.pe().get_constant(&const_ref);
1225 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1226 if decl.name.as_str() == symbol.as_str()
1227 && (as_trait.is_none()
1228 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1229 {
1230 candidates.insert(
1231 trait_call_path_string,
1232 ResolvedTraitImplItem::Parsed(ImplItem::Constant(const_ref)),
1233 );
1234 }
1235 }
1236 ImplItem::Type(type_ref) => {
1237 let decl = engines.pe().get_trait_type(&type_ref);
1238 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1239 if decl.name.as_str() == symbol.as_str()
1240 && (as_trait.is_none()
1241 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1242 {
1243 candidates.insert(
1244 trait_call_path_string,
1245 ResolvedTraitImplItem::Parsed(ImplItem::Type(type_ref)),
1246 );
1247 }
1248 }
1249 },
1250 ResolvedTraitImplItem::Typed(ty_impl_item) => match ty_impl_item {
1251 ty::TyTraitItem::Fn(fn_ref) => {
1252 let decl = engines.de().get_function(&fn_ref);
1253 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1254 if decl.name.as_str() == symbol.as_str()
1255 && (as_trait.is_none()
1256 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1257 {
1258 candidates.insert(
1259 trait_call_path_string,
1260 ResolvedTraitImplItem::Typed(TyTraitItem::Fn(fn_ref)),
1261 );
1262 }
1263 }
1264 ty::TyTraitItem::Constant(const_ref) => {
1265 let decl = engines.de().get_constant(&const_ref);
1266 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1267 if decl.call_path.suffix.as_str() == symbol.as_str()
1268 && (as_trait.is_none()
1269 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1270 {
1271 candidates.insert(
1272 trait_call_path_string,
1273 ResolvedTraitImplItem::Typed(TyTraitItem::Constant(const_ref)),
1274 );
1275 }
1276 }
1277 ty::TyTraitItem::Type(type_ref) => {
1278 let decl = engines.de().get_type(&type_ref);
1279 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1280 if decl.name.as_str() == symbol.as_str()
1281 && (as_trait.is_none()
1282 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1283 {
1284 candidates.insert(
1285 trait_call_path_string,
1286 ResolvedTraitImplItem::Typed(TyTraitItem::Type(type_ref)),
1287 );
1288 }
1289 }
1290 },
1291 },
1292 );
1293
1294 match candidates.len().cmp(&1) {
1295 Ordering::Greater => Err(handler.emit_err(
1296 CompileError::MultipleApplicableItemsInScope {
1297 item_name: symbol.as_str().to_string(),
1298 item_kind: "item".to_string(),
1299 as_traits: candidates
1300 .keys()
1301 .map(|k| {
1302 (
1303 k.clone()
1304 .split("::")
1305 .collect::<Vec<_>>()
1306 .last()
1307 .unwrap()
1308 .to_string(),
1309 engines.help_out(type_id).to_string(),
1310 )
1311 })
1312 .collect::<Vec<_>>(),
1313 span: symbol.span(),
1314 },
1315 )),
1316 Ordering::Less => Err(handler.emit_err(CompileError::SymbolNotFound {
1317 name: symbol.clone(),
1318 span: symbol.span(),
1319 })),
1320 Ordering::Equal => Ok(candidates.values().next().unwrap().clone()),
1321 }
1322 }
1323
1324 #[allow(clippy::too_many_arguments)]
1326 pub(crate) fn check_if_trait_constraints_are_satisfied_for_type(
1327 handler: &Handler,
1328 module: &mut Module,
1329 type_id: TypeId,
1330 constraints: &[TraitConstraint],
1331 access_span: &Span,
1332 engines: &Engines,
1333 ) -> Result<(), ErrorEmitted> {
1334 let type_engine = engines.te();
1335
1336 let type_id = type_engine.get_unaliased_type_id(type_id);
1337
1338 type_engine.decay_numeric(handler, engines, type_id, access_span)?;
1340
1341 if constraints.is_empty() {
1342 return Ok(());
1343 }
1344
1345 let mut hasher = DefaultHasher::default();
1347 type_id.hash(&mut hasher);
1348 for c in constraints {
1349 c.hash(&mut hasher, engines);
1350 }
1351 let hash = hasher.finish();
1352
1353 {
1354 let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1355 if trait_map.satisfied_cache.contains(&hash) {
1356 return Ok(());
1357 }
1358 }
1359
1360 let all_impld_traits: BTreeSet<(Ident, TypeId)> =
1361 Self::get_all_implemented_traits(module, type_id, engines);
1362
1363 match Self::check_if_trait_constraints_are_satisfied_for_type_inner(
1365 handler,
1366 type_id,
1367 constraints,
1368 access_span,
1369 engines,
1370 all_impld_traits,
1371 ) {
1372 Ok(()) => {
1373 let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1374 trait_map.satisfied_cache.insert(hash);
1375 Ok(())
1376 }
1377 r => r,
1378 }
1379 }
1380
1381 fn get_all_implemented_traits(
1382 module: &Module,
1383 type_id: TypeId,
1384 engines: &Engines,
1385 ) -> BTreeSet<(Ident, TypeId)> {
1386 let mut all_impld_traits: BTreeSet<(Ident, TypeId)> = Default::default();
1387 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1388 all_impld_traits.extend(
1389 lexical_scope
1390 .items
1391 .implemented_traits
1392 .get_implemented_traits(type_id, engines),
1393 );
1394 Ok(None::<()>)
1395 });
1396 all_impld_traits
1397 }
1398
1399 fn get_implemented_traits(
1400 &self,
1401 type_id: TypeId,
1402 engines: &Engines,
1403 ) -> BTreeSet<(Ident, TypeId)> {
1404 let type_engine = engines.te();
1405 let unify_check = UnifyCheck::constraint_subset(engines);
1406 let mut all_impld_traits = BTreeSet::<(Ident, TypeId)>::new();
1407 self.for_each_impls(engines, type_id, true, |e| {
1408 let key = &e.inner.key;
1409 let suffix = &key.name.suffix;
1410 if unify_check.check(type_id, key.type_id) {
1411 let map_trait_type_id = type_engine.new_custom(
1412 engines,
1413 suffix.name.clone().into(),
1414 if suffix.args.is_empty() {
1415 None
1416 } else {
1417 Some(suffix.args.to_vec())
1418 },
1419 );
1420 all_impld_traits.insert((suffix.name.clone(), map_trait_type_id));
1421 }
1422 });
1423 all_impld_traits
1424 }
1425
1426 #[allow(clippy::too_many_arguments)]
1427 fn check_if_trait_constraints_are_satisfied_for_type_inner(
1428 handler: &Handler,
1429 type_id: TypeId,
1430 constraints: &[TraitConstraint],
1431 access_span: &Span,
1432 engines: &Engines,
1433 all_impld_traits: BTreeSet<(Ident, TypeId)>,
1434 ) -> Result<(), ErrorEmitted> {
1435 let type_engine = engines.te();
1436 let unify_check = UnifyCheck::constraint_subset(engines);
1437
1438 let required_traits: BTreeSet<(Ident, TypeId)> = constraints
1439 .iter()
1440 .map(|c| {
1441 let TraitConstraint {
1442 trait_name: constraint_trait_name,
1443 type_arguments: constraint_type_arguments,
1444 } = c;
1445 let constraint_type_id = type_engine.new_custom(
1446 engines,
1447 constraint_trait_name.suffix.clone().into(),
1448 if constraint_type_arguments.is_empty() {
1449 None
1450 } else {
1451 Some(constraint_type_arguments.clone())
1452 },
1453 );
1454 (c.trait_name.suffix.clone(), constraint_type_id)
1455 })
1456 .collect();
1457
1458 let traits_not_found: BTreeSet<(BaseIdent, TypeId)> = required_traits
1459 .into_iter()
1460 .filter(|(required_trait_name, required_trait_type_id)| {
1461 !all_impld_traits
1462 .iter()
1463 .any(|(trait_name, constraint_type_id)| {
1464 trait_name == required_trait_name
1465 && unify_check.check(*constraint_type_id, *required_trait_type_id)
1466 })
1467 })
1468 .collect();
1469
1470 handler.scope(|handler| {
1471 for (trait_name, constraint_type_id) in traits_not_found.iter() {
1472 let mut type_arguments_string = "".to_string();
1473 if let TypeInfo::Custom {
1474 qualified_call_path: _,
1475 type_arguments: Some(type_arguments),
1476 } = &*type_engine.get(*constraint_type_id)
1477 {
1478 type_arguments_string = format!("<{}>", engines.help_out(type_arguments));
1479 }
1480
1481 handler.emit_err(CompileError::TraitConstraintNotSatisfied {
1483 type_id: type_id.index(),
1484 ty: engines.help_out(type_id).to_string(),
1485 trait_name: format!("{}{}", trait_name, type_arguments_string),
1486 span: access_span.clone(),
1487 });
1488 }
1489
1490 Ok(())
1491 })
1492 }
1493
1494 pub fn get_trait_constraints_are_satisfied_for_types(
1495 module: &Module,
1496 _handler: &Handler,
1497 type_id: TypeId,
1498 constraints: &[TraitConstraint],
1499 engines: &Engines,
1500 ) -> Result<Vec<(TypeId, String)>, ErrorEmitted> {
1501 let type_id = engines.te().get_unaliased_type_id(type_id);
1502
1503 let _decl_engine = engines.de();
1504 let unify_check = UnifyCheck::coercion(engines);
1505 let unify_check_equality = UnifyCheck::constraint_subset(engines);
1506
1507 let mut impld_traits_type_ids: Vec<Vec<(TypeId, String)>> = vec![];
1508 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1509 lexical_scope
1510 .items
1511 .implemented_traits
1512 .for_each_impls(engines, type_id, true, |e| {
1513 let mut traits: Vec<(TypeId, String)> = vec![];
1514
1515 let key = &e.inner.key;
1516 for constraint in constraints {
1517 if key.name.suffix.name == constraint.trait_name.suffix
1518 && key
1519 .name
1520 .suffix
1521 .args
1522 .iter()
1523 .zip(constraint.type_arguments.iter())
1524 .all(|(a1, a2)| {
1525 unify_check_equality.check(a1.type_id(), a2.type_id())
1526 })
1527 && unify_check.check(type_id, key.type_id)
1528 {
1529 let name_type_args = if !key.name.suffix.args.is_empty() {
1530 format!("<{}>", engines.help_out(key.name.suffix.args.clone()))
1531 } else {
1532 "".to_string()
1533 };
1534 let name =
1535 format!("{}{}", key.name.suffix.name.as_str(), name_type_args);
1536 traits.push((key.type_id, name));
1537 break;
1538 }
1539 }
1540 impld_traits_type_ids.push(traits);
1541 });
1542
1543 Ok(None::<()>)
1544 });
1545 Ok(impld_traits_type_ids.concat())
1546 }
1547
1548 fn get_impls_mut(&mut self, engines: &Engines, type_id: TypeId) -> &mut Vec<SharedTraitEntry> {
1549 let type_root_filter = Self::get_type_root_filter(engines, type_id);
1550 if !self.trait_impls.contains_key(&type_root_filter) {
1551 self.trait_impls
1552 .insert(type_root_filter.clone(), Vec::new());
1553 }
1554
1555 self.trait_impls.get_mut(&type_root_filter).unwrap()
1556 }
1557
1558 pub(crate) fn for_each_impls<F>(
1559 &self,
1560 engines: &Engines,
1561 type_id: TypeId,
1562 include_placeholder: bool,
1563 mut callback: F,
1564 ) where
1565 F: FnMut(&SharedTraitEntry),
1566 {
1567 let type_root_filter = Self::get_type_root_filter(engines, type_id);
1568 self.trait_impls
1569 .get(&type_root_filter)
1570 .iter()
1571 .for_each(|vec| vec.iter().for_each(&mut callback));
1572 if include_placeholder && type_root_filter != TypeRootFilter::Placeholder {
1573 self.trait_impls
1574 .get(&TypeRootFilter::Placeholder)
1575 .iter()
1576 .for_each(|vec| vec.iter().for_each(&mut callback));
1577 }
1578 }
1579
1580 fn get_type_root_filter(engines: &Engines, type_id: TypeId) -> TypeRootFilter {
1583 use TypeInfo::*;
1584 match &*engines.te().get(type_id) {
1585 Unknown => TypeRootFilter::Unknown,
1586 Never => TypeRootFilter::Never,
1587 UnknownGeneric { .. } | Placeholder(_) => TypeRootFilter::Placeholder,
1588 TypeParam(_param) => unreachable!(),
1589 StringSlice => TypeRootFilter::StringSlice,
1590 StringArray(_) => TypeRootFilter::StringArray,
1591 UnsignedInteger(x) => match x {
1592 IntegerBits::Eight => TypeRootFilter::U8,
1593 IntegerBits::Sixteen => TypeRootFilter::U16,
1594 IntegerBits::ThirtyTwo => TypeRootFilter::U32,
1595 IntegerBits::SixtyFour => TypeRootFilter::U64,
1596 IntegerBits::V256 => TypeRootFilter::U256,
1597 },
1598 Boolean => TypeRootFilter::Bool,
1599 Custom {
1600 qualified_call_path: call_path,
1601 ..
1602 } => TypeRootFilter::Custom(call_path.call_path.suffix.to_string()),
1603 B256 => TypeRootFilter::B256,
1604 Numeric => TypeRootFilter::U64, Contract => TypeRootFilter::Contract,
1606 ErrorRecovery(_) => TypeRootFilter::ErrorRecovery,
1607 Tuple(fields) => TypeRootFilter::Tuple(fields.len()),
1608 UntypedEnum(decl_id) => TypeRootFilter::Enum(*decl_id),
1609 UntypedStruct(decl_id) => TypeRootFilter::Struct(*decl_id),
1610 Enum(decl_id) => {
1611 TypeRootFilter::Enum(engines.de().get_parsed_decl_id(decl_id).unwrap())
1613 }
1614 Struct(decl_id) => {
1615 TypeRootFilter::Struct(engines.de().get_parsed_decl_id(decl_id).unwrap())
1617 }
1618 ContractCaller { abi_name, .. } => TypeRootFilter::ContractCaller(abi_name.to_string()),
1619 Array(_, _) => TypeRootFilter::Array,
1620 RawUntypedPtr => TypeRootFilter::RawUntypedPtr,
1621 RawUntypedSlice => TypeRootFilter::RawUntypedSlice,
1622 Ptr(_) => TypeRootFilter::Ptr,
1623 Slice(_) => TypeRootFilter::Slice,
1624 Alias { ty, .. } => Self::get_type_root_filter(engines, ty.type_id()),
1625 TraitType { name, .. } => TypeRootFilter::TraitType(name.to_string()),
1626 Ref {
1627 referenced_type, ..
1628 } => Self::get_type_root_filter(engines, referenced_type.type_id()),
1629 }
1630 }
1631}