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, Vec<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(vec) = traits_types.get_mut(&callpath) {
599 vec.push(self_entry.inner.key.type_id);
600 } else {
601 traits_types.insert(callpath, vec![self_entry.inner.key.type_id]);
602 }
603 }
604 }
605 Ok(())
606 }
607
608 pub(crate) fn filter_by_trait_decl_span(&self, trait_decl_span: Span) -> TraitMap {
611 let mut trait_map = TraitMap::default();
612 for key in self.trait_impls.keys() {
613 let vec = &self.trait_impls[key];
614 for entry in vec {
615 if entry.inner.key.trait_decl_span.as_ref() == Some(&trait_decl_span) {
616 let trait_map_vec =
617 if let Some(trait_map_vec) = trait_map.trait_impls.get_mut(key) {
618 trait_map_vec
619 } else {
620 trait_map.trait_impls.insert(key.clone(), Vec::<_>::new());
621 trait_map.trait_impls.get_mut(key).unwrap()
622 };
623
624 trait_map_vec.push(entry.clone());
625 }
626 }
627 }
628 trait_map
629 }
630
631 pub(crate) fn filter_by_type_item_import(
690 &self,
691 type_id: TypeId,
692 engines: &Engines,
693 ) -> TraitMap {
694 let unify_checker = UnifyCheck::constraint_subset(engines);
695 let unify_checker_for_item_import = UnifyCheck::non_generic_constraint_subset(engines);
696
697 let decider = |left: TypeId, right: TypeId| {
699 unify_checker.check(left, right) || unify_checker_for_item_import.check(right, left)
700 };
701 let mut trait_map = self.filter_by_type_inner(engines, vec![type_id], decider);
702 let all_types = type_id
703 .extract_inner_types(engines, IncludeSelf::No)
704 .into_iter()
705 .collect::<Vec<_>>();
706 let decider2 = |left: TypeId, right: TypeId| unify_checker.check(left, right);
708
709 trait_map.extend(
710 self.filter_by_type_inner(engines, all_types, decider2),
711 engines,
712 );
713 trait_map
714 }
715
716 fn filter_by_type_inner(
717 &self,
718 engines: &Engines,
719 mut all_types: Vec<TypeId>,
720 decider: impl Fn(TypeId, TypeId) -> bool,
721 ) -> TraitMap {
722 let type_engine = engines.te();
723 let mut trait_map = TraitMap::default();
724 for type_id in all_types.iter_mut() {
725 let type_info = type_engine.get(*type_id);
726 self.for_each_impls(engines, *type_id, true, |entry| {
727 let TraitEntry {
728 key:
729 TraitKey {
730 name: map_trait_name,
731 type_id: map_type_id,
732 trait_decl_span: map_trait_decl_span,
733 impl_type_parameters: map_impl_type_parameters,
734 is_impl_interface_surface: _,
735 },
736 value:
737 TraitValue {
738 trait_items: map_trait_items,
739 impl_span,
740 },
741 } = entry.inner.as_ref();
742
743 if !type_engine.is_type_changeable(engines, &type_info) && *type_id == *map_type_id
744 {
745 trait_map.insert_inner(
746 map_trait_name.clone(),
747 impl_span.clone(),
748 map_trait_decl_span.clone(),
749 *type_id,
750 map_impl_type_parameters.clone(),
751 map_trait_items.clone(),
752 IsImplInterfaceSurface::No,
753 engines,
754 );
755 } else if decider(*type_id, *map_type_id) {
756 trait_map.insert_inner(
757 map_trait_name.clone(),
758 impl_span.clone(),
759 map_trait_decl_span.clone(),
760 *map_type_id,
761 map_impl_type_parameters.clone(),
762 Self::filter_dummy_methods(
763 map_trait_items,
764 *type_id,
765 *map_type_id,
766 engines,
767 )
768 .map(|(name, item)| (name.to_string(), item))
769 .collect(),
770 IsImplInterfaceSurface::No,
771 engines,
772 );
773 }
774 });
775 }
776 trait_map
777 }
778
779 fn filter_dummy_methods<'a>(
780 map_trait_items: &'a TraitItems,
781 type_id: TypeId,
782 map_type_id: TypeId,
783 engines: &'a Engines,
784 ) -> impl Iterator<Item = (&'a str, ResolvedTraitImplItem)> + 'a {
785 let maybe_is_from_type_parameter = engines.te().map(map_type_id, |x| match x {
786 TypeInfo::UnknownGeneric {
787 is_from_type_parameter,
788 ..
789 } => Some(*is_from_type_parameter),
790 _ => None,
791 });
792 let insertable = if let Some(is_from_type_parameter) = maybe_is_from_type_parameter {
793 !is_from_type_parameter
794 || matches!(*engines.te().get(type_id), TypeInfo::UnknownGeneric { .. })
795 } else {
796 true
797 };
798
799 map_trait_items
800 .iter()
801 .filter_map(move |(name, item)| match item {
802 ResolvedTraitImplItem::Parsed(_item) => todo!(),
803 ResolvedTraitImplItem::Typed(item) => match item {
804 ty::TyTraitItem::Fn(decl_ref) => engines.de().map(decl_ref.id(), |decl| {
805 if decl.is_trait_method_dummy && !insertable {
806 None
807 } else {
808 Some((
809 name.as_str(),
810 ResolvedTraitImplItem::Typed(TyImplItem::Fn(decl_ref.clone())),
811 ))
812 }
813 }),
814 ty::TyTraitItem::Constant(decl_ref) => Some((
815 name.as_str(),
816 ResolvedTraitImplItem::Typed(TyImplItem::Constant(decl_ref.clone())),
817 )),
818 ty::TyTraitItem::Type(decl_ref) => Some((
819 name.as_str(),
820 ResolvedTraitImplItem::Typed(TyImplItem::Type(decl_ref.clone())),
821 )),
822 },
823 })
824 }
825
826 fn make_item_for_type_mapping(
827 engines: &Engines,
828 item: ResolvedTraitImplItem,
829 mut type_mapping: TypeSubstMap,
830 type_id: TypeId,
831 code_block_first_pass: CodeBlockFirstPass,
832 ) -> ResolvedTraitImplItem {
833 let decl_engine = engines.de();
834 match &item {
835 ResolvedTraitImplItem::Parsed(_item) => todo!(),
836 ResolvedTraitImplItem::Typed(item) => match item {
837 ty::TyTraitItem::Fn(decl_ref) => {
838 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
839 if let Some(decl_implementing_for_typeid) = decl.implementing_for_typeid {
840 type_mapping.insert(decl_implementing_for_typeid, type_id);
841 }
842 decl.subst(&SubstTypesContext::new(
843 engines,
844 &type_mapping,
845 matches!(code_block_first_pass, CodeBlockFirstPass::No),
846 ));
847
848 let new_ref = decl_engine
849 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref())
850 .with_parent(decl_engine, decl_ref.id().into());
851
852 ResolvedTraitImplItem::Typed(TyImplItem::Fn(new_ref))
853 }
854 ty::TyTraitItem::Constant(decl_ref) => {
855 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
856 decl.subst(&SubstTypesContext::new(
857 engines,
858 &type_mapping,
859 matches!(code_block_first_pass, CodeBlockFirstPass::No),
860 ));
861 let new_ref = decl_engine
862 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref());
863 ResolvedTraitImplItem::Typed(TyImplItem::Constant(new_ref))
864 }
865 ty::TyTraitItem::Type(decl_ref) => {
866 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
867 decl.subst(&SubstTypesContext::new(
868 engines,
869 &type_mapping,
870 matches!(code_block_first_pass, CodeBlockFirstPass::No),
871 ));
872 let new_ref = decl_engine
873 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref());
874 ResolvedTraitImplItem::Typed(TyImplItem::Type(new_ref))
875 }
876 },
877 }
878 }
879
880 pub(crate) fn append_items_for_type(
890 module: &Module,
891 engines: &Engines,
892 type_id: TypeId,
893 items: &mut Vec<ResolvedTraitImplItem>,
894 ) {
895 TraitMap::find_items_and_trait_key_for_type(module, engines, type_id, &mut |item, _| {
896 items.push(item);
897 });
898 }
899
900 pub(crate) fn find_items_and_trait_key_for_type(
901 module: &Module,
902 engines: &Engines,
903 type_id: TypeId,
904 callback: &mut impl FnMut(ResolvedTraitImplItem, TraitKey),
905 ) {
906 let type_engine = engines.te();
907 let type_id = engines.te().get_unaliased_type_id(type_id);
908
909 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
911 return;
912 }
913
914 let unify_check = UnifyCheck::constraint_subset(engines);
915
916 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
917 lexical_scope.items.implemented_traits.for_each_impls(
918 engines,
919 type_id,
920 true,
921 |entry| {
922 if unify_check.check(type_id, entry.inner.key.type_id) {
923 let trait_items = Self::filter_dummy_methods(
924 &entry.inner.value.trait_items,
925 type_id,
926 entry.inner.key.type_id,
927 engines,
928 )
929 .map(|(_, i)| (i, entry.inner.key.clone()));
930
931 for i in trait_items {
932 callback(i.0, i.1);
933 }
934 }
935 },
936 );
937
938 Ok(None::<()>)
939 });
940 }
941
942 pub fn get_impl_spans_for_type(
952 module: &Module,
953 engines: &Engines,
954 type_id: &TypeId,
955 ) -> Vec<Span> {
956 let type_engine = engines.te();
957 let unify_check = UnifyCheck::constraint_subset(engines);
958
959 let type_id = &engines.te().get_unaliased_type_id(*type_id);
960
961 let mut spans = vec![];
962 if matches!(&*type_engine.get(*type_id), TypeInfo::ErrorRecovery(_)) {
964 return spans;
965 }
966 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
967 lexical_scope.items.implemented_traits.for_each_impls(
968 engines,
969 *type_id,
970 false,
971 |entry| {
972 if unify_check.check(*type_id, entry.inner.key.type_id) {
973 spans.push(entry.inner.value.impl_span.clone());
974 }
975 },
976 );
977
978 Ok(None::<()>)
979 });
980
981 spans
982 }
983
984 pub fn get_impl_spans_for_decl(
986 module: &Module,
987 engines: &Engines,
988 ty_decl: &TyDecl,
989 ) -> Vec<Span> {
990 let handler = Handler::default();
991 ty_decl
992 .return_type(&handler, engines)
993 .map(|type_id| TraitMap::get_impl_spans_for_type(module, engines, &type_id))
994 .unwrap_or_default()
995 }
996
997 pub fn get_impl_spans_for_trait_name(module: &Module, trait_name: &CallPath) -> Vec<Span> {
1000 let mut spans = vec![];
1001 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1002 spans.push(
1003 lexical_scope
1004 .items
1005 .implemented_traits
1006 .trait_impls
1007 .values()
1008 .map(|impls| {
1009 impls
1010 .iter()
1011 .filter_map(|entry| {
1012 let map_trait_name = CallPath {
1013 prefixes: entry.inner.key.name.prefixes.clone(),
1014 suffix: entry.inner.key.name.suffix.name.clone(),
1015 callpath_type: entry.inner.key.name.callpath_type,
1016 };
1017 if &map_trait_name == trait_name {
1018 Some(entry.inner.value.impl_span.clone())
1019 } else {
1020 None
1021 }
1022 })
1023 .collect::<Vec<Span>>()
1024 })
1025 .collect::<Vec<Vec<Span>>>()
1026 .concat(),
1027 );
1028 Ok(None::<()>)
1029 });
1030
1031 spans.concat()
1032 }
1033
1034 pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments(
1045 module: &Module,
1046 engines: &Engines,
1047 type_id: TypeId,
1048 trait_name: &CallPath,
1049 trait_type_args: &[GenericArgument],
1050 ) -> Vec<ResolvedTraitImplItem> {
1051 let type_id = engines.te().get_unaliased_type_id(type_id);
1052
1053 let type_engine = engines.te();
1054 let unify_check = UnifyCheck::constraint_subset(engines);
1055 let mut items = vec![];
1056 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1058 return items;
1059 }
1060 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1061 lexical_scope
1062 .items
1063 .implemented_traits
1064 .for_each_impls(engines, type_id, false, |e| {
1065 let map_trait_name = CallPath {
1066 prefixes: e.inner.key.name.prefixes.clone(),
1067 suffix: e.inner.key.name.suffix.name.clone(),
1068 callpath_type: e.inner.key.name.callpath_type,
1069 };
1070 if &map_trait_name == trait_name
1071 && unify_check.check(type_id, e.inner.key.type_id)
1072 && trait_type_args.len() == e.inner.key.name.suffix.args.len()
1073 && trait_type_args
1074 .iter()
1075 .zip(e.inner.key.name.suffix.args.iter())
1076 .all(|(t1, t2)| unify_check.check(t1.type_id(), t2.type_id()))
1077 {
1078 let type_mapping = TypeSubstMap::from_superset_and_subset(
1079 engines,
1080 e.inner.key.type_id,
1081 type_id,
1082 );
1083
1084 let mut trait_items = Self::filter_dummy_methods(
1085 &e.inner.value.trait_items,
1086 type_id,
1087 e.inner.key.type_id,
1088 engines,
1089 )
1090 .map(|(_, i)| {
1091 Self::make_item_for_type_mapping(
1092 engines,
1093 i,
1094 type_mapping.clone(),
1095 type_id,
1096 CodeBlockFirstPass::No,
1097 )
1098 })
1099 .collect::<Vec<_>>();
1100
1101 items.append(&mut trait_items);
1102 }
1103 });
1104 Ok(None::<()>)
1105 });
1106 items
1107 }
1108
1109 pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments_typed(
1120 module: &Module,
1121 engines: &Engines,
1122 type_id: TypeId,
1123 trait_name: &CallPath,
1124 trait_type_args: &[GenericArgument],
1125 ) -> Vec<ty::TyTraitItem> {
1126 TraitMap::get_items_for_type_and_trait_name_and_trait_type_arguments(
1127 module,
1128 engines,
1129 type_id,
1130 trait_name,
1131 trait_type_args,
1132 )
1133 .into_iter()
1134 .map(|item| item.expect_typed())
1135 .collect::<Vec<_>>()
1136 }
1137
1138 pub(crate) fn get_trait_names_and_type_arguments_for_type(
1139 module: &Module,
1140 engines: &Engines,
1141 type_id: TypeId,
1142 ) -> Vec<(CallPath, Vec<GenericArgument>)> {
1143 let type_id = engines.te().get_unaliased_type_id(type_id);
1144
1145 let type_engine = engines.te();
1146 let unify_check = UnifyCheck::constraint_subset(engines);
1147 let mut trait_names = vec![];
1148 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1150 return trait_names;
1151 }
1152 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1153 lexical_scope.items.implemented_traits.for_each_impls(
1154 engines,
1155 type_id,
1156 false,
1157 |entry| {
1158 if unify_check.check(type_id, entry.inner.key.type_id) {
1159 let trait_call_path = CallPath {
1160 prefixes: entry.inner.key.name.prefixes.clone(),
1161 suffix: entry.inner.key.name.suffix.name.clone(),
1162 callpath_type: entry.inner.key.name.callpath_type,
1163 };
1164 trait_names
1165 .push((trait_call_path, entry.inner.key.name.suffix.args.clone()));
1166 }
1167 },
1168 );
1169 Ok(None::<()>)
1170 });
1171 trait_names
1172 }
1173
1174 pub(crate) fn type_implements_trait<F: Fn(&SharedTraitEntry) -> bool>(
1177 module: &Module,
1178 engines: &Engines,
1179 type_id: TypeId,
1180 predicate: F,
1181 ) -> bool {
1182 let type_id = engines.te().get_unaliased_type_id(type_id);
1183
1184 if matches!(&*engines.te().get(type_id), TypeInfo::ErrorRecovery(_)) {
1186 return false;
1187 }
1188
1189 let unify_check = UnifyCheck::constraint_subset(engines);
1190 let mut implements_trait = false;
1191 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1192 lexical_scope.items.implemented_traits.for_each_impls(
1193 engines,
1194 type_id,
1195 false,
1196 |entry| {
1197 if !implements_trait
1200 && unify_check.check(type_id, entry.inner.key.type_id)
1201 && predicate(entry)
1202 {
1203 implements_trait = true;
1204 }
1205 },
1206 );
1207 Ok(None::<()>)
1208 });
1209 implements_trait
1210 }
1211
1212 pub(crate) fn get_trait_item_for_type(
1213 module: &Module,
1214 handler: &Handler,
1215 engines: &Engines,
1216 symbol: &Ident,
1217 type_id: TypeId,
1218 as_trait: Option<CallPath>,
1219 ) -> Result<ResolvedTraitImplItem, ErrorEmitted> {
1220 let type_id = engines.te().get_unaliased_type_id(type_id);
1221
1222 let mut candidates = HashMap::<String, ResolvedTraitImplItem>::new();
1223
1224 TraitMap::find_items_and_trait_key_for_type(
1225 module,
1226 engines,
1227 type_id,
1228 &mut |trait_item, trait_key| match trait_item {
1229 ResolvedTraitImplItem::Parsed(impl_item) => match impl_item {
1230 ImplItem::Fn(fn_ref) => {
1231 let decl = engines.pe().get_function(&fn_ref);
1232 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1233 if decl.name.as_str() == symbol.as_str()
1234 && (as_trait.is_none()
1235 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1236 {
1237 candidates.insert(
1238 trait_call_path_string,
1239 ResolvedTraitImplItem::Parsed(ImplItem::Fn(fn_ref)),
1240 );
1241 }
1242 }
1243 ImplItem::Constant(const_ref) => {
1244 let decl = engines.pe().get_constant(&const_ref);
1245 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1246 if decl.name.as_str() == symbol.as_str()
1247 && (as_trait.is_none()
1248 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1249 {
1250 candidates.insert(
1251 trait_call_path_string,
1252 ResolvedTraitImplItem::Parsed(ImplItem::Constant(const_ref)),
1253 );
1254 }
1255 }
1256 ImplItem::Type(type_ref) => {
1257 let decl = engines.pe().get_trait_type(&type_ref);
1258 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1259 if decl.name.as_str() == symbol.as_str()
1260 && (as_trait.is_none()
1261 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1262 {
1263 candidates.insert(
1264 trait_call_path_string,
1265 ResolvedTraitImplItem::Parsed(ImplItem::Type(type_ref)),
1266 );
1267 }
1268 }
1269 },
1270 ResolvedTraitImplItem::Typed(ty_impl_item) => match ty_impl_item {
1271 ty::TyTraitItem::Fn(fn_ref) => {
1272 let decl = engines.de().get_function(&fn_ref);
1273 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1274 if decl.name.as_str() == symbol.as_str()
1275 && (as_trait.is_none()
1276 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1277 {
1278 candidates.insert(
1279 trait_call_path_string,
1280 ResolvedTraitImplItem::Typed(TyTraitItem::Fn(fn_ref)),
1281 );
1282 }
1283 }
1284 ty::TyTraitItem::Constant(const_ref) => {
1285 let decl = engines.de().get_constant(&const_ref);
1286 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1287 if decl.call_path.suffix.as_str() == symbol.as_str()
1288 && (as_trait.is_none()
1289 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1290 {
1291 candidates.insert(
1292 trait_call_path_string,
1293 ResolvedTraitImplItem::Typed(TyTraitItem::Constant(const_ref)),
1294 );
1295 }
1296 }
1297 ty::TyTraitItem::Type(type_ref) => {
1298 let decl = engines.de().get_type(&type_ref);
1299 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1300 if decl.name.as_str() == symbol.as_str()
1301 && (as_trait.is_none()
1302 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1303 {
1304 candidates.insert(
1305 trait_call_path_string,
1306 ResolvedTraitImplItem::Typed(TyTraitItem::Type(type_ref)),
1307 );
1308 }
1309 }
1310 },
1311 },
1312 );
1313
1314 match candidates.len().cmp(&1) {
1315 Ordering::Greater => Err(handler.emit_err(
1316 CompileError::MultipleApplicableItemsInScope {
1317 item_name: symbol.as_str().to_string(),
1318 item_kind: "item".to_string(),
1319 as_traits: candidates
1320 .keys()
1321 .map(|k| {
1322 (
1323 k.clone()
1324 .split("::")
1325 .collect::<Vec<_>>()
1326 .last()
1327 .unwrap()
1328 .to_string(),
1329 engines.help_out(type_id).to_string(),
1330 )
1331 })
1332 .collect::<Vec<_>>(),
1333 span: symbol.span(),
1334 },
1335 )),
1336 Ordering::Less => Err(handler.emit_err(CompileError::SymbolNotFound {
1337 name: symbol.clone(),
1338 span: symbol.span(),
1339 })),
1340 Ordering::Equal => Ok(candidates.values().next().unwrap().clone()),
1341 }
1342 }
1343
1344 #[allow(clippy::too_many_arguments)]
1346 pub(crate) fn check_if_trait_constraints_are_satisfied_for_type(
1347 handler: &Handler,
1348 module: &mut Module,
1349 type_id: TypeId,
1350 constraints: &[TraitConstraint],
1351 access_span: &Span,
1352 engines: &Engines,
1353 ) -> Result<(), ErrorEmitted> {
1354 let type_engine = engines.te();
1355
1356 let type_id = type_engine.get_unaliased_type_id(type_id);
1357
1358 type_engine.decay_numeric(handler, engines, type_id, access_span)?;
1360
1361 if constraints.is_empty() {
1362 return Ok(());
1363 }
1364
1365 let mut hasher = DefaultHasher::default();
1367 type_id.hash(&mut hasher);
1368 for c in constraints {
1369 c.hash(&mut hasher, engines);
1370 }
1371 let hash = hasher.finish();
1372
1373 {
1374 let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1375 if trait_map.satisfied_cache.contains(&hash) {
1376 return Ok(());
1377 }
1378 }
1379
1380 let all_impld_traits: BTreeSet<(Ident, TypeId)> =
1381 Self::get_all_implemented_traits(module, type_id, engines);
1382
1383 match Self::check_if_trait_constraints_are_satisfied_for_type_inner(
1385 handler,
1386 type_id,
1387 constraints,
1388 access_span,
1389 engines,
1390 all_impld_traits,
1391 ) {
1392 Ok(()) => {
1393 let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1394 trait_map.satisfied_cache.insert(hash);
1395 Ok(())
1396 }
1397 r => r,
1398 }
1399 }
1400
1401 fn get_all_implemented_traits(
1402 module: &Module,
1403 type_id: TypeId,
1404 engines: &Engines,
1405 ) -> BTreeSet<(Ident, TypeId)> {
1406 let mut all_impld_traits: BTreeSet<(Ident, TypeId)> = Default::default();
1407 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1408 all_impld_traits.extend(
1409 lexical_scope
1410 .items
1411 .implemented_traits
1412 .get_implemented_traits(type_id, engines),
1413 );
1414 Ok(None::<()>)
1415 });
1416 all_impld_traits
1417 }
1418
1419 fn get_implemented_traits(
1420 &self,
1421 type_id: TypeId,
1422 engines: &Engines,
1423 ) -> BTreeSet<(Ident, TypeId)> {
1424 let type_engine = engines.te();
1425 let unify_check = UnifyCheck::constraint_subset(engines);
1426 let mut all_impld_traits = BTreeSet::<(Ident, TypeId)>::new();
1427 self.for_each_impls(engines, type_id, true, |e| {
1428 let key = &e.inner.key;
1429 let suffix = &key.name.suffix;
1430 if unify_check.check(type_id, key.type_id) {
1431 let map_trait_type_id = type_engine.new_custom(
1432 engines,
1433 suffix.name.clone().into(),
1434 if suffix.args.is_empty() {
1435 None
1436 } else {
1437 Some(suffix.args.to_vec())
1438 },
1439 );
1440 all_impld_traits.insert((suffix.name.clone(), map_trait_type_id));
1441 }
1442 });
1443 all_impld_traits
1444 }
1445
1446 #[allow(clippy::too_many_arguments)]
1447 fn check_if_trait_constraints_are_satisfied_for_type_inner(
1448 handler: &Handler,
1449 type_id: TypeId,
1450 constraints: &[TraitConstraint],
1451 access_span: &Span,
1452 engines: &Engines,
1453 all_impld_traits: BTreeSet<(Ident, TypeId)>,
1454 ) -> Result<(), ErrorEmitted> {
1455 let type_engine = engines.te();
1456 let unify_check = UnifyCheck::constraint_subset(engines);
1457
1458 let required_traits: BTreeSet<(Ident, TypeId)> = constraints
1459 .iter()
1460 .map(|c| {
1461 let TraitConstraint {
1462 trait_name: constraint_trait_name,
1463 type_arguments: constraint_type_arguments,
1464 } = c;
1465 let constraint_type_id = type_engine.new_custom(
1466 engines,
1467 constraint_trait_name.suffix.clone().into(),
1468 if constraint_type_arguments.is_empty() {
1469 None
1470 } else {
1471 Some(constraint_type_arguments.clone())
1472 },
1473 );
1474 (c.trait_name.suffix.clone(), constraint_type_id)
1475 })
1476 .collect();
1477
1478 let traits_not_found: BTreeSet<(BaseIdent, TypeId)> = required_traits
1479 .into_iter()
1480 .filter(|(required_trait_name, required_trait_type_id)| {
1481 !all_impld_traits
1482 .iter()
1483 .any(|(trait_name, constraint_type_id)| {
1484 trait_name == required_trait_name
1485 && unify_check.check(*constraint_type_id, *required_trait_type_id)
1486 })
1487 })
1488 .collect();
1489
1490 handler.scope(|handler| {
1491 for (trait_name, constraint_type_id) in traits_not_found.iter() {
1492 let mut type_arguments_string = "".to_string();
1493 if let TypeInfo::Custom {
1494 qualified_call_path: _,
1495 type_arguments: Some(type_arguments),
1496 } = &*type_engine.get(*constraint_type_id)
1497 {
1498 type_arguments_string = format!("<{}>", engines.help_out(type_arguments));
1499 }
1500
1501 handler.emit_err(CompileError::TraitConstraintNotSatisfied {
1503 type_id: type_id.index(),
1504 ty: engines.help_out(type_id).to_string(),
1505 trait_name: format!("{}{}", trait_name, type_arguments_string),
1506 span: access_span.clone(),
1507 });
1508 }
1509
1510 Ok(())
1511 })
1512 }
1513
1514 pub fn get_trait_constraints_are_satisfied_for_types(
1515 module: &Module,
1516 _handler: &Handler,
1517 type_id: TypeId,
1518 constraints: &[TraitConstraint],
1519 engines: &Engines,
1520 ) -> Result<Vec<(TypeId, String)>, ErrorEmitted> {
1521 let type_id = engines.te().get_unaliased_type_id(type_id);
1522
1523 let _decl_engine = engines.de();
1524 let unify_check = UnifyCheck::coercion(engines);
1525 let unify_check_equality = UnifyCheck::constraint_subset(engines);
1526
1527 let mut impld_traits_type_ids: Vec<Vec<(TypeId, String)>> = vec![];
1528 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1529 lexical_scope
1530 .items
1531 .implemented_traits
1532 .for_each_impls(engines, type_id, true, |e| {
1533 let mut traits: Vec<(TypeId, String)> = vec![];
1534
1535 let key = &e.inner.key;
1536 for constraint in constraints {
1537 if key.name.suffix.name == constraint.trait_name.suffix
1538 && key
1539 .name
1540 .suffix
1541 .args
1542 .iter()
1543 .zip(constraint.type_arguments.iter())
1544 .all(|(a1, a2)| {
1545 unify_check_equality.check(a1.type_id(), a2.type_id())
1546 })
1547 && unify_check.check(type_id, key.type_id)
1548 {
1549 let name_type_args = if !key.name.suffix.args.is_empty() {
1550 format!("<{}>", engines.help_out(key.name.suffix.args.clone()))
1551 } else {
1552 "".to_string()
1553 };
1554 let name =
1555 format!("{}{}", key.name.suffix.name.as_str(), name_type_args);
1556 traits.push((key.type_id, name));
1557 break;
1558 }
1559 }
1560 impld_traits_type_ids.push(traits);
1561 });
1562
1563 Ok(None::<()>)
1564 });
1565 Ok(impld_traits_type_ids.concat())
1566 }
1567
1568 fn get_impls_mut(&mut self, engines: &Engines, type_id: TypeId) -> &mut Vec<SharedTraitEntry> {
1569 let type_root_filter = Self::get_type_root_filter(engines, type_id);
1570 if !self.trait_impls.contains_key(&type_root_filter) {
1571 self.trait_impls
1572 .insert(type_root_filter.clone(), Vec::new());
1573 }
1574
1575 self.trait_impls.get_mut(&type_root_filter).unwrap()
1576 }
1577
1578 pub(crate) fn for_each_impls<F>(
1579 &self,
1580 engines: &Engines,
1581 type_id: TypeId,
1582 include_placeholder: bool,
1583 mut callback: F,
1584 ) where
1585 F: FnMut(&SharedTraitEntry),
1586 {
1587 let type_root_filter = Self::get_type_root_filter(engines, type_id);
1588 self.trait_impls
1589 .get(&type_root_filter)
1590 .iter()
1591 .for_each(|vec| vec.iter().for_each(&mut callback));
1592 if include_placeholder && type_root_filter != TypeRootFilter::Placeholder {
1593 self.trait_impls
1594 .get(&TypeRootFilter::Placeholder)
1595 .iter()
1596 .for_each(|vec| vec.iter().for_each(&mut callback));
1597 }
1598 }
1599
1600 fn get_type_root_filter(engines: &Engines, type_id: TypeId) -> TypeRootFilter {
1603 use TypeInfo::*;
1604 match &*engines.te().get(type_id) {
1605 Unknown => TypeRootFilter::Unknown,
1606 Never => TypeRootFilter::Never,
1607 UnknownGeneric { .. } | Placeholder(_) => TypeRootFilter::Placeholder,
1608 TypeParam(_param) => unreachable!(),
1609 StringSlice => TypeRootFilter::StringSlice,
1610 StringArray(_) => TypeRootFilter::StringArray,
1611 UnsignedInteger(x) => match x {
1612 IntegerBits::Eight => TypeRootFilter::U8,
1613 IntegerBits::Sixteen => TypeRootFilter::U16,
1614 IntegerBits::ThirtyTwo => TypeRootFilter::U32,
1615 IntegerBits::SixtyFour => TypeRootFilter::U64,
1616 IntegerBits::V256 => TypeRootFilter::U256,
1617 },
1618 Boolean => TypeRootFilter::Bool,
1619 Custom {
1620 qualified_call_path: call_path,
1621 ..
1622 } => TypeRootFilter::Custom(call_path.call_path.suffix.to_string()),
1623 B256 => TypeRootFilter::B256,
1624 Numeric => TypeRootFilter::U64, Contract => TypeRootFilter::Contract,
1626 ErrorRecovery(_) => TypeRootFilter::ErrorRecovery,
1627 Tuple(fields) => TypeRootFilter::Tuple(fields.len()),
1628 UntypedEnum(decl_id) => TypeRootFilter::Enum(*decl_id),
1629 UntypedStruct(decl_id) => TypeRootFilter::Struct(*decl_id),
1630 Enum(decl_id) => {
1631 TypeRootFilter::Enum(engines.de().get_parsed_decl_id(decl_id).unwrap())
1633 }
1634 Struct(decl_id) => {
1635 TypeRootFilter::Struct(engines.de().get_parsed_decl_id(decl_id).unwrap())
1637 }
1638 ContractCaller { abi_name, .. } => TypeRootFilter::ContractCaller(abi_name.to_string()),
1639 Array(_, _) => TypeRootFilter::Array,
1640 RawUntypedPtr => TypeRootFilter::RawUntypedPtr,
1641 RawUntypedSlice => TypeRootFilter::RawUntypedSlice,
1642 Ptr(_) => TypeRootFilter::Ptr,
1643 Slice(_) => TypeRootFilter::Slice,
1644 Alias { ty, .. } => Self::get_type_root_filter(engines, ty.type_id()),
1645 TraitType { name, .. } => TypeRootFilter::TraitType(name.to_string()),
1646 Ref {
1647 referenced_type, ..
1648 } => Self::get_type_root_filter(engines, referenced_type.type_id()),
1649 }
1650 }
1651}