sway_core/semantic_analysis/namespace/
trait_map.rs

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    IncludeSelf, SubstTypesContext, TraitConstraint, TypeArgument, TypeEngine, TypeInfo,
27    TypeSubstMap, UnifyCheck,
28};
29
30use super::Module;
31
32/// Enum used to pass a value asking for insertion of type into trait map when an implementation
33/// of the trait cannot be found.
34#[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<TypeArgument>,
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
150/// Map of name to [ResolvedTraitImplItem](ResolvedTraitImplItem)
151type TraitItems = BTreeMap<String, ResolvedTraitImplItem>;
152
153#[derive(Clone, Debug)]
154pub(crate) struct TraitValue {
155    pub(crate) trait_items: TraitItems,
156    /// The span of the entire impl block.
157    pub(crate) impl_span: Span,
158}
159
160#[derive(Clone, Debug)]
161pub(crate) struct TraitEntry {
162    pub(crate) key: TraitKey,
163    pub(crate) value: TraitValue,
164}
165
166/// Map of string of type entry id and vec of [TraitEntry].
167/// We are using the HashMap as a wrapper to the vec so the TraitMap algorithms
168/// don't need to traverse every TraitEntry.
169pub(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/// Map holding trait implementations for types.
201///
202/// Note: "impl self" blocks are considered traits and are stored in the
203/// [TraitMap].
204#[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    /// Given a [TraitName] `trait_name`, [TypeId] `type_id`, and list of
222    /// [TyImplItem](ty::TyImplItem) `items`, inserts
223    /// `items` into the [TraitMap] with the key `(trait_name, type_id)`.
224    ///
225    /// This method is as conscious as possible of existing entries in the
226    /// [TraitMap], and tries to append `items` to an existing list of
227    /// declarations for the key `(trait_name, type_id)` whenever possible.
228    #[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<TypeArgument>,
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                                // duplicate method name
257                                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            // check to see if adding this trait will produce a conflicting definition
276            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                // Types are subset if the `unaliased_type_id` that we want to insert can unify with the
303                // existing `map_type_id`. In addition we need to additionally check for the case of
304                // `&mut <type>` and `&<type>`.
305                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                /// `left` can unify into `right`. Additionally we need to check subset condition in case of
309                /// [TypeInfo::Ref] types.  Although `&mut <type>` can unify with `&<type>`
310                /// when it comes to trait and self impls, we considered them to be different types.
311                /// E.g., we can have `impl Foo for &T` and at the same time `impl Foo for &mut T`.
312                /// Or in general, `impl Foo for & &mut .. &T` is different type then, e.g., `impl Foo for &mut & .. &mut T`.
313                fn is_unified_type_subset(
314                    type_engine: &TypeEngine,
315                    mut left: TypeId,
316                    mut right: TypeId,
317                ) -> bool {
318                    // The loop cannot be endless, because at the end we must hit a referenced type which is not
319                    // a reference.
320                    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, // Different mutability means not subset.
334                            (
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            // even if there is a conflicting definition, add the trait anyway
464            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    /// Given [TraitMap]s `self` and `other`, extend `self` with `other`,
514    /// extending existing entries when possible.
515    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    /// Filters the entries in `self` and return a new [TraitMap] with all of
543    /// the entries from `self` that implement a trait from the declaration with that span.
544    pub(crate) fn filter_by_trait_decl_span(&self, trait_decl_span: Span) -> TraitMap {
545        let mut trait_map = TraitMap::default();
546        for key in self.trait_impls.keys() {
547            let vec = &self.trait_impls[key];
548            for entry in vec {
549                if entry.key.trait_decl_span.as_ref() == Some(&trait_decl_span) {
550                    let trait_map_vec =
551                        if let Some(trait_map_vec) = trait_map.trait_impls.get_mut(key) {
552                            trait_map_vec
553                        } else {
554                            trait_map
555                                .trait_impls
556                                .insert(key.clone(), Vec::<TraitEntry>::new());
557                            trait_map.trait_impls.get_mut(key).unwrap()
558                        };
559
560                    trait_map_vec.push(entry.clone());
561                }
562            }
563        }
564        trait_map
565    }
566
567    /// Filters the entries in `self` with the given [TypeId] `type_id` and
568    /// return a new [TraitMap] with all of the entries from `self` for which
569    /// `type_id` is a subtype or a supertype. Additionally, the new [TraitMap]
570    /// contains the entries for the inner types of `self`.
571    ///
572    /// This is used for handling the case in which we need to import an impl
573    /// block from another module, and the type that that impl block is defined
574    /// for is of the type that we are importing, but in a more concrete form.
575    ///
576    /// Here is some example Sway code that we should expect to compile:
577    ///
578    /// `my_double.sw`:
579    /// ```ignore
580    /// library;
581    ///
582    /// pub trait MyDouble<T> {
583    ///     fn my_double(self, input: T) -> T;
584    /// }
585    /// ```
586    ///
587    /// `my_point.sw`:
588    /// ```ignore
589    /// library;
590    ///
591    /// use ::my_double::MyDouble;
592    ///
593    /// pub struct MyPoint<T> {
594    ///     x: T,
595    ///     y: T,
596    /// }
597    ///
598    /// impl MyDouble<u64> for MyPoint<u64> {
599    ///     fn my_double(self, value: u64) -> u64 {
600    ///         (self.x*2) + (self.y*2) + (value*2)
601    ///     }
602    /// }
603    /// ```
604    ///
605    /// `main.sw`:
606    /// ```ignore
607    /// script;
608    ///
609    /// mod my_double;
610    /// mod my_point;
611    ///
612    /// use my_point::MyPoint;
613    ///
614    /// fn main() -> u64 {
615    ///     let foo = MyPoint {
616    ///         x: 10u64,
617    ///         y: 10u64,
618    ///     };
619    ///     foo.my_double(100)
620    /// }
621    /// ```
622    ///
623    /// We need to be able to import the trait defined upon `MyPoint<u64>` just
624    /// from seeing `use ::my_double::MyDouble;`.
625    pub(crate) fn filter_by_type_item_import(
626        &self,
627        type_id: TypeId,
628        engines: &Engines,
629    ) -> TraitMap {
630        let unify_checker = UnifyCheck::constraint_subset(engines);
631        let unify_checker_for_item_import = UnifyCheck::non_generic_constraint_subset(engines);
632
633        // a curried version of the decider protocol to use in the helper functions
634        let decider = |left: TypeId, right: TypeId| {
635            unify_checker.check(left, right) || unify_checker_for_item_import.check(right, left)
636        };
637        let mut trait_map = self.filter_by_type_inner(engines, vec![type_id], decider);
638        let all_types = type_id
639            .extract_inner_types(engines, IncludeSelf::No)
640            .into_iter()
641            .collect::<Vec<_>>();
642        // a curried version of the decider protocol to use in the helper functions
643        let decider2 = |left: TypeId, right: TypeId| unify_checker.check(left, right);
644
645        trait_map.extend(
646            self.filter_by_type_inner(engines, all_types, decider2),
647            engines,
648        );
649        trait_map
650    }
651
652    fn filter_by_type_inner(
653        &self,
654        engines: &Engines,
655        mut all_types: Vec<TypeId>,
656        decider: impl Fn(TypeId, TypeId) -> bool,
657    ) -> TraitMap {
658        let type_engine = engines.te();
659        let mut trait_map = TraitMap::default();
660        for type_id in all_types.iter_mut() {
661            let type_info = type_engine.get(*type_id);
662            self.for_each_impls(
663                engines,
664                *type_id,
665                true,
666                |TraitEntry {
667                     key:
668                         TraitKey {
669                             name: map_trait_name,
670                             type_id: map_type_id,
671                             trait_decl_span: map_trait_decl_span,
672                             impl_type_parameters: map_impl_type_parameters,
673                         },
674                     value:
675                         TraitValue {
676                             trait_items: map_trait_items,
677                             impl_span,
678                         },
679                 }| {
680                    if !type_engine.is_type_changeable(engines, &type_info)
681                        && *type_id == *map_type_id
682                    {
683                        trait_map.insert_inner(
684                            map_trait_name.clone(),
685                            impl_span.clone(),
686                            map_trait_decl_span.clone(),
687                            *type_id,
688                            map_impl_type_parameters.clone(),
689                            map_trait_items.clone(),
690                            engines,
691                        );
692                    } else if decider(*type_id, *map_type_id) {
693                        trait_map.insert_inner(
694                            map_trait_name.clone(),
695                            impl_span.clone(),
696                            map_trait_decl_span.clone(),
697                            *map_type_id,
698                            map_impl_type_parameters.clone(),
699                            Self::filter_dummy_methods(
700                                map_trait_items,
701                                *type_id,
702                                *map_type_id,
703                                engines,
704                            ),
705                            engines,
706                        );
707                    }
708                },
709            );
710        }
711        trait_map
712    }
713
714    fn filter_dummy_methods(
715        map_trait_items: &TraitItems,
716        type_id: TypeId,
717        map_type_id: TypeId,
718        engines: &Engines,
719    ) -> TraitItems {
720        let mut insertable = true;
721        if let TypeInfo::UnknownGeneric {
722            is_from_type_parameter,
723            ..
724        } = *engines.te().get(map_type_id)
725        {
726            insertable = !is_from_type_parameter
727                || matches!(*engines.te().get(type_id), TypeInfo::UnknownGeneric { .. });
728        }
729
730        map_trait_items
731            .iter()
732            .filter_map(|(name, item)| match item {
733                ResolvedTraitImplItem::Parsed(_item) => todo!(),
734                ResolvedTraitImplItem::Typed(item) => match item {
735                    ty::TyTraitItem::Fn(decl_ref) => {
736                        let decl = (*engines.de().get(decl_ref.id())).clone();
737                        if decl.is_trait_method_dummy && !insertable {
738                            None
739                        } else {
740                            Some((
741                                name.clone(),
742                                ResolvedTraitImplItem::Typed(TyImplItem::Fn(decl_ref.clone())),
743                            ))
744                        }
745                    }
746                    ty::TyTraitItem::Constant(decl_ref) => Some((
747                        name.clone(),
748                        ResolvedTraitImplItem::Typed(TyImplItem::Constant(decl_ref.clone())),
749                    )),
750                    ty::TyTraitItem::Type(decl_ref) => Some((
751                        name.clone(),
752                        ResolvedTraitImplItem::Typed(TyImplItem::Type(decl_ref.clone())),
753                    )),
754                },
755            })
756            .collect()
757    }
758
759    fn make_item_for_type_mapping(
760        engines: &Engines,
761        item: ResolvedTraitImplItem,
762        mut type_mapping: TypeSubstMap,
763        type_id: TypeId,
764        code_block_first_pass: CodeBlockFirstPass,
765    ) -> ResolvedTraitImplItem {
766        let decl_engine = engines.de();
767        match &item {
768            ResolvedTraitImplItem::Parsed(_item) => todo!(),
769            ResolvedTraitImplItem::Typed(item) => match item {
770                ty::TyTraitItem::Fn(decl_ref) => {
771                    let mut decl = (*decl_engine.get(decl_ref.id())).clone();
772                    if let Some(decl_implementing_for_typeid) = decl.implementing_for_typeid {
773                        type_mapping.insert(decl_implementing_for_typeid, type_id);
774                    }
775                    decl.subst(&SubstTypesContext::new(
776                        engines,
777                        &type_mapping,
778                        matches!(code_block_first_pass, CodeBlockFirstPass::No),
779                    ));
780
781                    let new_ref = decl_engine
782                        .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref())
783                        .with_parent(decl_engine, decl_ref.id().into());
784
785                    ResolvedTraitImplItem::Typed(TyImplItem::Fn(new_ref))
786                }
787                ty::TyTraitItem::Constant(decl_ref) => {
788                    let mut decl = (*decl_engine.get(decl_ref.id())).clone();
789                    decl.subst(&SubstTypesContext::new(
790                        engines,
791                        &type_mapping,
792                        matches!(code_block_first_pass, CodeBlockFirstPass::No),
793                    ));
794                    let new_ref = decl_engine
795                        .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref());
796                    ResolvedTraitImplItem::Typed(TyImplItem::Constant(new_ref))
797                }
798                ty::TyTraitItem::Type(decl_ref) => {
799                    let mut decl = (*decl_engine.get(decl_ref.id())).clone();
800                    decl.subst(&SubstTypesContext::new(
801                        engines,
802                        &type_mapping,
803                        matches!(code_block_first_pass, CodeBlockFirstPass::No),
804                    ));
805                    let new_ref = decl_engine
806                        .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref());
807                    ResolvedTraitImplItem::Typed(TyImplItem::Type(new_ref))
808                }
809            },
810        }
811    }
812
813    /// Find the entries in `self` that are equivalent to `type_id`.
814    ///
815    /// Notes:
816    /// - equivalency is defined (1) based on whether the types contains types
817    ///     that are dynamic and can change and (2) whether the types hold
818    ///     equivalency after (1) is fulfilled
819    /// - this method does not translate types from the found entries to the
820    ///     `type_id` (like in `filter_by_type()`). This is because the only
821    ///     entries that qualify as hits are equivalents of `type_id`
822    pub(crate) fn get_items_for_type(
823        module: &Module,
824        engines: &Engines,
825        type_id: TypeId,
826    ) -> Vec<ResolvedTraitImplItem> {
827        TraitMap::get_items_and_trait_key_for_type(module, engines, type_id)
828            .iter()
829            .map(|i| i.0.clone())
830            .collect::<Vec<_>>()
831    }
832
833    fn get_items_and_trait_key_for_type(
834        module: &Module,
835        engines: &Engines,
836        type_id: TypeId,
837    ) -> Vec<(ResolvedTraitImplItem, TraitKey)> {
838        let type_engine = engines.te();
839        let unify_check = UnifyCheck::constraint_subset(engines);
840
841        let type_id = engines.te().get_unaliased_type_id(type_id);
842
843        let mut items = vec![];
844        // small performance gain in bad case
845        if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
846            return items;
847        }
848
849        let _ = module.walk_scope_chain_early_return(|lexical_scope| {
850            lexical_scope.items.implemented_traits.for_each_impls(
851                engines,
852                type_id,
853                true,
854                |entry| {
855                    if unify_check.check(type_id, entry.key.type_id) {
856                        let trait_items = Self::filter_dummy_methods(
857                            &entry.value.trait_items,
858                            type_id,
859                            entry.key.type_id,
860                            engines,
861                        )
862                        .values()
863                        .cloned()
864                        .map(|i| (i, entry.key.clone()))
865                        .collect::<Vec<_>>();
866
867                        items.extend(trait_items);
868                    }
869                },
870            );
871
872            Ok(None::<()>)
873        });
874        items
875    }
876
877    /// Find the spans of all impls for the given type.
878    ///
879    /// Notes:
880    /// - equivalency is defined (1) based on whether the types contains types
881    ///     that are dynamic and can change and (2) whether the types hold
882    ///     equivalency after (1) is fulfilled
883    /// - this method does not translate types from the found entries to the
884    ///     `type_id` (like in `filter_by_type()`). This is because the only
885    ///     entries that qualify as hits are equivalents of `type_id`
886    pub fn get_impl_spans_for_type(
887        module: &Module,
888        engines: &Engines,
889        type_id: &TypeId,
890    ) -> Vec<Span> {
891        let type_engine = engines.te();
892        let unify_check = UnifyCheck::constraint_subset(engines);
893
894        let type_id = &engines.te().get_unaliased_type_id(*type_id);
895
896        let mut spans = vec![];
897        // small performance gain in bad case
898        if matches!(&*type_engine.get(*type_id), TypeInfo::ErrorRecovery(_)) {
899            return spans;
900        }
901        let _ = module.walk_scope_chain_early_return(|lexical_scope| {
902            lexical_scope.items.implemented_traits.for_each_impls(
903                engines,
904                *type_id,
905                false,
906                |entry| {
907                    if unify_check.check(*type_id, entry.key.type_id) {
908                        spans.push(entry.value.impl_span.clone());
909                    }
910                },
911            );
912
913            Ok(None::<()>)
914        });
915
916        spans
917    }
918
919    /// Find the spans of all impls for the given decl.
920    pub fn get_impl_spans_for_decl(
921        module: &Module,
922        engines: &Engines,
923        ty_decl: &TyDecl,
924    ) -> Vec<Span> {
925        let handler = Handler::default();
926        ty_decl
927            .return_type(&handler, engines)
928            .map(|type_id| TraitMap::get_impl_spans_for_type(module, engines, &type_id))
929            .unwrap_or_default()
930    }
931
932    /// Find the entries in `self` with trait name `trait_name` and return the
933    /// spans of the impls.
934    pub fn get_impl_spans_for_trait_name(module: &Module, trait_name: &CallPath) -> Vec<Span> {
935        let mut spans = vec![];
936        let _ = module.walk_scope_chain_early_return(|lexical_scope| {
937            spans.push(
938                lexical_scope
939                    .items
940                    .implemented_traits
941                    .trait_impls
942                    .values()
943                    .map(|impls| {
944                        impls
945                            .iter()
946                            .filter_map(|entry| {
947                                let map_trait_name = CallPath {
948                                    prefixes: entry.key.name.prefixes.clone(),
949                                    suffix: entry.key.name.suffix.name.clone(),
950                                    callpath_type: entry.key.name.callpath_type,
951                                };
952                                if &map_trait_name == trait_name {
953                                    Some(entry.value.impl_span.clone())
954                                } else {
955                                    None
956                                }
957                            })
958                            .collect::<Vec<Span>>()
959                    })
960                    .collect::<Vec<Vec<Span>>>()
961                    .concat(),
962            );
963            Ok(None::<()>)
964        });
965
966        spans.concat()
967    }
968
969    /// Find the entries in `self` that are equivalent to `type_id` with trait
970    /// name `trait_name` and with trait type arguments.
971    ///
972    /// Notes:
973    /// - equivalency is defined (1) based on whether the types contains types
974    ///     that are dynamic and can change and (2) whether the types hold
975    ///     equivalency after (1) is fulfilled
976    /// - this method does not translate types from the found entries to the
977    ///     `type_id` (like in `filter_by_type()`). This is because the only
978    ///     entries that qualify as hits are equivalents of `type_id`
979    pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments(
980        module: &Module,
981        engines: &Engines,
982        type_id: TypeId,
983        trait_name: &CallPath,
984        trait_type_args: &[TypeArgument],
985    ) -> Vec<ResolvedTraitImplItem> {
986        let type_id = engines.te().get_unaliased_type_id(type_id);
987
988        let type_engine = engines.te();
989        let unify_check = UnifyCheck::constraint_subset(engines);
990        let mut items = vec![];
991        // small performance gain in bad case
992        if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
993            return items;
994        }
995        let _ = module.walk_scope_chain_early_return(|lexical_scope| {
996            lexical_scope
997                .items
998                .implemented_traits
999                .for_each_impls(engines, type_id, false, |e| {
1000                    let map_trait_name = CallPath {
1001                        prefixes: e.key.name.prefixes.clone(),
1002                        suffix: e.key.name.suffix.name.clone(),
1003                        callpath_type: e.key.name.callpath_type,
1004                    };
1005                    if &map_trait_name == trait_name
1006                        && unify_check.check(type_id, e.key.type_id)
1007                        && trait_type_args.len() == e.key.name.suffix.args.len()
1008                        && trait_type_args
1009                            .iter()
1010                            .zip(e.key.name.suffix.args.iter())
1011                            .all(|(t1, t2)| unify_check.check(t1.type_id, t2.type_id))
1012                    {
1013                        let type_mapping =
1014                            TypeSubstMap::from_superset_and_subset(engines, e.key.type_id, type_id);
1015
1016                        let mut trait_items = Self::filter_dummy_methods(
1017                            &e.value.trait_items,
1018                            type_id,
1019                            e.key.type_id,
1020                            engines,
1021                        )
1022                        .values()
1023                        .cloned()
1024                        .map(|i| {
1025                            Self::make_item_for_type_mapping(
1026                                engines,
1027                                i,
1028                                type_mapping.clone(),
1029                                type_id,
1030                                CodeBlockFirstPass::No,
1031                            )
1032                        })
1033                        .collect::<Vec<_>>();
1034
1035                        items.append(&mut trait_items);
1036                    }
1037                });
1038            Ok(None::<()>)
1039        });
1040        items
1041    }
1042
1043    /// Find the entries in `self` that are equivalent to `type_id` with trait
1044    /// name `trait_name` and with trait type arguments.
1045    ///
1046    /// Notes:
1047    /// - equivalency is defined (1) based on whether the types contains types
1048    ///     that are dynamic and can change and (2) whether the types hold
1049    ///     equivalency after (1) is fulfilled
1050    /// - this method does not translate types from the found entries to the
1051    ///     `type_id` (like in `filter_by_type()`). This is because the only
1052    ///     entries that qualify as hits are equivalents of `type_id`
1053    pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments_typed(
1054        module: &Module,
1055        engines: &Engines,
1056        type_id: TypeId,
1057        trait_name: &CallPath,
1058        trait_type_args: &[TypeArgument],
1059    ) -> Vec<ty::TyTraitItem> {
1060        TraitMap::get_items_for_type_and_trait_name_and_trait_type_arguments(
1061            module,
1062            engines,
1063            type_id,
1064            trait_name,
1065            trait_type_args,
1066        )
1067        .into_iter()
1068        .map(|item| item.expect_typed())
1069        .collect::<Vec<_>>()
1070    }
1071
1072    pub(crate) fn get_trait_names_and_type_arguments_for_type(
1073        module: &Module,
1074        engines: &Engines,
1075        type_id: TypeId,
1076    ) -> Vec<(CallPath, Vec<TypeArgument>)> {
1077        let type_id = engines.te().get_unaliased_type_id(type_id);
1078
1079        let type_engine = engines.te();
1080        let unify_check = UnifyCheck::constraint_subset(engines);
1081        let mut trait_names = vec![];
1082        // small performance gain in bad case
1083        if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1084            return trait_names;
1085        }
1086        let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1087            lexical_scope.items.implemented_traits.for_each_impls(
1088                engines,
1089                type_id,
1090                false,
1091                |entry| {
1092                    if unify_check.check(type_id, entry.key.type_id) {
1093                        let trait_call_path = CallPath {
1094                            prefixes: entry.key.name.prefixes.clone(),
1095                            suffix: entry.key.name.suffix.name.clone(),
1096                            callpath_type: entry.key.name.callpath_type,
1097                        };
1098                        trait_names.push((trait_call_path, entry.key.name.suffix.args.clone()));
1099                    }
1100                },
1101            );
1102            Ok(None::<()>)
1103        });
1104        trait_names
1105    }
1106
1107    pub(crate) fn get_trait_item_for_type(
1108        module: &Module,
1109        handler: &Handler,
1110        engines: &Engines,
1111        symbol: &Ident,
1112        type_id: TypeId,
1113        as_trait: Option<CallPath>,
1114    ) -> Result<ResolvedTraitImplItem, ErrorEmitted> {
1115        let type_id = engines.te().get_unaliased_type_id(type_id);
1116
1117        let mut candidates = HashMap::<String, ResolvedTraitImplItem>::new();
1118        for (trait_item, trait_key) in
1119            TraitMap::get_items_and_trait_key_for_type(module, engines, type_id)
1120        {
1121            match trait_item {
1122                ResolvedTraitImplItem::Parsed(impl_item) => match impl_item {
1123                    ImplItem::Fn(fn_ref) => {
1124                        let decl = engines.pe().get_function(&fn_ref);
1125                        let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1126                        if decl.name.as_str() == symbol.as_str()
1127                            && (as_trait.is_none()
1128                                || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1129                        {
1130                            candidates.insert(
1131                                trait_call_path_string,
1132                                ResolvedTraitImplItem::Parsed(ImplItem::Fn(fn_ref)),
1133                            );
1134                        }
1135                    }
1136                    ImplItem::Constant(const_ref) => {
1137                        let decl = engines.pe().get_constant(&const_ref);
1138                        let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1139                        if decl.name.as_str() == symbol.as_str()
1140                            && (as_trait.is_none()
1141                                || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1142                        {
1143                            candidates.insert(
1144                                trait_call_path_string,
1145                                ResolvedTraitImplItem::Parsed(ImplItem::Constant(const_ref)),
1146                            );
1147                        }
1148                    }
1149                    ImplItem::Type(type_ref) => {
1150                        let decl = engines.pe().get_trait_type(&type_ref);
1151                        let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1152                        if decl.name.as_str() == symbol.as_str()
1153                            && (as_trait.is_none()
1154                                || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1155                        {
1156                            candidates.insert(
1157                                trait_call_path_string,
1158                                ResolvedTraitImplItem::Parsed(ImplItem::Type(type_ref)),
1159                            );
1160                        }
1161                    }
1162                },
1163                ResolvedTraitImplItem::Typed(ty_impl_item) => match ty_impl_item {
1164                    ty::TyTraitItem::Fn(fn_ref) => {
1165                        let decl = engines.de().get_function(&fn_ref);
1166                        let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1167                        if decl.name.as_str() == symbol.as_str()
1168                            && (as_trait.is_none()
1169                                || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1170                        {
1171                            candidates.insert(
1172                                trait_call_path_string,
1173                                ResolvedTraitImplItem::Typed(TyTraitItem::Fn(fn_ref)),
1174                            );
1175                        }
1176                    }
1177                    ty::TyTraitItem::Constant(const_ref) => {
1178                        let decl = engines.de().get_constant(&const_ref);
1179                        let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1180                        if decl.call_path.suffix.as_str() == symbol.as_str()
1181                            && (as_trait.is_none()
1182                                || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1183                        {
1184                            candidates.insert(
1185                                trait_call_path_string,
1186                                ResolvedTraitImplItem::Typed(TyTraitItem::Constant(const_ref)),
1187                            );
1188                        }
1189                    }
1190                    ty::TyTraitItem::Type(type_ref) => {
1191                        let decl = engines.de().get_type(&type_ref);
1192                        let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1193                        if decl.name.as_str() == symbol.as_str()
1194                            && (as_trait.is_none()
1195                                || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1196                        {
1197                            candidates.insert(
1198                                trait_call_path_string,
1199                                ResolvedTraitImplItem::Typed(TyTraitItem::Type(type_ref)),
1200                            );
1201                        }
1202                    }
1203                },
1204            }
1205        }
1206
1207        match candidates.len().cmp(&1) {
1208            Ordering::Greater => Err(handler.emit_err(
1209                CompileError::MultipleApplicableItemsInScope {
1210                    item_name: symbol.as_str().to_string(),
1211                    item_kind: "item".to_string(),
1212                    as_traits: candidates
1213                        .keys()
1214                        .map(|k| {
1215                            (
1216                                k.clone()
1217                                    .split("::")
1218                                    .collect::<Vec<_>>()
1219                                    .last()
1220                                    .unwrap()
1221                                    .to_string(),
1222                                engines.help_out(type_id).to_string(),
1223                            )
1224                        })
1225                        .collect::<Vec<_>>(),
1226                    span: symbol.span(),
1227                },
1228            )),
1229            Ordering::Less => Err(handler.emit_err(CompileError::SymbolNotFound {
1230                name: symbol.clone(),
1231                span: symbol.span(),
1232            })),
1233            Ordering::Equal => Ok(candidates.values().next().unwrap().clone()),
1234        }
1235    }
1236
1237    /// Checks to see if the trait constraints are satisfied for a given type.
1238    #[allow(clippy::too_many_arguments)]
1239    pub(crate) fn check_if_trait_constraints_are_satisfied_for_type(
1240        handler: &Handler,
1241        module: &mut Module,
1242        type_id: TypeId,
1243        constraints: &[TraitConstraint],
1244        access_span: &Span,
1245        engines: &Engines,
1246    ) -> Result<(), ErrorEmitted> {
1247        let type_engine = engines.te();
1248
1249        let type_id = type_engine.get_unaliased_type_id(type_id);
1250
1251        // resolving trait constraints require a concrete type, we need to default numeric to u64
1252        type_engine.decay_numeric(handler, engines, type_id, access_span)?;
1253
1254        if constraints.is_empty() {
1255            return Ok(());
1256        }
1257
1258        // Check we can use the cache
1259        let mut hasher = DefaultHasher::default();
1260        type_id.hash(&mut hasher);
1261        for c in constraints {
1262            c.hash(&mut hasher, engines);
1263        }
1264        let hash = hasher.finish();
1265
1266        {
1267            let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1268            if trait_map.satisfied_cache.contains(&hash) {
1269                return Ok(());
1270            }
1271        }
1272
1273        let all_impld_traits: BTreeSet<(Ident, TypeId)> =
1274            Self::get_all_implemented_traits(module, type_id, engines);
1275
1276        // Call the real implementation and cache when true
1277        match Self::check_if_trait_constraints_are_satisfied_for_type_inner(
1278            handler,
1279            type_id,
1280            constraints,
1281            access_span,
1282            engines,
1283            all_impld_traits,
1284        ) {
1285            Ok(()) => {
1286                let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1287                trait_map.satisfied_cache.insert(hash);
1288                Ok(())
1289            }
1290            r => r,
1291        }
1292    }
1293
1294    fn get_all_implemented_traits(
1295        module: &Module,
1296        type_id: TypeId,
1297        engines: &Engines,
1298    ) -> BTreeSet<(Ident, TypeId)> {
1299        let mut all_impld_traits: BTreeSet<(Ident, TypeId)> = Default::default();
1300        let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1301            all_impld_traits.extend(
1302                lexical_scope
1303                    .items
1304                    .implemented_traits
1305                    .get_implemented_traits(type_id, engines),
1306            );
1307            Ok(None::<()>)
1308        });
1309        all_impld_traits
1310    }
1311
1312    fn get_implemented_traits(
1313        &self,
1314        type_id: TypeId,
1315        engines: &Engines,
1316    ) -> BTreeSet<(Ident, TypeId)> {
1317        let type_engine = engines.te();
1318        let unify_check = UnifyCheck::constraint_subset(engines);
1319        let mut all_impld_traits = BTreeSet::<(Ident, TypeId)>::new();
1320        self.for_each_impls(engines, type_id, true, |e| {
1321            let key = &e.key;
1322            let suffix = &key.name.suffix;
1323            if unify_check.check(type_id, key.type_id) {
1324                let map_trait_type_id = type_engine.new_custom(
1325                    engines,
1326                    suffix.name.clone().into(),
1327                    if suffix.args.is_empty() {
1328                        None
1329                    } else {
1330                        Some(suffix.args.to_vec())
1331                    },
1332                );
1333                all_impld_traits.insert((suffix.name.clone(), map_trait_type_id));
1334            }
1335        });
1336        all_impld_traits
1337    }
1338
1339    #[allow(clippy::too_many_arguments)]
1340    fn check_if_trait_constraints_are_satisfied_for_type_inner(
1341        handler: &Handler,
1342        type_id: TypeId,
1343        constraints: &[TraitConstraint],
1344        access_span: &Span,
1345        engines: &Engines,
1346        all_impld_traits: BTreeSet<(Ident, TypeId)>,
1347    ) -> Result<(), ErrorEmitted> {
1348        let type_engine = engines.te();
1349        let unify_check = UnifyCheck::constraint_subset(engines);
1350
1351        let required_traits: BTreeSet<(Ident, TypeId)> = constraints
1352            .iter()
1353            .map(|c| {
1354                let TraitConstraint {
1355                    trait_name: constraint_trait_name,
1356                    type_arguments: constraint_type_arguments,
1357                } = c;
1358                let constraint_type_id = type_engine.new_custom(
1359                    engines,
1360                    constraint_trait_name.suffix.clone().into(),
1361                    if constraint_type_arguments.is_empty() {
1362                        None
1363                    } else {
1364                        Some(constraint_type_arguments.clone())
1365                    },
1366                );
1367                (c.trait_name.suffix.clone(), constraint_type_id)
1368            })
1369            .collect();
1370
1371        let traits_not_found: BTreeSet<(BaseIdent, TypeId)> = required_traits
1372            .into_iter()
1373            .filter(|(required_trait_name, required_trait_type_id)| {
1374                !all_impld_traits
1375                    .iter()
1376                    .any(|(trait_name, constraint_type_id)| {
1377                        trait_name == required_trait_name
1378                            && unify_check.check(*constraint_type_id, *required_trait_type_id)
1379                    })
1380            })
1381            .collect();
1382
1383        handler.scope(|handler| {
1384            for (trait_name, constraint_type_id) in traits_not_found.iter() {
1385                let mut type_arguments_string = "".to_string();
1386                if let TypeInfo::Custom {
1387                    qualified_call_path: _,
1388                    type_arguments: Some(type_arguments),
1389                } = &*type_engine.get(*constraint_type_id)
1390                {
1391                    type_arguments_string = format!("<{}>", engines.help_out(type_arguments));
1392                }
1393
1394                // TODO: use a better span
1395                handler.emit_err(CompileError::TraitConstraintNotSatisfied {
1396                    type_id: type_id.index(),
1397                    ty: engines.help_out(type_id).to_string(),
1398                    trait_name: format!("{}{}", trait_name, type_arguments_string),
1399                    span: access_span.clone(),
1400                });
1401            }
1402
1403            Ok(())
1404        })
1405    }
1406
1407    pub fn get_trait_constraints_are_satisfied_for_types(
1408        module: &Module,
1409        _handler: &Handler,
1410        type_id: TypeId,
1411        constraints: &[TraitConstraint],
1412        engines: &Engines,
1413    ) -> Result<Vec<(TypeId, String)>, ErrorEmitted> {
1414        let type_id = engines.te().get_unaliased_type_id(type_id);
1415
1416        let _decl_engine = engines.de();
1417        let unify_check = UnifyCheck::coercion(engines);
1418        let unify_check_equality = UnifyCheck::constraint_subset(engines);
1419
1420        let mut impld_traits_type_ids: Vec<Vec<(TypeId, String)>> = vec![];
1421        let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1422            lexical_scope
1423                .items
1424                .implemented_traits
1425                .for_each_impls(engines, type_id, true, |e| {
1426                    let mut traits: Vec<(TypeId, String)> = vec![];
1427
1428                    let key = &e.key;
1429                    for constraint in constraints {
1430                        if key.name.suffix.name == constraint.trait_name.suffix
1431                            && key
1432                                .name
1433                                .suffix
1434                                .args
1435                                .iter()
1436                                .zip(constraint.type_arguments.iter())
1437                                .all(|(a1, a2)| unify_check_equality.check(a1.type_id, a2.type_id))
1438                            && unify_check.check(type_id, key.type_id)
1439                        {
1440                            let name_type_args = if !key.name.suffix.args.is_empty() {
1441                                format!("<{}>", engines.help_out(key.name.suffix.args.clone()))
1442                            } else {
1443                                "".to_string()
1444                            };
1445                            let name =
1446                                format!("{}{}", key.name.suffix.name.as_str(), name_type_args);
1447                            traits.push((key.type_id, name));
1448                            break;
1449                        }
1450                    }
1451                    impld_traits_type_ids.push(traits);
1452                });
1453
1454            Ok(None::<()>)
1455        });
1456        Ok(impld_traits_type_ids.concat())
1457    }
1458
1459    fn get_impls_mut(&mut self, engines: &Engines, type_id: TypeId) -> &mut Vec<TraitEntry> {
1460        let type_root_filter = Self::get_type_root_filter(engines, type_id);
1461        if !self.trait_impls.contains_key(&type_root_filter) {
1462            self.trait_impls
1463                .insert(type_root_filter.clone(), Vec::new());
1464        }
1465
1466        self.trait_impls.get_mut(&type_root_filter).unwrap()
1467    }
1468
1469    pub(crate) fn for_each_impls<F>(
1470        &self,
1471        engines: &Engines,
1472        type_id: TypeId,
1473        include_placeholder: bool,
1474        mut callback: F,
1475    ) where
1476        F: FnMut(&TraitEntry),
1477    {
1478        let type_root_filter = Self::get_type_root_filter(engines, type_id);
1479        self.trait_impls
1480            .get(&type_root_filter)
1481            .iter()
1482            .for_each(|vec| vec.iter().for_each(&mut callback));
1483        if include_placeholder && type_root_filter != TypeRootFilter::Placeholder {
1484            self.trait_impls
1485                .get(&TypeRootFilter::Placeholder)
1486                .iter()
1487                .for_each(|vec| vec.iter().for_each(&mut callback));
1488        }
1489    }
1490
1491    // Return a string representing only the base type.
1492    // This is used by the trait map to filter the entries into a HashMap with the return type string as key.
1493    fn get_type_root_filter(engines: &Engines, type_id: TypeId) -> TypeRootFilter {
1494        use TypeInfo::*;
1495        match &*engines.te().get(type_id) {
1496            Unknown => TypeRootFilter::Unknown,
1497            Never => TypeRootFilter::Never,
1498            UnknownGeneric { .. } | Placeholder(_) => TypeRootFilter::Placeholder,
1499            TypeParam(_param) => unreachable!(),
1500            StringSlice => TypeRootFilter::StringSlice,
1501            StringArray(x) => TypeRootFilter::StringArray(x.val()),
1502            UnsignedInteger(x) => match x {
1503                IntegerBits::Eight => TypeRootFilter::U8,
1504                IntegerBits::Sixteen => TypeRootFilter::U16,
1505                IntegerBits::ThirtyTwo => TypeRootFilter::U32,
1506                IntegerBits::SixtyFour => TypeRootFilter::U64,
1507                IntegerBits::V256 => TypeRootFilter::U256,
1508            },
1509            Boolean => TypeRootFilter::Bool,
1510            Custom {
1511                qualified_call_path: call_path,
1512                ..
1513            } => TypeRootFilter::Custom(call_path.call_path.suffix.to_string()),
1514            B256 => TypeRootFilter::B256,
1515            Numeric => TypeRootFilter::U64, // u64 is the default
1516            Contract => TypeRootFilter::Contract,
1517            ErrorRecovery(_) => TypeRootFilter::ErrorRecovery,
1518            Tuple(fields) => TypeRootFilter::Tuple(fields.len()),
1519            UntypedEnum(decl_id) => TypeRootFilter::Enum(*decl_id),
1520            UntypedStruct(decl_id) => TypeRootFilter::Struct(*decl_id),
1521            Enum(decl_id) => {
1522                // TODO Remove unwrap once #6475 is fixed
1523                TypeRootFilter::Enum(engines.de().get_parsed_decl_id(decl_id).unwrap())
1524            }
1525            Struct(decl_id) => {
1526                // TODO Remove unwrap once #6475 is fixed
1527                TypeRootFilter::Struct(engines.de().get_parsed_decl_id(decl_id).unwrap())
1528            }
1529            ContractCaller { abi_name, .. } => TypeRootFilter::ContractCaller(abi_name.to_string()),
1530            Array(_, _) => TypeRootFilter::Array,
1531            RawUntypedPtr => TypeRootFilter::RawUntypedPtr,
1532            RawUntypedSlice => TypeRootFilter::RawUntypedSlice,
1533            Ptr(_) => TypeRootFilter::Ptr,
1534            Slice(_) => TypeRootFilter::Slice,
1535            Alias { ty, .. } => Self::get_type_root_filter(engines, ty.type_id),
1536            TraitType { name, .. } => TypeRootFilter::TraitType(name.to_string()),
1537            Ref {
1538                referenced_type, ..
1539            } => Self::get_type_root_filter(engines, referenced_type.type_id),
1540        }
1541    }
1542}