sway_core/semantic_analysis/namespace/
trait_map.rs

1use std::{
2    cmp::Ordering,
3    collections::{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 = HashMap<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 = HashMap<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 = HashMap::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                    let mut names = trait_items.keys().clone().collect::<Vec<_>>();
385                    names.sort();
386                    for name in names {
387                        let item = &trait_items[name];
388                        match item {
389                            ResolvedTraitImplItem::Parsed(_item) => todo!(),
390                            ResolvedTraitImplItem::Typed(item) => match item {
391                                ty::TyTraitItem::Fn(decl_ref) => {
392                                    if let Some(existing_item) = map_trait_items.get(name) {
393                                        handler.emit_err(
394                                            CompileError::DuplicateDeclDefinedForType {
395                                                decl_kind: "method".into(),
396                                                decl_name: decl_ref.name().to_string(),
397                                                type_implementing_for: engines
398                                                    .help_out(type_id)
399                                                    .to_string(),
400                                                type_implementing_for_unaliased: engines
401                                                    .help_out(unaliased_type_id)
402                                                    .to_string(),
403                                                existing_impl_span: existing_item
404                                                    .span(engines)
405                                                    .clone(),
406                                                second_impl_span: decl_ref.name().span(),
407                                            },
408                                        );
409                                    }
410                                }
411                                ty::TyTraitItem::Constant(decl_ref) => {
412                                    if let Some(existing_item) = map_trait_items.get(name) {
413                                        handler.emit_err(
414                                            CompileError::DuplicateDeclDefinedForType {
415                                                decl_kind: "constant".into(),
416                                                decl_name: decl_ref.name().to_string(),
417                                                type_implementing_for: engines
418                                                    .help_out(type_id)
419                                                    .to_string(),
420                                                type_implementing_for_unaliased: engines
421                                                    .help_out(unaliased_type_id)
422                                                    .to_string(),
423                                                existing_impl_span: existing_item
424                                                    .span(engines)
425                                                    .clone(),
426                                                second_impl_span: decl_ref.name().span(),
427                                            },
428                                        );
429                                    }
430                                }
431                                ty::TyTraitItem::Type(decl_ref) => {
432                                    if let Some(existing_item) = map_trait_items.get(name) {
433                                        handler.emit_err(
434                                            CompileError::DuplicateDeclDefinedForType {
435                                                decl_kind: "type".into(),
436                                                decl_name: decl_ref.name().to_string(),
437                                                type_implementing_for: engines
438                                                    .help_out(type_id)
439                                                    .to_string(),
440                                                type_implementing_for_unaliased: engines
441                                                    .help_out(unaliased_type_id)
442                                                    .to_string(),
443                                                existing_impl_span: existing_item
444                                                    .span(engines)
445                                                    .clone(),
446                                                second_impl_span: decl_ref.name().span(),
447                                            },
448                                        );
449                                    }
450                                }
451                            },
452                        }
453                    }
454                }
455            }
456            let trait_name: TraitName = Arc::new(CallPath {
457                prefixes: trait_name.prefixes,
458                suffix: TraitSuffix {
459                    name: trait_name.suffix,
460                    args: trait_type_args,
461                },
462                callpath_type: trait_name.callpath_type,
463            });
464
465            // even if there is a conflicting definition, add the trait anyway
466            self.insert_inner(
467                trait_name,
468                impl_span.clone(),
469                trait_decl_span,
470                unaliased_type_id,
471                impl_type_parameters,
472                trait_items,
473                engines,
474            );
475
476            Ok(())
477        })
478    }
479
480    #[allow(clippy::too_many_arguments)]
481    fn insert_inner(
482        &mut self,
483        trait_name: TraitName,
484        impl_span: Span,
485        trait_decl_span: Option<Span>,
486        type_id: TypeId,
487        impl_type_parameters: Vec<TypeId>,
488        trait_methods: TraitItems,
489        engines: &Engines,
490    ) {
491        let key = TraitKey {
492            name: trait_name,
493            type_id,
494            trait_decl_span,
495            impl_type_parameters,
496        };
497        let value = TraitValue {
498            trait_items: trait_methods,
499            impl_span,
500        };
501        let entry = TraitEntry { key, value };
502        let mut trait_impls: TraitImpls = HashMap::<TypeRootFilter, Vec<TraitEntry>>::new();
503        let type_root_filter = Self::get_type_root_filter(engines, type_id);
504        let impls_vector = vec![entry];
505        trait_impls.insert(type_root_filter, impls_vector);
506
507        let trait_map = TraitMap {
508            trait_impls,
509            satisfied_cache: HashSet::default(),
510        };
511
512        self.extend(trait_map, engines);
513    }
514
515    /// Given [TraitMap]s `self` and `other`, extend `self` with `other`,
516    /// extending existing entries when possible.
517    pub(crate) fn extend(&mut self, other: TraitMap, engines: &Engines) {
518        let mut impls_keys = other.trait_impls.keys().clone().collect::<Vec<_>>();
519        impls_keys.sort();
520        for impls_key in impls_keys {
521            let oe_vec = &other.trait_impls[impls_key];
522            let self_vec = if let Some(self_vec) = self.trait_impls.get_mut(impls_key) {
523                self_vec
524            } else {
525                self.trait_impls
526                    .insert(impls_key.clone(), Vec::<TraitEntry>::new());
527                self.trait_impls.get_mut(impls_key).unwrap()
528            };
529
530            for oe in oe_vec.iter() {
531                let pos = self_vec.binary_search_by(|se| {
532                    se.key.cmp(&oe.key, &OrdWithEnginesContext::new(engines))
533                });
534
535                match pos {
536                    Ok(pos) => self_vec[pos]
537                        .value
538                        .trait_items
539                        .extend(oe.value.trait_items.clone()),
540                    Err(pos) => self_vec.insert(pos, oe.clone()),
541                }
542            }
543        }
544    }
545
546    /// Filters the entries in `self` and return a new [TraitMap] with all of
547    /// the entries from `self` that implement a trait from the declaration with that span.
548    pub(crate) fn filter_by_trait_decl_span(&self, trait_decl_span: Span) -> TraitMap {
549        let mut trait_map = TraitMap::default();
550        let mut keys = self.trait_impls.keys().clone().collect::<Vec<_>>();
551        keys.sort();
552        for key in keys {
553            let vec = &self.trait_impls[key];
554            for entry in vec {
555                if entry.key.trait_decl_span.as_ref() == Some(&trait_decl_span) {
556                    let trait_map_vec =
557                        if let Some(trait_map_vec) = trait_map.trait_impls.get_mut(key) {
558                            trait_map_vec
559                        } else {
560                            trait_map
561                                .trait_impls
562                                .insert(key.clone(), Vec::<TraitEntry>::new());
563                            trait_map.trait_impls.get_mut(key).unwrap()
564                        };
565
566                    trait_map_vec.push(entry.clone());
567                }
568            }
569        }
570        trait_map
571    }
572
573    /// Filters the entries in `self` with the given [TypeId] `type_id` and
574    /// return a new [TraitMap] with all of the entries from `self` for which
575    /// `type_id` is a subtype or a supertype. Additionally, the new [TraitMap]
576    /// contains the entries for the inner types of `self`.
577    ///
578    /// This is used for handling the case in which we need to import an impl
579    /// block from another module, and the type that that impl block is defined
580    /// for is of the type that we are importing, but in a more concrete form.
581    ///
582    /// Here is some example Sway code that we should expect to compile:
583    ///
584    /// `my_double.sw`:
585    /// ```ignore
586    /// library;
587    ///
588    /// pub trait MyDouble<T> {
589    ///     fn my_double(self, input: T) -> T;
590    /// }
591    /// ```
592    ///
593    /// `my_point.sw`:
594    /// ```ignore
595    /// library;
596    ///
597    /// use ::my_double::MyDouble;
598    ///
599    /// pub struct MyPoint<T> {
600    ///     x: T,
601    ///     y: T,
602    /// }
603    ///
604    /// impl MyDouble<u64> for MyPoint<u64> {
605    ///     fn my_double(self, value: u64) -> u64 {
606    ///         (self.x*2) + (self.y*2) + (value*2)
607    ///     }
608    /// }
609    /// ```
610    ///
611    /// `main.sw`:
612    /// ```ignore
613    /// script;
614    ///
615    /// mod my_double;
616    /// mod my_point;
617    ///
618    /// use my_point::MyPoint;
619    ///
620    /// fn main() -> u64 {
621    ///     let foo = MyPoint {
622    ///         x: 10u64,
623    ///         y: 10u64,
624    ///     };
625    ///     foo.my_double(100)
626    /// }
627    /// ```
628    ///
629    /// We need to be able to import the trait defined upon `MyPoint<u64>` just
630    /// from seeing `use ::my_double::MyDouble;`.
631    pub(crate) fn filter_by_type_item_import(
632        &self,
633        type_id: TypeId,
634        engines: &Engines,
635    ) -> TraitMap {
636        let unify_checker = UnifyCheck::constraint_subset(engines);
637        let unify_checker_for_item_import = UnifyCheck::non_generic_constraint_subset(engines);
638
639        // a curried version of the decider protocol to use in the helper functions
640        let decider = |left: TypeId, right: TypeId| {
641            unify_checker.check(left, right) || unify_checker_for_item_import.check(right, left)
642        };
643        let mut trait_map = self.filter_by_type_inner(engines, vec![type_id], decider);
644        let all_types = type_id
645            .extract_inner_types(engines, IncludeSelf::No)
646            .into_iter()
647            .collect::<Vec<_>>();
648        // a curried version of the decider protocol to use in the helper functions
649        let decider2 = |left: TypeId, right: TypeId| unify_checker.check(left, right);
650
651        trait_map.extend(
652            self.filter_by_type_inner(engines, all_types, decider2),
653            engines,
654        );
655        trait_map
656    }
657
658    fn filter_by_type_inner(
659        &self,
660        engines: &Engines,
661        mut all_types: Vec<TypeId>,
662        decider: impl Fn(TypeId, TypeId) -> bool,
663    ) -> TraitMap {
664        let type_engine = engines.te();
665        let mut trait_map = TraitMap::default();
666        for type_id in all_types.iter_mut() {
667            let type_info = type_engine.get(*type_id);
668            let impls = self.get_impls(engines, *type_id, true);
669            for TraitEntry {
670                key:
671                    TraitKey {
672                        name: map_trait_name,
673                        type_id: map_type_id,
674                        trait_decl_span: map_trait_decl_span,
675                        impl_type_parameters: map_impl_type_parameters,
676                    },
677                value:
678                    TraitValue {
679                        trait_items: map_trait_items,
680                        impl_span,
681                    },
682            } in impls.iter()
683            {
684                if !type_engine.is_type_changeable(engines, &type_info) && *type_id == *map_type_id
685                {
686                    trait_map.insert_inner(
687                        map_trait_name.clone(),
688                        impl_span.clone(),
689                        map_trait_decl_span.clone(),
690                        *type_id,
691                        map_impl_type_parameters.clone(),
692                        map_trait_items.clone(),
693                        engines,
694                    );
695                } else if decider(*type_id, *map_type_id) {
696                    trait_map.insert_inner(
697                        map_trait_name.clone(),
698                        impl_span.clone(),
699                        map_trait_decl_span.clone(),
700                        *map_type_id,
701                        map_impl_type_parameters.clone(),
702                        Self::filter_dummy_methods(
703                            map_trait_items.clone(),
704                            *type_id,
705                            *map_type_id,
706                            engines,
707                        ),
708                        engines,
709                    );
710                }
711            }
712        }
713        trait_map
714    }
715
716    fn filter_dummy_methods(
717        map_trait_items: TraitItems,
718        type_id: TypeId,
719        map_type_id: TypeId,
720        engines: &Engines,
721    ) -> TraitItems {
722        let mut insertable = true;
723        if let TypeInfo::UnknownGeneric {
724            is_from_type_parameter,
725            ..
726        } = *engines.te().get(map_type_id)
727        {
728            insertable = !is_from_type_parameter
729                || matches!(*engines.te().get(type_id), TypeInfo::UnknownGeneric { .. });
730        }
731
732        map_trait_items
733            .clone()
734            .into_iter()
735            .filter_map(|(name, item)| match item {
736                ResolvedTraitImplItem::Parsed(_item) => todo!(),
737                ResolvedTraitImplItem::Typed(item) => match item {
738                    ty::TyTraitItem::Fn(decl_ref) => {
739                        let decl = (*engines.de().get(decl_ref.id())).clone();
740                        if decl.is_trait_method_dummy && !insertable {
741                            None
742                        } else {
743                            Some((name, ResolvedTraitImplItem::Typed(TyImplItem::Fn(decl_ref))))
744                        }
745                    }
746                    ty::TyTraitItem::Constant(decl_ref) => Some((
747                        name,
748                        ResolvedTraitImplItem::Typed(TyImplItem::Constant(decl_ref)),
749                    )),
750                    ty::TyTraitItem::Type(decl_ref) => Some((
751                        name,
752                        ResolvedTraitImplItem::Typed(TyImplItem::Type(decl_ref)),
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(|lexical_scope| {
850            let impls = lexical_scope
851                .items
852                .implemented_traits
853                .get_impls(engines, type_id, true);
854            for entry in impls {
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            Ok(None::<()>)
871        });
872        items
873    }
874
875    /// Find the spans of all impls for the given type.
876    ///
877    /// Notes:
878    /// - equivalency is defined (1) based on whether the types contains types
879    ///     that are dynamic and can change and (2) whether the types hold
880    ///     equivalency after (1) is fulfilled
881    /// - this method does not translate types from the found entries to the
882    ///     `type_id` (like in `filter_by_type()`). This is because the only
883    ///     entries that qualify as hits are equivalents of `type_id`
884    pub fn get_impl_spans_for_type(
885        module: &Module,
886        engines: &Engines,
887        type_id: &TypeId,
888    ) -> Vec<Span> {
889        let type_engine = engines.te();
890        let unify_check = UnifyCheck::constraint_subset(engines);
891
892        let type_id = &engines.te().get_unaliased_type_id(*type_id);
893
894        let mut spans = vec![];
895        // small performance gain in bad case
896        if matches!(&*type_engine.get(*type_id), TypeInfo::ErrorRecovery(_)) {
897            return spans;
898        }
899        let _ = module.walk_scope_chain(|lexical_scope| {
900            let impls = lexical_scope
901                .items
902                .implemented_traits
903                .get_impls(engines, *type_id, false);
904            for entry in impls {
905                if unify_check.check(*type_id, entry.key.type_id) {
906                    spans.push(entry.value.impl_span.clone());
907                }
908            }
909            Ok(None::<()>)
910        });
911
912        spans
913    }
914
915    /// Find the spans of all impls for the given decl.
916    pub fn get_impl_spans_for_decl(
917        module: &Module,
918        engines: &Engines,
919        ty_decl: &TyDecl,
920    ) -> Vec<Span> {
921        let handler = Handler::default();
922        ty_decl
923            .return_type(&handler, engines)
924            .map(|type_id| TraitMap::get_impl_spans_for_type(module, engines, &type_id))
925            .unwrap_or_default()
926    }
927
928    /// Find the entries in `self` with trait name `trait_name` and return the
929    /// spans of the impls.
930    pub fn get_impl_spans_for_trait_name(module: &Module, trait_name: &CallPath) -> Vec<Span> {
931        let mut spans = vec![];
932        let _ = module.walk_scope_chain(|lexical_scope| {
933            spans.push(
934                lexical_scope
935                    .items
936                    .implemented_traits
937                    .trait_impls
938                    .values()
939                    .map(|impls| {
940                        impls
941                            .iter()
942                            .filter_map(|entry| {
943                                let map_trait_name = CallPath {
944                                    prefixes: entry.key.name.prefixes.clone(),
945                                    suffix: entry.key.name.suffix.name.clone(),
946                                    callpath_type: entry.key.name.callpath_type,
947                                };
948                                if &map_trait_name == trait_name {
949                                    Some(entry.value.impl_span.clone())
950                                } else {
951                                    None
952                                }
953                            })
954                            .collect::<Vec<Span>>()
955                    })
956                    .collect::<Vec<Vec<Span>>>()
957                    .concat(),
958            );
959            Ok(None::<()>)
960        });
961
962        spans.concat()
963    }
964
965    /// Find the entries in `self` that are equivalent to `type_id` with trait
966    /// name `trait_name` and with trait type arguments.
967    ///
968    /// Notes:
969    /// - equivalency is defined (1) based on whether the types contains types
970    ///     that are dynamic and can change and (2) whether the types hold
971    ///     equivalency after (1) is fulfilled
972    /// - this method does not translate types from the found entries to the
973    ///     `type_id` (like in `filter_by_type()`). This is because the only
974    ///     entries that qualify as hits are equivalents of `type_id`
975    pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments(
976        module: &Module,
977        engines: &Engines,
978        type_id: TypeId,
979        trait_name: &CallPath,
980        trait_type_args: &[TypeArgument],
981    ) -> Vec<ResolvedTraitImplItem> {
982        let type_id = engines.te().get_unaliased_type_id(type_id);
983
984        let type_engine = engines.te();
985        let unify_check = UnifyCheck::constraint_subset(engines);
986        let mut items = vec![];
987        // small performance gain in bad case
988        if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
989            return items;
990        }
991        let _ = module.walk_scope_chain(|lexical_scope| {
992            let impls = lexical_scope
993                .items
994                .implemented_traits
995                .get_impls(engines, type_id, false);
996            for e in impls {
997                let map_trait_name = CallPath {
998                    prefixes: e.key.name.prefixes.clone(),
999                    suffix: e.key.name.suffix.name.clone(),
1000                    callpath_type: e.key.name.callpath_type,
1001                };
1002                if &map_trait_name == trait_name
1003                    && unify_check.check(type_id, e.key.type_id)
1004                    && trait_type_args.len() == e.key.name.suffix.args.len()
1005                    && trait_type_args
1006                        .iter()
1007                        .zip(e.key.name.suffix.args.iter())
1008                        .all(|(t1, t2)| unify_check.check(t1.type_id, t2.type_id))
1009                {
1010                    let type_mapping =
1011                        TypeSubstMap::from_superset_and_subset(engines, e.key.type_id, type_id);
1012
1013                    let mut trait_items = Self::filter_dummy_methods(
1014                        e.value.trait_items,
1015                        type_id,
1016                        e.key.type_id,
1017                        engines,
1018                    )
1019                    .values()
1020                    .cloned()
1021                    .map(|i| {
1022                        Self::make_item_for_type_mapping(
1023                            engines,
1024                            i,
1025                            type_mapping.clone(),
1026                            type_id,
1027                            CodeBlockFirstPass::No,
1028                        )
1029                    })
1030                    .collect::<Vec<_>>();
1031
1032                    items.append(&mut trait_items);
1033                }
1034            }
1035            Ok(None::<()>)
1036        });
1037        items
1038    }
1039
1040    /// Find the entries in `self` that are equivalent to `type_id` with trait
1041    /// name `trait_name` and with trait type arguments.
1042    ///
1043    /// Notes:
1044    /// - equivalency is defined (1) based on whether the types contains types
1045    ///     that are dynamic and can change and (2) whether the types hold
1046    ///     equivalency after (1) is fulfilled
1047    /// - this method does not translate types from the found entries to the
1048    ///     `type_id` (like in `filter_by_type()`). This is because the only
1049    ///     entries that qualify as hits are equivalents of `type_id`
1050    pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments_typed(
1051        module: &Module,
1052        engines: &Engines,
1053        type_id: TypeId,
1054        trait_name: &CallPath,
1055        trait_type_args: &[TypeArgument],
1056    ) -> Vec<ty::TyTraitItem> {
1057        TraitMap::get_items_for_type_and_trait_name_and_trait_type_arguments(
1058            module,
1059            engines,
1060            type_id,
1061            trait_name,
1062            trait_type_args,
1063        )
1064        .into_iter()
1065        .map(|item| item.expect_typed())
1066        .collect::<Vec<_>>()
1067    }
1068
1069    pub(crate) fn get_trait_names_and_type_arguments_for_type(
1070        module: &Module,
1071        engines: &Engines,
1072        type_id: TypeId,
1073    ) -> Vec<(CallPath, Vec<TypeArgument>)> {
1074        let type_id = engines.te().get_unaliased_type_id(type_id);
1075
1076        let type_engine = engines.te();
1077        let unify_check = UnifyCheck::constraint_subset(engines);
1078        let mut trait_names = vec![];
1079        // small performance gain in bad case
1080        if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1081            return trait_names;
1082        }
1083        let _ = module.walk_scope_chain(|lexical_scope| {
1084            let impls = lexical_scope
1085                .items
1086                .implemented_traits
1087                .get_impls(engines, type_id, false);
1088            for entry in impls {
1089                if unify_check.check(type_id, entry.key.type_id) {
1090                    let trait_call_path = CallPath {
1091                        prefixes: entry.key.name.prefixes.clone(),
1092                        suffix: entry.key.name.suffix.name.clone(),
1093                        callpath_type: entry.key.name.callpath_type,
1094                    };
1095                    trait_names.push((trait_call_path, entry.key.name.suffix.args.clone()));
1096                }
1097            }
1098            Ok(None::<()>)
1099        });
1100        trait_names
1101    }
1102
1103    pub(crate) fn get_trait_item_for_type(
1104        module: &Module,
1105        handler: &Handler,
1106        engines: &Engines,
1107        symbol: &Ident,
1108        type_id: TypeId,
1109        as_trait: Option<CallPath>,
1110    ) -> Result<ResolvedTraitImplItem, ErrorEmitted> {
1111        let type_id = engines.te().get_unaliased_type_id(type_id);
1112
1113        let mut candidates = HashMap::<String, ResolvedTraitImplItem>::new();
1114        for (trait_item, trait_key) in
1115            TraitMap::get_items_and_trait_key_for_type(module, engines, type_id)
1116        {
1117            match trait_item {
1118                ResolvedTraitImplItem::Parsed(impl_item) => match impl_item {
1119                    ImplItem::Fn(fn_ref) => {
1120                        let decl = engines.pe().get_function(&fn_ref);
1121                        let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1122                        if decl.name.as_str() == symbol.as_str()
1123                            && (as_trait.is_none()
1124                                || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1125                        {
1126                            candidates.insert(
1127                                trait_call_path_string,
1128                                ResolvedTraitImplItem::Parsed(ImplItem::Fn(fn_ref)),
1129                            );
1130                        }
1131                    }
1132                    ImplItem::Constant(const_ref) => {
1133                        let decl = engines.pe().get_constant(&const_ref);
1134                        let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1135                        if decl.name.as_str() == symbol.as_str()
1136                            && (as_trait.is_none()
1137                                || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1138                        {
1139                            candidates.insert(
1140                                trait_call_path_string,
1141                                ResolvedTraitImplItem::Parsed(ImplItem::Constant(const_ref)),
1142                            );
1143                        }
1144                    }
1145                    ImplItem::Type(type_ref) => {
1146                        let decl = engines.pe().get_trait_type(&type_ref);
1147                        let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1148                        if decl.name.as_str() == symbol.as_str()
1149                            && (as_trait.is_none()
1150                                || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1151                        {
1152                            candidates.insert(
1153                                trait_call_path_string,
1154                                ResolvedTraitImplItem::Parsed(ImplItem::Type(type_ref)),
1155                            );
1156                        }
1157                    }
1158                },
1159                ResolvedTraitImplItem::Typed(ty_impl_item) => match ty_impl_item {
1160                    ty::TyTraitItem::Fn(fn_ref) => {
1161                        let decl = engines.de().get_function(&fn_ref);
1162                        let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1163                        if decl.name.as_str() == symbol.as_str()
1164                            && (as_trait.is_none()
1165                                || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1166                        {
1167                            candidates.insert(
1168                                trait_call_path_string,
1169                                ResolvedTraitImplItem::Typed(TyTraitItem::Fn(fn_ref)),
1170                            );
1171                        }
1172                    }
1173                    ty::TyTraitItem::Constant(const_ref) => {
1174                        let decl = engines.de().get_constant(&const_ref);
1175                        let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1176                        if decl.call_path.suffix.as_str() == symbol.as_str()
1177                            && (as_trait.is_none()
1178                                || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1179                        {
1180                            candidates.insert(
1181                                trait_call_path_string,
1182                                ResolvedTraitImplItem::Typed(TyTraitItem::Constant(const_ref)),
1183                            );
1184                        }
1185                    }
1186                    ty::TyTraitItem::Type(type_ref) => {
1187                        let decl = engines.de().get_type(&type_ref);
1188                        let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1189                        if decl.name.as_str() == symbol.as_str()
1190                            && (as_trait.is_none()
1191                                || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1192                        {
1193                            candidates.insert(
1194                                trait_call_path_string,
1195                                ResolvedTraitImplItem::Typed(TyTraitItem::Type(type_ref)),
1196                            );
1197                        }
1198                    }
1199                },
1200            }
1201        }
1202
1203        match candidates.len().cmp(&1) {
1204            Ordering::Greater => Err(handler.emit_err(
1205                CompileError::MultipleApplicableItemsInScope {
1206                    item_name: symbol.as_str().to_string(),
1207                    item_kind: "item".to_string(),
1208                    as_traits: candidates
1209                        .keys()
1210                        .map(|k| {
1211                            (
1212                                k.clone()
1213                                    .split("::")
1214                                    .collect::<Vec<_>>()
1215                                    .last()
1216                                    .unwrap()
1217                                    .to_string(),
1218                                engines.help_out(type_id).to_string(),
1219                            )
1220                        })
1221                        .collect::<Vec<_>>(),
1222                    span: symbol.span(),
1223                },
1224            )),
1225            Ordering::Less => Err(handler.emit_err(CompileError::SymbolNotFound {
1226                name: symbol.clone(),
1227                span: symbol.span(),
1228            })),
1229            Ordering::Equal => Ok(candidates.values().next().unwrap().clone()),
1230        }
1231    }
1232
1233    /// Checks to see if the trait constraints are satisfied for a given type.
1234    #[allow(clippy::too_many_arguments)]
1235    pub(crate) fn check_if_trait_constraints_are_satisfied_for_type(
1236        handler: &Handler,
1237        module: &mut Module,
1238        type_id: TypeId,
1239        constraints: &[TraitConstraint],
1240        access_span: &Span,
1241        engines: &Engines,
1242    ) -> Result<(), ErrorEmitted> {
1243        let type_engine = engines.te();
1244
1245        let type_id = type_engine.get_unaliased_type_id(type_id);
1246
1247        // resolving trait constraints require a concrete type, we need to default numeric to u64
1248        type_engine.decay_numeric(handler, engines, type_id, access_span)?;
1249
1250        if constraints.is_empty() {
1251            return Ok(());
1252        }
1253
1254        // Check we can use the cache
1255        let mut hasher = DefaultHasher::default();
1256        type_id.hash(&mut hasher);
1257        for c in constraints {
1258            c.hash(&mut hasher, engines);
1259        }
1260        let hash = hasher.finish();
1261
1262        {
1263            let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1264            if trait_map.satisfied_cache.contains(&hash) {
1265                return Ok(());
1266            }
1267        }
1268
1269        let all_impld_traits: BTreeSet<(Ident, TypeId)> =
1270            Self::get_all_implemented_traits(module, type_id, engines);
1271
1272        // Call the real implementation and cache when true
1273        match Self::check_if_trait_constraints_are_satisfied_for_type_inner(
1274            handler,
1275            type_id,
1276            constraints,
1277            access_span,
1278            engines,
1279            all_impld_traits,
1280        ) {
1281            Ok(()) => {
1282                let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1283                trait_map.satisfied_cache.insert(hash);
1284                Ok(())
1285            }
1286            r => r,
1287        }
1288    }
1289
1290    fn get_all_implemented_traits(
1291        module: &Module,
1292        type_id: TypeId,
1293        engines: &Engines,
1294    ) -> BTreeSet<(Ident, TypeId)> {
1295        let mut all_impld_traits: BTreeSet<(Ident, TypeId)> = Default::default();
1296        let _ = module.walk_scope_chain(|lexical_scope| {
1297            all_impld_traits.extend(
1298                lexical_scope
1299                    .items
1300                    .implemented_traits
1301                    .get_implemented_traits(type_id, engines),
1302            );
1303            Ok(None::<()>)
1304        });
1305        all_impld_traits
1306    }
1307
1308    fn get_implemented_traits(
1309        &self,
1310        type_id: TypeId,
1311        engines: &Engines,
1312    ) -> BTreeSet<(Ident, TypeId)> {
1313        let type_engine = engines.te();
1314        let unify_check = UnifyCheck::constraint_subset(engines);
1315
1316        let impls = self.get_impls(engines, type_id, true);
1317        let all_impld_traits: BTreeSet<(Ident, TypeId)> = impls
1318            .iter()
1319            .filter_map(|e| {
1320                let key = &e.key;
1321                let suffix = &key.name.suffix;
1322                if unify_check.check(type_id, key.type_id) {
1323                    let map_trait_type_id = type_engine.new_custom(
1324                        engines,
1325                        suffix.name.clone().into(),
1326                        if suffix.args.is_empty() {
1327                            None
1328                        } else {
1329                            Some(suffix.args.to_vec())
1330                        },
1331                    );
1332                    Some((suffix.name.clone(), map_trait_type_id))
1333                } else {
1334                    None
1335                }
1336            })
1337            .collect();
1338
1339        all_impld_traits
1340    }
1341
1342    #[allow(clippy::too_many_arguments)]
1343    fn check_if_trait_constraints_are_satisfied_for_type_inner(
1344        handler: &Handler,
1345        type_id: TypeId,
1346        constraints: &[TraitConstraint],
1347        access_span: &Span,
1348        engines: &Engines,
1349        all_impld_traits: BTreeSet<(Ident, TypeId)>,
1350    ) -> Result<(), ErrorEmitted> {
1351        let type_engine = engines.te();
1352        let unify_check = UnifyCheck::constraint_subset(engines);
1353
1354        let required_traits: BTreeSet<(Ident, TypeId)> = constraints
1355            .iter()
1356            .map(|c| {
1357                let TraitConstraint {
1358                    trait_name: constraint_trait_name,
1359                    type_arguments: constraint_type_arguments,
1360                } = c;
1361                let constraint_type_id = type_engine.new_custom(
1362                    engines,
1363                    constraint_trait_name.suffix.clone().into(),
1364                    if constraint_type_arguments.is_empty() {
1365                        None
1366                    } else {
1367                        Some(constraint_type_arguments.clone())
1368                    },
1369                );
1370                (c.trait_name.suffix.clone(), constraint_type_id)
1371            })
1372            .collect();
1373
1374        let traits_not_found: BTreeSet<(BaseIdent, TypeId)> = required_traits
1375            .into_iter()
1376            .filter(|(required_trait_name, required_trait_type_id)| {
1377                !all_impld_traits
1378                    .iter()
1379                    .any(|(trait_name, constraint_type_id)| {
1380                        trait_name == required_trait_name
1381                            && unify_check.check(*constraint_type_id, *required_trait_type_id)
1382                    })
1383            })
1384            .collect();
1385
1386        handler.scope(|handler| {
1387            for (trait_name, constraint_type_id) in traits_not_found.iter() {
1388                let mut type_arguments_string = "".to_string();
1389                if let TypeInfo::Custom {
1390                    qualified_call_path: _,
1391                    type_arguments: Some(type_arguments),
1392                } = &*type_engine.get(*constraint_type_id)
1393                {
1394                    type_arguments_string = format!("<{}>", engines.help_out(type_arguments));
1395                }
1396
1397                // TODO: use a better span
1398                handler.emit_err(CompileError::TraitConstraintNotSatisfied {
1399                    type_id: type_id.index(),
1400                    ty: engines.help_out(type_id).to_string(),
1401                    trait_name: format!("{}{}", trait_name, type_arguments_string),
1402                    span: access_span.clone(),
1403                });
1404            }
1405
1406            Ok(())
1407        })
1408    }
1409
1410    pub fn get_trait_constraints_are_satisfied_for_types(
1411        module: &Module,
1412        _handler: &Handler,
1413        type_id: TypeId,
1414        constraints: &[TraitConstraint],
1415        engines: &Engines,
1416    ) -> Result<Vec<(TypeId, String)>, ErrorEmitted> {
1417        let type_id = engines.te().get_unaliased_type_id(type_id);
1418
1419        let _decl_engine = engines.de();
1420        let unify_check = UnifyCheck::coercion(engines);
1421        let unify_check_equality = UnifyCheck::constraint_subset(engines);
1422
1423        let mut impld_traits_type_ids: Vec<Vec<(TypeId, String)>> = vec![];
1424        let _ = module.walk_scope_chain(|lexical_scope| {
1425            let impls = lexical_scope
1426                .items
1427                .implemented_traits
1428                .get_impls(engines, type_id, true);
1429            impld_traits_type_ids.push(
1430                impls
1431                    .iter()
1432                    .filter_map(|e| {
1433                        let key = &e.key;
1434                        let mut res = None;
1435                        for constraint in constraints {
1436                            if key.name.suffix.name == constraint.trait_name.suffix
1437                                && key
1438                                    .name
1439                                    .suffix
1440                                    .args
1441                                    .iter()
1442                                    .zip(constraint.type_arguments.iter())
1443                                    .all(|(a1, a2)| {
1444                                        unify_check_equality.check(a1.type_id, a2.type_id)
1445                                    })
1446                                && unify_check.check(type_id, key.type_id)
1447                            {
1448                                let name_type_args = if !key.name.suffix.args.is_empty() {
1449                                    format!("<{}>", engines.help_out(key.name.suffix.args.clone()))
1450                                } else {
1451                                    "".to_string()
1452                                };
1453                                let name =
1454                                    format!("{}{}", key.name.suffix.name.as_str(), name_type_args);
1455                                res = Some((key.type_id, name));
1456                                break;
1457                            }
1458                        }
1459                        res
1460                    })
1461                    .collect(),
1462            );
1463
1464            Ok(None::<()>)
1465        });
1466        Ok(impld_traits_type_ids.concat())
1467    }
1468
1469    fn get_impls_mut(&mut self, engines: &Engines, type_id: TypeId) -> &mut Vec<TraitEntry> {
1470        let type_root_filter = Self::get_type_root_filter(engines, type_id);
1471        if !self.trait_impls.contains_key(&type_root_filter) {
1472            self.trait_impls
1473                .insert(type_root_filter.clone(), Vec::new());
1474        }
1475
1476        self.trait_impls.get_mut(&type_root_filter).unwrap()
1477    }
1478
1479    fn get_impls(
1480        &self,
1481        engines: &Engines,
1482        type_id: TypeId,
1483        extend_with_placeholder: bool,
1484    ) -> Vec<TraitEntry> {
1485        let type_root_filter = Self::get_type_root_filter(engines, type_id);
1486        let mut vec = self
1487            .trait_impls
1488            .get(&type_root_filter)
1489            .cloned()
1490            .unwrap_or_default();
1491        if extend_with_placeholder && type_root_filter != TypeRootFilter::Placeholder {
1492            vec.extend(
1493                self.trait_impls
1494                    .get(&TypeRootFilter::Placeholder)
1495                    .cloned()
1496                    .unwrap_or_default(),
1497            );
1498        }
1499        vec
1500    }
1501
1502    // Return a string representing only the base type.
1503    // This is used by the trait map to filter the entries into a HashMap with the return type string as key.
1504    fn get_type_root_filter(engines: &Engines, type_id: TypeId) -> TypeRootFilter {
1505        use TypeInfo::*;
1506        match &*engines.te().get(type_id) {
1507            Unknown => TypeRootFilter::Unknown,
1508            Never => TypeRootFilter::Never,
1509            UnknownGeneric { .. } | Placeholder(_) => TypeRootFilter::Placeholder,
1510            TypeParam(_param) => unreachable!(),
1511            StringSlice => TypeRootFilter::StringSlice,
1512            StringArray(x) => TypeRootFilter::StringArray(x.val()),
1513            UnsignedInteger(x) => match x {
1514                IntegerBits::Eight => TypeRootFilter::U8,
1515                IntegerBits::Sixteen => TypeRootFilter::U16,
1516                IntegerBits::ThirtyTwo => TypeRootFilter::U32,
1517                IntegerBits::SixtyFour => TypeRootFilter::U64,
1518                IntegerBits::V256 => TypeRootFilter::U256,
1519            },
1520            Boolean => TypeRootFilter::Bool,
1521            Custom {
1522                qualified_call_path: call_path,
1523                ..
1524            } => TypeRootFilter::Custom(call_path.call_path.suffix.to_string()),
1525            B256 => TypeRootFilter::B256,
1526            Numeric => TypeRootFilter::U64, // u64 is the default
1527            Contract => TypeRootFilter::Contract,
1528            ErrorRecovery(_) => TypeRootFilter::ErrorRecovery,
1529            Tuple(fields) => TypeRootFilter::Tuple(fields.len()),
1530            UntypedEnum(decl_id) => TypeRootFilter::Enum(*decl_id),
1531            UntypedStruct(decl_id) => TypeRootFilter::Struct(*decl_id),
1532            Enum(decl_id) => {
1533                // TODO Remove unwrap once #6475 is fixed
1534                TypeRootFilter::Enum(engines.de().get_parsed_decl_id(decl_id).unwrap())
1535            }
1536            Struct(decl_id) => {
1537                // TODO Remove unwrap once #6475 is fixed
1538                TypeRootFilter::Struct(engines.de().get_parsed_decl_id(decl_id).unwrap())
1539            }
1540            ContractCaller { abi_name, .. } => TypeRootFilter::ContractCaller(abi_name.to_string()),
1541            Array(_, _) => TypeRootFilter::Array,
1542            RawUntypedPtr => TypeRootFilter::RawUntypedPtr,
1543            RawUntypedSlice => TypeRootFilter::RawUntypedSlice,
1544            Ptr(_) => TypeRootFilter::Ptr,
1545            Slice(_) => TypeRootFilter::Slice,
1546            Alias { ty, .. } => Self::get_type_root_filter(engines, ty.type_id),
1547            TraitType { name, .. } => TypeRootFilter::TraitType(name.to_string()),
1548            Ref {
1549                referenced_type, ..
1550            } => Self::get_type_root_filter(engines, referenced_type.type_id),
1551        }
1552    }
1553}