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
166pub(crate) type TraitImpls = BTreeMap<TypeRootFilter, Vec<TraitEntry>>;
170
171#[derive(Clone, Hash, Eq, PartialOrd, Ord, PartialEq, Debug)]
172pub(crate) enum TypeRootFilter {
173 Unknown,
174 Never,
175 Placeholder,
176 StringSlice,
177 StringArray(usize),
178 U8,
179 U16,
180 U32,
181 U64,
182 U256,
183 Bool,
184 Custom(String),
185 B256,
186 Contract,
187 ErrorRecovery,
188 Tuple(usize),
189 Enum(ParsedDeclId<EnumDeclaration>),
190 Struct(ParsedDeclId<StructDeclaration>),
191 ContractCaller(String),
192 Array,
193 RawUntypedPtr,
194 RawUntypedSlice,
195 Ptr,
196 Slice,
197 TraitType(String),
198}
199
200#[derive(Clone, Debug, Default)]
205pub struct TraitMap {
206 pub(crate) trait_impls: TraitImpls,
207 satisfied_cache: HashSet<u64>,
208}
209
210pub(crate) enum IsImplSelf {
211 Yes,
212 No,
213}
214
215pub(crate) enum IsExtendingExistingImpl {
216 Yes,
217 No,
218}
219
220impl TraitMap {
221 #[allow(clippy::too_many_arguments)]
229 pub(crate) fn insert(
230 &mut self,
231 handler: &Handler,
232 trait_name: CallPath,
233 trait_type_args: Vec<GenericArgument>,
234 type_id: TypeId,
235 impl_type_parameters: Vec<TypeId>,
236 items: &[ResolvedTraitImplItem],
237 impl_span: &Span,
238 trait_decl_span: Option<Span>,
239 is_impl_self: IsImplSelf,
240 is_extending_existing_impl: IsExtendingExistingImpl,
241 engines: &Engines,
242 ) -> Result<(), ErrorEmitted> {
243 let unaliased_type_id = engines.te().get_unaliased_type_id(type_id);
244
245 handler.scope(|handler| {
246 let mut trait_items: TraitItems = BTreeMap::new();
247 for item in items.iter() {
248 match item {
249 ResolvedTraitImplItem::Parsed(_) => todo!(),
250 ResolvedTraitImplItem::Typed(ty_item) => match ty_item {
251 TyImplItem::Fn(decl_ref) => {
252 if trait_items
253 .insert(decl_ref.name().clone().to_string(), item.clone())
254 .is_some()
255 {
256 handler.emit_err(CompileError::MultipleDefinitionsOfName {
258 name: decl_ref.name().clone(),
259 span: decl_ref.span(),
260 });
261 }
262 }
263 TyImplItem::Constant(decl_ref) => {
264 trait_items.insert(decl_ref.name().to_string(), item.clone());
265 }
266 TyImplItem::Type(decl_ref) => {
267 trait_items.insert(decl_ref.name().to_string(), item.clone());
268 }
269 },
270 }
271 }
272
273 let trait_impls = self.get_impls_mut(engines, unaliased_type_id);
274
275 for TraitEntry {
277 key:
278 TraitKey {
279 name: map_trait_name,
280 type_id: map_type_id,
281 trait_decl_span: _,
282 impl_type_parameters: _,
283 },
284 value:
285 TraitValue {
286 trait_items: map_trait_items,
287 impl_span: existing_impl_span,
288 },
289 } in trait_impls.iter()
290 {
291 let CallPath {
292 suffix:
293 TraitSuffix {
294 name: map_trait_name_suffix,
295 args: map_trait_type_args,
296 },
297 ..
298 } = &*map_trait_name.clone();
299
300 let unify_checker = UnifyCheck::non_generic_constraint_subset(engines);
301
302 let types_are_subset = unify_checker.check(unaliased_type_id, *map_type_id)
306 && is_unified_type_subset(engines.te(), unaliased_type_id, *map_type_id);
307
308 fn is_unified_type_subset(
314 type_engine: &TypeEngine,
315 mut left: TypeId,
316 mut right: TypeId,
317 ) -> bool {
318 loop {
321 let left_ty_info = &*type_engine.get_unaliased(left);
322 let right_ty_info = &*type_engine.get_unaliased(right);
323 match (left_ty_info, right_ty_info) {
324 (
325 TypeInfo::Ref {
326 to_mutable_value: l_to_mut,
327 ..
328 },
329 TypeInfo::Ref {
330 to_mutable_value: r_to_mut,
331 ..
332 },
333 ) if *l_to_mut != *r_to_mut => return false, (
335 TypeInfo::Ref {
336 referenced_type: l_ty,
337 ..
338 },
339 TypeInfo::Ref {
340 referenced_type: r_ty,
341 ..
342 },
343 ) => {
344 left = l_ty.type_id();
345 right = r_ty.type_id();
346 }
347 _ => return true,
348 }
349 }
350 }
351
352 let mut traits_are_subset = true;
353 if *map_trait_name_suffix != trait_name.suffix
354 || map_trait_type_args.len() != trait_type_args.len()
355 {
356 traits_are_subset = false;
357 } else {
358 for (map_arg_type, arg_type) in
359 map_trait_type_args.iter().zip(trait_type_args.iter())
360 {
361 if !unify_checker.check(arg_type.type_id(), map_arg_type.type_id()) {
362 traits_are_subset = false;
363 }
364 }
365 }
366
367 if matches!(is_extending_existing_impl, IsExtendingExistingImpl::No)
368 && types_are_subset
369 && traits_are_subset
370 && matches!(is_impl_self, IsImplSelf::No)
371 {
372 handler.emit_err(CompileError::ConflictingImplsForTraitAndType {
373 trait_name: trait_name.to_string_with_args(engines, &trait_type_args),
374 type_implementing_for: engines.help_out(type_id).to_string(),
375 type_implementing_for_unaliased: engines
376 .help_out(unaliased_type_id)
377 .to_string(),
378 existing_impl_span: existing_impl_span.clone(),
379 second_impl_span: impl_span.clone(),
380 });
381 } else if types_are_subset
382 && (traits_are_subset || matches!(is_impl_self, IsImplSelf::Yes))
383 {
384 for name in trait_items.keys() {
385 let item = &trait_items[name];
386 match item {
387 ResolvedTraitImplItem::Parsed(_item) => todo!(),
388 ResolvedTraitImplItem::Typed(item) => match item {
389 ty::TyTraitItem::Fn(decl_ref) => {
390 if let Some(existing_item) = map_trait_items.get(name) {
391 handler.emit_err(
392 CompileError::DuplicateDeclDefinedForType {
393 decl_kind: "method".into(),
394 decl_name: decl_ref.name().to_string(),
395 type_implementing_for: engines
396 .help_out(type_id)
397 .to_string(),
398 type_implementing_for_unaliased: engines
399 .help_out(unaliased_type_id)
400 .to_string(),
401 existing_impl_span: existing_item
402 .span(engines)
403 .clone(),
404 second_impl_span: decl_ref.name().span(),
405 },
406 );
407 }
408 }
409 ty::TyTraitItem::Constant(decl_ref) => {
410 if let Some(existing_item) = map_trait_items.get(name) {
411 handler.emit_err(
412 CompileError::DuplicateDeclDefinedForType {
413 decl_kind: "constant".into(),
414 decl_name: decl_ref.name().to_string(),
415 type_implementing_for: engines
416 .help_out(type_id)
417 .to_string(),
418 type_implementing_for_unaliased: engines
419 .help_out(unaliased_type_id)
420 .to_string(),
421 existing_impl_span: existing_item
422 .span(engines)
423 .clone(),
424 second_impl_span: decl_ref.name().span(),
425 },
426 );
427 }
428 }
429 ty::TyTraitItem::Type(decl_ref) => {
430 if let Some(existing_item) = map_trait_items.get(name) {
431 handler.emit_err(
432 CompileError::DuplicateDeclDefinedForType {
433 decl_kind: "type".into(),
434 decl_name: decl_ref.name().to_string(),
435 type_implementing_for: engines
436 .help_out(type_id)
437 .to_string(),
438 type_implementing_for_unaliased: engines
439 .help_out(unaliased_type_id)
440 .to_string(),
441 existing_impl_span: existing_item
442 .span(engines)
443 .clone(),
444 second_impl_span: decl_ref.name().span(),
445 },
446 );
447 }
448 }
449 },
450 }
451 }
452 }
453 }
454 let trait_name: TraitName = Arc::new(CallPath {
455 prefixes: trait_name.prefixes,
456 suffix: TraitSuffix {
457 name: trait_name.suffix,
458 args: trait_type_args,
459 },
460 callpath_type: trait_name.callpath_type,
461 });
462
463 self.insert_inner(
465 trait_name,
466 impl_span.clone(),
467 trait_decl_span,
468 unaliased_type_id,
469 impl_type_parameters,
470 trait_items,
471 engines,
472 );
473
474 Ok(())
475 })
476 }
477
478 #[allow(clippy::too_many_arguments)]
479 fn insert_inner(
480 &mut self,
481 trait_name: TraitName,
482 impl_span: Span,
483 trait_decl_span: Option<Span>,
484 type_id: TypeId,
485 impl_type_parameters: Vec<TypeId>,
486 trait_methods: TraitItems,
487 engines: &Engines,
488 ) {
489 let key = TraitKey {
490 name: trait_name,
491 type_id,
492 trait_decl_span,
493 impl_type_parameters,
494 };
495 let value = TraitValue {
496 trait_items: trait_methods,
497 impl_span,
498 };
499 let entry = TraitEntry { key, value };
500 let mut trait_impls: TraitImpls = BTreeMap::<TypeRootFilter, Vec<TraitEntry>>::new();
501 let type_root_filter = Self::get_type_root_filter(engines, type_id);
502 let impls_vector = vec![entry];
503 trait_impls.insert(type_root_filter, impls_vector);
504
505 let trait_map = TraitMap {
506 trait_impls,
507 satisfied_cache: HashSet::default(),
508 };
509
510 self.extend(trait_map, engines);
511 }
512
513 pub(crate) fn extend(&mut self, other: TraitMap, engines: &Engines) {
516 for impls_key in other.trait_impls.keys() {
517 let oe_vec = &other.trait_impls[impls_key];
518 let self_vec = if let Some(self_vec) = self.trait_impls.get_mut(impls_key) {
519 self_vec
520 } else {
521 self.trait_impls
522 .insert(impls_key.clone(), Vec::<TraitEntry>::new());
523 self.trait_impls.get_mut(impls_key).unwrap()
524 };
525
526 for oe in oe_vec.iter() {
527 let pos = self_vec.binary_search_by(|se| {
528 se.key.cmp(&oe.key, &OrdWithEnginesContext::new(engines))
529 });
530
531 match pos {
532 Ok(pos) => self_vec[pos]
533 .value
534 .trait_items
535 .extend(oe.value.trait_items.clone()),
536 Err(pos) => self_vec.insert(pos, oe.clone()),
537 }
538 }
539 }
540 }
541
542 pub(crate) fn get_traits_types(
543 &self,
544 traits_types: &mut HashMap<CallPath, Vec<TypeId>>,
545 ) -> Result<(), ErrorEmitted> {
546 for key in self.trait_impls.keys() {
547 for self_entry in self.trait_impls[key].iter() {
548 let callpath = CallPath {
549 prefixes: self_entry.key.name.prefixes.clone(),
550 suffix: self_entry.key.name.suffix.name.clone(),
551 callpath_type: self_entry.key.name.callpath_type,
552 };
553 if let Some(vec) = traits_types.get_mut(&callpath) {
554 vec.push(self_entry.key.type_id);
555 } else {
556 traits_types.insert(callpath, vec![self_entry.key.type_id]);
557 }
558 }
559 }
560 Ok(())
561 }
562
563 pub(crate) fn filter_by_trait_decl_span(&self, trait_decl_span: Span) -> TraitMap {
566 let mut trait_map = TraitMap::default();
567 for key in self.trait_impls.keys() {
568 let vec = &self.trait_impls[key];
569 for entry in vec {
570 if entry.key.trait_decl_span.as_ref() == Some(&trait_decl_span) {
571 let trait_map_vec =
572 if let Some(trait_map_vec) = trait_map.trait_impls.get_mut(key) {
573 trait_map_vec
574 } else {
575 trait_map
576 .trait_impls
577 .insert(key.clone(), Vec::<TraitEntry>::new());
578 trait_map.trait_impls.get_mut(key).unwrap()
579 };
580
581 trait_map_vec.push(entry.clone());
582 }
583 }
584 }
585 trait_map
586 }
587
588 pub(crate) fn filter_by_type_item_import(
647 &self,
648 type_id: TypeId,
649 engines: &Engines,
650 ) -> TraitMap {
651 let unify_checker = UnifyCheck::constraint_subset(engines);
652 let unify_checker_for_item_import = UnifyCheck::non_generic_constraint_subset(engines);
653
654 let decider = |left: TypeId, right: TypeId| {
656 unify_checker.check(left, right) || unify_checker_for_item_import.check(right, left)
657 };
658 let mut trait_map = self.filter_by_type_inner(engines, vec![type_id], decider);
659 let all_types = type_id
660 .extract_inner_types(engines, IncludeSelf::No)
661 .into_iter()
662 .collect::<Vec<_>>();
663 let decider2 = |left: TypeId, right: TypeId| unify_checker.check(left, right);
665
666 trait_map.extend(
667 self.filter_by_type_inner(engines, all_types, decider2),
668 engines,
669 );
670 trait_map
671 }
672
673 fn filter_by_type_inner(
674 &self,
675 engines: &Engines,
676 mut all_types: Vec<TypeId>,
677 decider: impl Fn(TypeId, TypeId) -> bool,
678 ) -> TraitMap {
679 let type_engine = engines.te();
680 let mut trait_map = TraitMap::default();
681 for type_id in all_types.iter_mut() {
682 let type_info = type_engine.get(*type_id);
683 self.for_each_impls(
684 engines,
685 *type_id,
686 true,
687 |TraitEntry {
688 key:
689 TraitKey {
690 name: map_trait_name,
691 type_id: map_type_id,
692 trait_decl_span: map_trait_decl_span,
693 impl_type_parameters: map_impl_type_parameters,
694 },
695 value:
696 TraitValue {
697 trait_items: map_trait_items,
698 impl_span,
699 },
700 }| {
701 if !type_engine.is_type_changeable(engines, &type_info)
702 && *type_id == *map_type_id
703 {
704 trait_map.insert_inner(
705 map_trait_name.clone(),
706 impl_span.clone(),
707 map_trait_decl_span.clone(),
708 *type_id,
709 map_impl_type_parameters.clone(),
710 map_trait_items.clone(),
711 engines,
712 );
713 } else if decider(*type_id, *map_type_id) {
714 trait_map.insert_inner(
715 map_trait_name.clone(),
716 impl_span.clone(),
717 map_trait_decl_span.clone(),
718 *map_type_id,
719 map_impl_type_parameters.clone(),
720 Self::filter_dummy_methods(
721 map_trait_items,
722 *type_id,
723 *map_type_id,
724 engines,
725 )
726 .map(|(name, item)| (name.to_string(), item))
727 .collect(),
728 engines,
729 );
730 }
731 },
732 );
733 }
734 trait_map
735 }
736
737 fn filter_dummy_methods<'a>(
738 map_trait_items: &'a TraitItems,
739 type_id: TypeId,
740 map_type_id: TypeId,
741 engines: &'a Engines,
742 ) -> impl Iterator<Item = (&'a str, ResolvedTraitImplItem)> + 'a {
743 let maybe_is_from_type_parameter = engines.te().map(map_type_id, |x| match x {
744 TypeInfo::UnknownGeneric {
745 is_from_type_parameter,
746 ..
747 } => Some(*is_from_type_parameter),
748 _ => None,
749 });
750 let insertable = if let Some(is_from_type_parameter) = maybe_is_from_type_parameter {
751 !is_from_type_parameter
752 || matches!(*engines.te().get(type_id), TypeInfo::UnknownGeneric { .. })
753 } else {
754 true
755 };
756
757 map_trait_items
758 .iter()
759 .filter_map(move |(name, item)| match item {
760 ResolvedTraitImplItem::Parsed(_item) => todo!(),
761 ResolvedTraitImplItem::Typed(item) => match item {
762 ty::TyTraitItem::Fn(decl_ref) => engines.de().map(decl_ref.id(), |decl| {
763 if decl.is_trait_method_dummy && !insertable {
764 None
765 } else {
766 Some((
767 name.as_str(),
768 ResolvedTraitImplItem::Typed(TyImplItem::Fn(decl_ref.clone())),
769 ))
770 }
771 }),
772 ty::TyTraitItem::Constant(decl_ref) => Some((
773 name.as_str(),
774 ResolvedTraitImplItem::Typed(TyImplItem::Constant(decl_ref.clone())),
775 )),
776 ty::TyTraitItem::Type(decl_ref) => Some((
777 name.as_str(),
778 ResolvedTraitImplItem::Typed(TyImplItem::Type(decl_ref.clone())),
779 )),
780 },
781 })
782 }
783
784 fn make_item_for_type_mapping(
785 engines: &Engines,
786 item: ResolvedTraitImplItem,
787 mut type_mapping: TypeSubstMap,
788 type_id: TypeId,
789 code_block_first_pass: CodeBlockFirstPass,
790 ) -> ResolvedTraitImplItem {
791 let decl_engine = engines.de();
792 match &item {
793 ResolvedTraitImplItem::Parsed(_item) => todo!(),
794 ResolvedTraitImplItem::Typed(item) => match item {
795 ty::TyTraitItem::Fn(decl_ref) => {
796 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
797 if let Some(decl_implementing_for_typeid) = decl.implementing_for_typeid {
798 type_mapping.insert(decl_implementing_for_typeid, type_id);
799 }
800 decl.subst(&SubstTypesContext::new(
801 engines,
802 &type_mapping,
803 matches!(code_block_first_pass, CodeBlockFirstPass::No),
804 ));
805
806 let new_ref = decl_engine
807 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref())
808 .with_parent(decl_engine, decl_ref.id().into());
809
810 ResolvedTraitImplItem::Typed(TyImplItem::Fn(new_ref))
811 }
812 ty::TyTraitItem::Constant(decl_ref) => {
813 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
814 decl.subst(&SubstTypesContext::new(
815 engines,
816 &type_mapping,
817 matches!(code_block_first_pass, CodeBlockFirstPass::No),
818 ));
819 let new_ref = decl_engine
820 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref());
821 ResolvedTraitImplItem::Typed(TyImplItem::Constant(new_ref))
822 }
823 ty::TyTraitItem::Type(decl_ref) => {
824 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
825 decl.subst(&SubstTypesContext::new(
826 engines,
827 &type_mapping,
828 matches!(code_block_first_pass, CodeBlockFirstPass::No),
829 ));
830 let new_ref = decl_engine
831 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref());
832 ResolvedTraitImplItem::Typed(TyImplItem::Type(new_ref))
833 }
834 },
835 }
836 }
837
838 pub(crate) fn get_items_for_type(
848 module: &Module,
849 engines: &Engines,
850 type_id: TypeId,
851 ) -> Vec<ResolvedTraitImplItem> {
852 TraitMap::get_items_and_trait_key_for_type(module, engines, type_id)
853 .iter()
854 .map(|i| i.0.clone())
855 .collect::<Vec<_>>()
856 }
857
858 fn get_items_and_trait_key_for_type(
859 module: &Module,
860 engines: &Engines,
861 type_id: TypeId,
862 ) -> Vec<(ResolvedTraitImplItem, TraitKey)> {
863 let type_engine = engines.te();
864 let unify_check = UnifyCheck::constraint_subset(engines);
865
866 let type_id = engines.te().get_unaliased_type_id(type_id);
867
868 let mut items = vec![];
869 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
871 return items;
872 }
873
874 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
875 lexical_scope.items.implemented_traits.for_each_impls(
876 engines,
877 type_id,
878 true,
879 |entry| {
880 if unify_check.check(type_id, entry.key.type_id) {
881 let trait_items = Self::filter_dummy_methods(
882 &entry.value.trait_items,
883 type_id,
884 entry.key.type_id,
885 engines,
886 )
887 .map(|(_, i)| (i, entry.key.clone()))
888 .collect::<Vec<_>>();
889
890 items.extend(trait_items);
891 }
892 },
893 );
894
895 Ok(None::<()>)
896 });
897 items
898 }
899
900 pub fn get_impl_spans_for_type(
910 module: &Module,
911 engines: &Engines,
912 type_id: &TypeId,
913 ) -> Vec<Span> {
914 let type_engine = engines.te();
915 let unify_check = UnifyCheck::constraint_subset(engines);
916
917 let type_id = &engines.te().get_unaliased_type_id(*type_id);
918
919 let mut spans = vec![];
920 if matches!(&*type_engine.get(*type_id), TypeInfo::ErrorRecovery(_)) {
922 return spans;
923 }
924 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
925 lexical_scope.items.implemented_traits.for_each_impls(
926 engines,
927 *type_id,
928 false,
929 |entry| {
930 if unify_check.check(*type_id, entry.key.type_id) {
931 spans.push(entry.value.impl_span.clone());
932 }
933 },
934 );
935
936 Ok(None::<()>)
937 });
938
939 spans
940 }
941
942 pub fn get_impl_spans_for_decl(
944 module: &Module,
945 engines: &Engines,
946 ty_decl: &TyDecl,
947 ) -> Vec<Span> {
948 let handler = Handler::default();
949 ty_decl
950 .return_type(&handler, engines)
951 .map(|type_id| TraitMap::get_impl_spans_for_type(module, engines, &type_id))
952 .unwrap_or_default()
953 }
954
955 pub fn get_impl_spans_for_trait_name(module: &Module, trait_name: &CallPath) -> Vec<Span> {
958 let mut spans = vec![];
959 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
960 spans.push(
961 lexical_scope
962 .items
963 .implemented_traits
964 .trait_impls
965 .values()
966 .map(|impls| {
967 impls
968 .iter()
969 .filter_map(|entry| {
970 let map_trait_name = CallPath {
971 prefixes: entry.key.name.prefixes.clone(),
972 suffix: entry.key.name.suffix.name.clone(),
973 callpath_type: entry.key.name.callpath_type,
974 };
975 if &map_trait_name == trait_name {
976 Some(entry.value.impl_span.clone())
977 } else {
978 None
979 }
980 })
981 .collect::<Vec<Span>>()
982 })
983 .collect::<Vec<Vec<Span>>>()
984 .concat(),
985 );
986 Ok(None::<()>)
987 });
988
989 spans.concat()
990 }
991
992 pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments(
1003 module: &Module,
1004 engines: &Engines,
1005 type_id: TypeId,
1006 trait_name: &CallPath,
1007 trait_type_args: &[GenericArgument],
1008 ) -> Vec<ResolvedTraitImplItem> {
1009 let type_id = engines.te().get_unaliased_type_id(type_id);
1010
1011 let type_engine = engines.te();
1012 let unify_check = UnifyCheck::constraint_subset(engines);
1013 let mut items = vec![];
1014 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1016 return items;
1017 }
1018 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1019 lexical_scope
1020 .items
1021 .implemented_traits
1022 .for_each_impls(engines, type_id, false, |e| {
1023 let map_trait_name = CallPath {
1024 prefixes: e.key.name.prefixes.clone(),
1025 suffix: e.key.name.suffix.name.clone(),
1026 callpath_type: e.key.name.callpath_type,
1027 };
1028 if &map_trait_name == trait_name
1029 && unify_check.check(type_id, e.key.type_id)
1030 && trait_type_args.len() == e.key.name.suffix.args.len()
1031 && trait_type_args
1032 .iter()
1033 .zip(e.key.name.suffix.args.iter())
1034 .all(|(t1, t2)| unify_check.check(t1.type_id(), t2.type_id()))
1035 {
1036 let type_mapping =
1037 TypeSubstMap::from_superset_and_subset(engines, e.key.type_id, type_id);
1038
1039 let mut trait_items = Self::filter_dummy_methods(
1040 &e.value.trait_items,
1041 type_id,
1042 e.key.type_id,
1043 engines,
1044 )
1045 .map(|(_, i)| {
1046 Self::make_item_for_type_mapping(
1047 engines,
1048 i,
1049 type_mapping.clone(),
1050 type_id,
1051 CodeBlockFirstPass::No,
1052 )
1053 })
1054 .collect::<Vec<_>>();
1055
1056 items.append(&mut trait_items);
1057 }
1058 });
1059 Ok(None::<()>)
1060 });
1061 items
1062 }
1063
1064 pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments_typed(
1075 module: &Module,
1076 engines: &Engines,
1077 type_id: TypeId,
1078 trait_name: &CallPath,
1079 trait_type_args: &[GenericArgument],
1080 ) -> Vec<ty::TyTraitItem> {
1081 TraitMap::get_items_for_type_and_trait_name_and_trait_type_arguments(
1082 module,
1083 engines,
1084 type_id,
1085 trait_name,
1086 trait_type_args,
1087 )
1088 .into_iter()
1089 .map(|item| item.expect_typed())
1090 .collect::<Vec<_>>()
1091 }
1092
1093 pub(crate) fn get_trait_names_and_type_arguments_for_type(
1094 module: &Module,
1095 engines: &Engines,
1096 type_id: TypeId,
1097 ) -> Vec<(CallPath, Vec<GenericArgument>)> {
1098 let type_id = engines.te().get_unaliased_type_id(type_id);
1099
1100 let type_engine = engines.te();
1101 let unify_check = UnifyCheck::constraint_subset(engines);
1102 let mut trait_names = vec![];
1103 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1105 return trait_names;
1106 }
1107 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1108 lexical_scope.items.implemented_traits.for_each_impls(
1109 engines,
1110 type_id,
1111 false,
1112 |entry| {
1113 if unify_check.check(type_id, entry.key.type_id) {
1114 let trait_call_path = CallPath {
1115 prefixes: entry.key.name.prefixes.clone(),
1116 suffix: entry.key.name.suffix.name.clone(),
1117 callpath_type: entry.key.name.callpath_type,
1118 };
1119 trait_names.push((trait_call_path, entry.key.name.suffix.args.clone()));
1120 }
1121 },
1122 );
1123 Ok(None::<()>)
1124 });
1125 trait_names
1126 }
1127
1128 pub(crate) fn type_implements_trait<F: Fn(&TraitEntry) -> bool>(
1131 module: &Module,
1132 engines: &Engines,
1133 type_id: TypeId,
1134 predicate: F,
1135 ) -> bool {
1136 let type_id = engines.te().get_unaliased_type_id(type_id);
1137
1138 if matches!(&*engines.te().get(type_id), TypeInfo::ErrorRecovery(_)) {
1140 return false;
1141 }
1142
1143 let unify_check = UnifyCheck::constraint_subset(engines);
1144 let mut implements_trait = false;
1145 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1146 lexical_scope.items.implemented_traits.for_each_impls(
1147 engines,
1148 type_id,
1149 false,
1150 |entry| {
1151 if !implements_trait
1154 && unify_check.check(type_id, entry.key.type_id)
1155 && predicate(entry)
1156 {
1157 implements_trait = true;
1158 }
1159 },
1160 );
1161 Ok(None::<()>)
1162 });
1163 implements_trait
1164 }
1165
1166 pub(crate) fn get_trait_item_for_type(
1167 module: &Module,
1168 handler: &Handler,
1169 engines: &Engines,
1170 symbol: &Ident,
1171 type_id: TypeId,
1172 as_trait: Option<CallPath>,
1173 ) -> Result<ResolvedTraitImplItem, ErrorEmitted> {
1174 let type_id = engines.te().get_unaliased_type_id(type_id);
1175
1176 let mut candidates = HashMap::<String, ResolvedTraitImplItem>::new();
1177 for (trait_item, trait_key) in
1178 TraitMap::get_items_and_trait_key_for_type(module, engines, type_id)
1179 {
1180 match trait_item {
1181 ResolvedTraitImplItem::Parsed(impl_item) => match impl_item {
1182 ImplItem::Fn(fn_ref) => {
1183 let decl = engines.pe().get_function(&fn_ref);
1184 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1185 if decl.name.as_str() == symbol.as_str()
1186 && (as_trait.is_none()
1187 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1188 {
1189 candidates.insert(
1190 trait_call_path_string,
1191 ResolvedTraitImplItem::Parsed(ImplItem::Fn(fn_ref)),
1192 );
1193 }
1194 }
1195 ImplItem::Constant(const_ref) => {
1196 let decl = engines.pe().get_constant(&const_ref);
1197 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1198 if decl.name.as_str() == symbol.as_str()
1199 && (as_trait.is_none()
1200 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1201 {
1202 candidates.insert(
1203 trait_call_path_string,
1204 ResolvedTraitImplItem::Parsed(ImplItem::Constant(const_ref)),
1205 );
1206 }
1207 }
1208 ImplItem::Type(type_ref) => {
1209 let decl = engines.pe().get_trait_type(&type_ref);
1210 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1211 if decl.name.as_str() == symbol.as_str()
1212 && (as_trait.is_none()
1213 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1214 {
1215 candidates.insert(
1216 trait_call_path_string,
1217 ResolvedTraitImplItem::Parsed(ImplItem::Type(type_ref)),
1218 );
1219 }
1220 }
1221 },
1222 ResolvedTraitImplItem::Typed(ty_impl_item) => match ty_impl_item {
1223 ty::TyTraitItem::Fn(fn_ref) => {
1224 let decl = engines.de().get_function(&fn_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::Typed(TyTraitItem::Fn(fn_ref)),
1233 );
1234 }
1235 }
1236 ty::TyTraitItem::Constant(const_ref) => {
1237 let decl = engines.de().get_constant(&const_ref);
1238 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1239 if decl.call_path.suffix.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::Typed(TyTraitItem::Constant(const_ref)),
1246 );
1247 }
1248 }
1249 ty::TyTraitItem::Type(type_ref) => {
1250 let decl = engines.de().get_type(&type_ref);
1251 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1252 if decl.name.as_str() == symbol.as_str()
1253 && (as_trait.is_none()
1254 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1255 {
1256 candidates.insert(
1257 trait_call_path_string,
1258 ResolvedTraitImplItem::Typed(TyTraitItem::Type(type_ref)),
1259 );
1260 }
1261 }
1262 },
1263 }
1264 }
1265
1266 match candidates.len().cmp(&1) {
1267 Ordering::Greater => Err(handler.emit_err(
1268 CompileError::MultipleApplicableItemsInScope {
1269 item_name: symbol.as_str().to_string(),
1270 item_kind: "item".to_string(),
1271 as_traits: candidates
1272 .keys()
1273 .map(|k| {
1274 (
1275 k.clone()
1276 .split("::")
1277 .collect::<Vec<_>>()
1278 .last()
1279 .unwrap()
1280 .to_string(),
1281 engines.help_out(type_id).to_string(),
1282 )
1283 })
1284 .collect::<Vec<_>>(),
1285 span: symbol.span(),
1286 },
1287 )),
1288 Ordering::Less => Err(handler.emit_err(CompileError::SymbolNotFound {
1289 name: symbol.clone(),
1290 span: symbol.span(),
1291 })),
1292 Ordering::Equal => Ok(candidates.values().next().unwrap().clone()),
1293 }
1294 }
1295
1296 #[allow(clippy::too_many_arguments)]
1298 pub(crate) fn check_if_trait_constraints_are_satisfied_for_type(
1299 handler: &Handler,
1300 module: &mut Module,
1301 type_id: TypeId,
1302 constraints: &[TraitConstraint],
1303 access_span: &Span,
1304 engines: &Engines,
1305 ) -> Result<(), ErrorEmitted> {
1306 let type_engine = engines.te();
1307
1308 let type_id = type_engine.get_unaliased_type_id(type_id);
1309
1310 type_engine.decay_numeric(handler, engines, type_id, access_span)?;
1312
1313 if constraints.is_empty() {
1314 return Ok(());
1315 }
1316
1317 let mut hasher = DefaultHasher::default();
1319 type_id.hash(&mut hasher);
1320 for c in constraints {
1321 c.hash(&mut hasher, engines);
1322 }
1323 let hash = hasher.finish();
1324
1325 {
1326 let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1327 if trait_map.satisfied_cache.contains(&hash) {
1328 return Ok(());
1329 }
1330 }
1331
1332 let all_impld_traits: BTreeSet<(Ident, TypeId)> =
1333 Self::get_all_implemented_traits(module, type_id, engines);
1334
1335 match Self::check_if_trait_constraints_are_satisfied_for_type_inner(
1337 handler,
1338 type_id,
1339 constraints,
1340 access_span,
1341 engines,
1342 all_impld_traits,
1343 ) {
1344 Ok(()) => {
1345 let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1346 trait_map.satisfied_cache.insert(hash);
1347 Ok(())
1348 }
1349 r => r,
1350 }
1351 }
1352
1353 fn get_all_implemented_traits(
1354 module: &Module,
1355 type_id: TypeId,
1356 engines: &Engines,
1357 ) -> BTreeSet<(Ident, TypeId)> {
1358 let mut all_impld_traits: BTreeSet<(Ident, TypeId)> = Default::default();
1359 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1360 all_impld_traits.extend(
1361 lexical_scope
1362 .items
1363 .implemented_traits
1364 .get_implemented_traits(type_id, engines),
1365 );
1366 Ok(None::<()>)
1367 });
1368 all_impld_traits
1369 }
1370
1371 fn get_implemented_traits(
1372 &self,
1373 type_id: TypeId,
1374 engines: &Engines,
1375 ) -> BTreeSet<(Ident, TypeId)> {
1376 let type_engine = engines.te();
1377 let unify_check = UnifyCheck::constraint_subset(engines);
1378 let mut all_impld_traits = BTreeSet::<(Ident, TypeId)>::new();
1379 self.for_each_impls(engines, type_id, true, |e| {
1380 let key = &e.key;
1381 let suffix = &key.name.suffix;
1382 if unify_check.check(type_id, key.type_id) {
1383 let map_trait_type_id = type_engine.new_custom(
1384 engines,
1385 suffix.name.clone().into(),
1386 if suffix.args.is_empty() {
1387 None
1388 } else {
1389 Some(suffix.args.to_vec())
1390 },
1391 );
1392 all_impld_traits.insert((suffix.name.clone(), map_trait_type_id));
1393 }
1394 });
1395 all_impld_traits
1396 }
1397
1398 #[allow(clippy::too_many_arguments)]
1399 fn check_if_trait_constraints_are_satisfied_for_type_inner(
1400 handler: &Handler,
1401 type_id: TypeId,
1402 constraints: &[TraitConstraint],
1403 access_span: &Span,
1404 engines: &Engines,
1405 all_impld_traits: BTreeSet<(Ident, TypeId)>,
1406 ) -> Result<(), ErrorEmitted> {
1407 let type_engine = engines.te();
1408 let unify_check = UnifyCheck::constraint_subset(engines);
1409
1410 let required_traits: BTreeSet<(Ident, TypeId)> = constraints
1411 .iter()
1412 .map(|c| {
1413 let TraitConstraint {
1414 trait_name: constraint_trait_name,
1415 type_arguments: constraint_type_arguments,
1416 } = c;
1417 let constraint_type_id = type_engine.new_custom(
1418 engines,
1419 constraint_trait_name.suffix.clone().into(),
1420 if constraint_type_arguments.is_empty() {
1421 None
1422 } else {
1423 Some(constraint_type_arguments.clone())
1424 },
1425 );
1426 (c.trait_name.suffix.clone(), constraint_type_id)
1427 })
1428 .collect();
1429
1430 let traits_not_found: BTreeSet<(BaseIdent, TypeId)> = required_traits
1431 .into_iter()
1432 .filter(|(required_trait_name, required_trait_type_id)| {
1433 !all_impld_traits
1434 .iter()
1435 .any(|(trait_name, constraint_type_id)| {
1436 trait_name == required_trait_name
1437 && unify_check.check(*constraint_type_id, *required_trait_type_id)
1438 })
1439 })
1440 .collect();
1441
1442 handler.scope(|handler| {
1443 for (trait_name, constraint_type_id) in traits_not_found.iter() {
1444 let mut type_arguments_string = "".to_string();
1445 if let TypeInfo::Custom {
1446 qualified_call_path: _,
1447 type_arguments: Some(type_arguments),
1448 } = &*type_engine.get(*constraint_type_id)
1449 {
1450 type_arguments_string = format!("<{}>", engines.help_out(type_arguments));
1451 }
1452
1453 handler.emit_err(CompileError::TraitConstraintNotSatisfied {
1455 type_id: type_id.index(),
1456 ty: engines.help_out(type_id).to_string(),
1457 trait_name: format!("{}{}", trait_name, type_arguments_string),
1458 span: access_span.clone(),
1459 });
1460 }
1461
1462 Ok(())
1463 })
1464 }
1465
1466 pub fn get_trait_constraints_are_satisfied_for_types(
1467 module: &Module,
1468 _handler: &Handler,
1469 type_id: TypeId,
1470 constraints: &[TraitConstraint],
1471 engines: &Engines,
1472 ) -> Result<Vec<(TypeId, String)>, ErrorEmitted> {
1473 let type_id = engines.te().get_unaliased_type_id(type_id);
1474
1475 let _decl_engine = engines.de();
1476 let unify_check = UnifyCheck::coercion(engines);
1477 let unify_check_equality = UnifyCheck::constraint_subset(engines);
1478
1479 let mut impld_traits_type_ids: Vec<Vec<(TypeId, String)>> = vec![];
1480 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1481 lexical_scope
1482 .items
1483 .implemented_traits
1484 .for_each_impls(engines, type_id, true, |e| {
1485 let mut traits: Vec<(TypeId, String)> = vec![];
1486
1487 let key = &e.key;
1488 for constraint in constraints {
1489 if key.name.suffix.name == constraint.trait_name.suffix
1490 && key
1491 .name
1492 .suffix
1493 .args
1494 .iter()
1495 .zip(constraint.type_arguments.iter())
1496 .all(|(a1, a2)| {
1497 unify_check_equality.check(a1.type_id(), a2.type_id())
1498 })
1499 && unify_check.check(type_id, key.type_id)
1500 {
1501 let name_type_args = if !key.name.suffix.args.is_empty() {
1502 format!("<{}>", engines.help_out(key.name.suffix.args.clone()))
1503 } else {
1504 "".to_string()
1505 };
1506 let name =
1507 format!("{}{}", key.name.suffix.name.as_str(), name_type_args);
1508 traits.push((key.type_id, name));
1509 break;
1510 }
1511 }
1512 impld_traits_type_ids.push(traits);
1513 });
1514
1515 Ok(None::<()>)
1516 });
1517 Ok(impld_traits_type_ids.concat())
1518 }
1519
1520 fn get_impls_mut(&mut self, engines: &Engines, type_id: TypeId) -> &mut Vec<TraitEntry> {
1521 let type_root_filter = Self::get_type_root_filter(engines, type_id);
1522 if !self.trait_impls.contains_key(&type_root_filter) {
1523 self.trait_impls
1524 .insert(type_root_filter.clone(), Vec::new());
1525 }
1526
1527 self.trait_impls.get_mut(&type_root_filter).unwrap()
1528 }
1529
1530 pub(crate) fn for_each_impls<F>(
1531 &self,
1532 engines: &Engines,
1533 type_id: TypeId,
1534 include_placeholder: bool,
1535 mut callback: F,
1536 ) where
1537 F: FnMut(&TraitEntry),
1538 {
1539 let type_root_filter = Self::get_type_root_filter(engines, type_id);
1540 self.trait_impls
1541 .get(&type_root_filter)
1542 .iter()
1543 .for_each(|vec| vec.iter().for_each(&mut callback));
1544 if include_placeholder && type_root_filter != TypeRootFilter::Placeholder {
1545 self.trait_impls
1546 .get(&TypeRootFilter::Placeholder)
1547 .iter()
1548 .for_each(|vec| vec.iter().for_each(&mut callback));
1549 }
1550 }
1551
1552 fn get_type_root_filter(engines: &Engines, type_id: TypeId) -> TypeRootFilter {
1555 use TypeInfo::*;
1556 match &*engines.te().get(type_id) {
1557 Unknown => TypeRootFilter::Unknown,
1558 Never => TypeRootFilter::Never,
1559 UnknownGeneric { .. } | Placeholder(_) => TypeRootFilter::Placeholder,
1560 TypeParam(_param) => unreachable!(),
1561 StringSlice => TypeRootFilter::StringSlice,
1562 StringArray(x) => TypeRootFilter::StringArray(x.val()),
1563 UnsignedInteger(x) => match x {
1564 IntegerBits::Eight => TypeRootFilter::U8,
1565 IntegerBits::Sixteen => TypeRootFilter::U16,
1566 IntegerBits::ThirtyTwo => TypeRootFilter::U32,
1567 IntegerBits::SixtyFour => TypeRootFilter::U64,
1568 IntegerBits::V256 => TypeRootFilter::U256,
1569 },
1570 Boolean => TypeRootFilter::Bool,
1571 Custom {
1572 qualified_call_path: call_path,
1573 ..
1574 } => TypeRootFilter::Custom(call_path.call_path.suffix.to_string()),
1575 B256 => TypeRootFilter::B256,
1576 Numeric => TypeRootFilter::U64, Contract => TypeRootFilter::Contract,
1578 ErrorRecovery(_) => TypeRootFilter::ErrorRecovery,
1579 Tuple(fields) => TypeRootFilter::Tuple(fields.len()),
1580 UntypedEnum(decl_id) => TypeRootFilter::Enum(*decl_id),
1581 UntypedStruct(decl_id) => TypeRootFilter::Struct(*decl_id),
1582 Enum(decl_id) => {
1583 TypeRootFilter::Enum(engines.de().get_parsed_decl_id(decl_id).unwrap())
1585 }
1586 Struct(decl_id) => {
1587 TypeRootFilter::Struct(engines.de().get_parsed_decl_id(decl_id).unwrap())
1589 }
1590 ContractCaller { abi_name, .. } => TypeRootFilter::ContractCaller(abi_name.to_string()),
1591 Array(_, _) => TypeRootFilter::Array,
1592 RawUntypedPtr => TypeRootFilter::RawUntypedPtr,
1593 RawUntypedSlice => TypeRootFilter::RawUntypedSlice,
1594 Ptr(_) => TypeRootFilter::Ptr,
1595 Slice(_) => TypeRootFilter::Slice,
1596 Alias { ty, .. } => Self::get_type_root_filter(engines, ty.type_id()),
1597 TraitType { name, .. } => TypeRootFilter::TraitType(name.to_string()),
1598 Ref {
1599 referenced_type, ..
1600 } => Self::get_type_root_filter(engines, referenced_type.type_id()),
1601 }
1602 }
1603}