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