1use std::{
2 cmp::Ordering,
3 collections::{BTreeMap, BTreeSet, HashMap, HashSet},
4 fmt,
5 hash::{DefaultHasher, Hash, Hasher},
6 sync::Arc,
7};
8
9use sway_error::{
10 error::CompileError,
11 handler::{ErrorEmitted, Handler},
12};
13use sway_types::{integer_bits::IntegerBits, BaseIdent, Ident, Span, Spanned};
14
15use crate::{
16 decl_engine::{
17 parsed_id::ParsedDeclId, DeclEngineGet, DeclEngineGetParsedDeclId, DeclEngineInsert,
18 },
19 engine_threading::*,
20 language::{
21 parsed::{EnumDeclaration, ImplItem, StructDeclaration},
22 ty::{self, TyDecl, TyImplItem, TyTraitItem},
23 CallPath,
24 },
25 type_system::{SubstTypes, TypeId},
26 GenericArgument, IncludeSelf, SubstTypesContext, TraitConstraint, TypeEngine, TypeInfo,
27 TypeSubstMap, UnifyCheck,
28};
29
30use super::Module;
31
32#[derive(Debug, Clone)]
35pub enum TryInsertingTraitImplOnFailure {
36 Yes,
37 No,
38}
39
40#[derive(Clone)]
41pub enum CodeBlockFirstPass {
42 Yes,
43 No,
44}
45
46impl From<bool> for CodeBlockFirstPass {
47 fn from(value: bool) -> Self {
48 if value {
49 CodeBlockFirstPass::Yes
50 } else {
51 CodeBlockFirstPass::No
52 }
53 }
54}
55
56#[derive(Clone, Debug)]
57pub(crate) struct TraitSuffix {
58 pub(crate) name: Ident,
59 pub(crate) args: Vec<GenericArgument>,
60}
61impl PartialEqWithEngines for TraitSuffix {
62 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
63 self.name == other.name && self.args.eq(&other.args, ctx)
64 }
65}
66impl OrdWithEngines for TraitSuffix {
67 fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> std::cmp::Ordering {
68 self.name
69 .cmp(&other.name)
70 .then_with(|| self.args.cmp(&other.args, ctx))
71 }
72}
73
74impl DisplayWithEngines for TraitSuffix {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
76 let res = write!(f, "{}", self.name.as_str());
77 if !self.args.is_empty() {
78 write!(
79 f,
80 "<{}>",
81 self.args
82 .iter()
83 .map(|i| engines.help_out(i.type_id()).to_string())
84 .collect::<Vec<_>>()
85 .join(", ")
86 )
87 } else {
88 res
89 }
90 }
91}
92
93impl DebugWithEngines for TraitSuffix {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
95 write!(f, "{}", engines.help_out(self))
96 }
97}
98
99type TraitName = Arc<CallPath<TraitSuffix>>;
100
101#[derive(Clone, Debug)]
102pub(crate) struct TraitKey {
103 pub(crate) name: TraitName,
104 pub(crate) type_id: TypeId,
105 pub(crate) impl_type_parameters: Vec<TypeId>,
106 pub(crate) trait_decl_span: Option<Span>,
107 pub(crate) is_impl_interface_surface: IsImplInterfaceSurface,
108}
109
110impl OrdWithEngines for TraitKey {
111 fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> std::cmp::Ordering {
112 self.name.cmp(&other.name, ctx).then_with(|| {
113 self.type_id
114 .cmp(&other.type_id)
115 .then_with(|| self.impl_type_parameters.cmp(&other.impl_type_parameters))
116 })
117 }
118}
119
120#[derive(Clone, Debug)]
121pub enum ResolvedTraitImplItem {
122 Parsed(ImplItem),
123 Typed(TyImplItem),
124}
125
126impl DebugWithEngines for ResolvedTraitImplItem {
127 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
128 match self {
129 ResolvedTraitImplItem::Parsed(_) => panic!(),
130 ResolvedTraitImplItem::Typed(ty) => write!(f, "{:?}", engines.help_out(ty)),
131 }
132 }
133}
134
135impl ResolvedTraitImplItem {
136 fn expect_typed(self) -> TyImplItem {
137 match self {
138 ResolvedTraitImplItem::Parsed(_) => panic!(),
139 ResolvedTraitImplItem::Typed(ty) => ty,
140 }
141 }
142
143 pub fn span(&self, engines: &Engines) -> Span {
144 match self {
145 ResolvedTraitImplItem::Parsed(item) => item.span(engines),
146 ResolvedTraitImplItem::Typed(item) => item.span(),
147 }
148 }
149}
150
151type TraitItems = BTreeMap<String, ResolvedTraitImplItem>;
153
154#[derive(Clone, Debug)]
155pub(crate) struct TraitValue {
156 pub(crate) trait_items: TraitItems,
157 pub(crate) impl_span: Span,
159}
160
161#[derive(Clone, Debug)]
162pub(crate) struct TraitEntry {
163 pub(crate) key: TraitKey,
164 pub(crate) value: TraitValue,
165}
166
167#[derive(Clone, Debug)]
168pub(crate) struct SharedTraitEntry {
169 pub(crate) inner: Arc<TraitEntry>,
170}
171
172impl SharedTraitEntry {
173 pub fn fork_if_non_unique(&mut self) -> &mut Self {
174 match Arc::get_mut(&mut self.inner) {
175 Some(_) => {}
176 None => {
177 let data = TraitEntry::clone(&self.inner);
178 self.inner = Arc::new(data);
179 }
180 }
181
182 self
183 }
184
185 pub fn get_mut(&mut self) -> &mut TraitEntry {
186 Arc::get_mut(&mut self.inner).unwrap()
187 }
188}
189
190pub(crate) type TraitImpls = BTreeMap<TypeRootFilter, Vec<SharedTraitEntry>>;
194
195#[derive(Clone, Hash, Eq, PartialOrd, Ord, PartialEq, Debug)]
196pub(crate) enum TypeRootFilter {
197 Unknown,
198 Never,
199 Placeholder,
200 StringSlice,
201 StringArray,
202 U8,
203 U16,
204 U32,
205 U64,
206 U256,
207 Bool,
208 Custom(String),
209 B256,
210 Contract,
211 ErrorRecovery,
212 Tuple(usize),
213 Enum(ParsedDeclId<EnumDeclaration>),
214 Struct(ParsedDeclId<StructDeclaration>),
215 ContractCaller(String),
216 Array,
217 RawUntypedPtr,
218 RawUntypedSlice,
219 Ptr,
220 Slice,
221 TraitType(String),
222}
223
224impl DebugWithEngines for TypeRootFilter {
225 fn fmt(&self, f: &mut fmt::Formatter<'_>, _engines: &Engines) -> fmt::Result {
226 use TypeRootFilter::*;
227 match self {
228 Unknown => write!(f, "Unknown"),
229 Never => write!(f, "Never"),
230 Placeholder => write!(f, "Placeholder"),
231 StringSlice => write!(f, "StringSlice"),
232 StringArray => write!(f, "StringArray"),
233 U8 => write!(f, "u8"),
234 U16 => write!(f, "u16"),
235 U32 => write!(f, "u32"),
236 U64 => write!(f, "u64"),
237 U256 => write!(f, "u256"),
238 Bool => write!(f, "bool"),
239 Custom(name) => write!(f, "Custom({name})"),
240 B256 => write!(f, "b256"),
241 Contract => write!(f, "Contract"),
242 ErrorRecovery => write!(f, "ErrorRecovery"),
243 Tuple(n) => write!(f, "Tuple(len={n})"),
244 Enum(parsed_id) => {
245 write!(f, "Enum({parsed_id:?})")
246 }
247 Struct(parsed_id) => {
248 write!(f, "Struct({parsed_id:?})")
249 }
250 ContractCaller(abi_name) => write!(f, "ContractCaller({abi_name})"),
251 Array => write!(f, "Array"),
252 RawUntypedPtr => write!(f, "RawUntypedPtr"),
253 RawUntypedSlice => write!(f, "RawUntypedSlice"),
254 Ptr => write!(f, "Ptr"),
255 Slice => write!(f, "Slice"),
256 TraitType(name) => write!(f, "TraitType({name})"),
257 }
258 }
259}
260
261#[derive(Clone, Debug, Default)]
266pub struct TraitMap {
267 pub(crate) trait_impls: TraitImpls,
268 satisfied_cache: HashSet<u64>,
269}
270
271pub(crate) enum IsImplSelf {
272 Yes,
273 No,
274}
275
276pub(crate) enum IsExtendingExistingImpl {
277 Yes,
278 No,
279}
280
281#[derive(Clone, Debug)]
282pub(crate) enum IsImplInterfaceSurface {
283 Yes,
284 No,
285}
286
287impl DebugWithEngines for TraitMap {
288 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
289 if self.trait_impls.is_empty() {
290 return write!(f, "TraitMap {{ <empty> }}");
291 }
292
293 writeln!(f, "TraitMap {{")?;
294
295 for (root, entries) in &self.trait_impls {
296 writeln!(f, " [root={:?}]", engines.help_out(root))?;
297
298 for se in entries {
299 let entry = &se.inner;
300 let key = &entry.key;
301 let value = &entry.value;
302
303 let trait_name_str = engines.help_out(&*key.name).to_string();
304 let ty_str = engines.help_out(key.type_id).to_string();
305
306 let iface_flag = match key.is_impl_interface_surface {
307 IsImplInterfaceSurface::Yes => "interface_surface",
308 IsImplInterfaceSurface::No => "impl",
309 };
310
311 let mut impl_tparams = String::new();
312 if !key.impl_type_parameters.is_empty() {
313 impl_tparams.push_str(" where [");
314 let mut first = true;
315 for t in &key.impl_type_parameters {
316 if !first {
317 impl_tparams.push_str(", ");
318 }
319 first = false;
320 impl_tparams.push_str(&engines.help_out(*t).to_string());
321 }
322 impl_tparams.push(']');
323 }
324
325 writeln!(
326 f,
327 " impl {trait_name_str} for {ty_str} [{iface_flag}]{impl_tparams} {{"
328 )?;
329
330 for (name, item) in &value.trait_items {
331 match item {
332 ResolvedTraitImplItem::Parsed(_p) => {
333 writeln!(f, " - {name}: <parsed>")?;
334 }
335 ResolvedTraitImplItem::Typed(ty_item) => {
336 writeln!(f, " - {}: {:?}", name, engines.help_out(ty_item))?;
337 }
338 }
339 }
340
341 writeln!(f, " [impl span: {:?}]", value.impl_span)?;
342 writeln!(f, " }}")?;
343 }
344 }
345
346 write!(f, "}}")
347 }
348}
349
350impl TraitMap {
351 #[allow(clippy::too_many_arguments)]
359 pub(crate) fn insert(
360 &mut self,
361 handler: &Handler,
362 trait_name: CallPath,
363 trait_type_args: Vec<GenericArgument>,
364 type_id: TypeId,
365 impl_type_parameters: Vec<TypeId>,
366 items: &[ResolvedTraitImplItem],
367 impl_span: &Span,
368 trait_decl_span: Option<Span>,
369 is_impl_self: IsImplSelf,
370 is_extending_existing_impl: IsExtendingExistingImpl,
371 is_impl_interface_surface: IsImplInterfaceSurface,
372 engines: &Engines,
373 ) -> Result<(), ErrorEmitted> {
374 let unaliased_type_id = engines.te().get_unaliased_type_id(type_id);
375
376 handler.scope(|handler| {
377 let mut trait_items: TraitItems = BTreeMap::new();
378 for item in items.iter() {
379 match item {
380 ResolvedTraitImplItem::Parsed(_) => todo!(),
381 ResolvedTraitImplItem::Typed(ty_item) => match ty_item {
382 TyImplItem::Fn(decl_ref) => {
383 if trait_items
384 .insert(decl_ref.name().clone().to_string(), item.clone())
385 .is_some()
386 {
387 handler.emit_err(CompileError::MultipleDefinitionsOfName {
389 name: decl_ref.name().clone(),
390 span: decl_ref.span(),
391 });
392 }
393 }
394 TyImplItem::Constant(decl_ref) => {
395 trait_items.insert(decl_ref.name().to_string(), item.clone());
396 }
397 TyImplItem::Type(decl_ref) => {
398 trait_items.insert(decl_ref.name().to_string(), item.clone());
399 }
400 },
401 }
402 }
403
404 let trait_impls = self.get_impls_mut(engines, unaliased_type_id);
405
406 for entry in trait_impls.iter() {
408 let TraitEntry {
409 key:
410 TraitKey {
411 name: map_trait_name,
412 type_id: map_type_id,
413 trait_decl_span: _,
414 impl_type_parameters: _,
415 is_impl_interface_surface: map_is_impl_interface_surface,
416 },
417 value:
418 TraitValue {
419 trait_items: map_trait_items,
420 impl_span: existing_impl_span,
421 },
422 } = entry.inner.as_ref();
423 let CallPath {
424 suffix:
425 TraitSuffix {
426 name: map_trait_name_suffix,
427 args: map_trait_type_args,
428 },
429 ..
430 } = &*map_trait_name.clone();
431
432 let unify_checker = UnifyCheck::non_generic_constraint_subset(engines);
433
434 let types_are_subset = unify_checker.check(unaliased_type_id, *map_type_id)
438 && is_unified_type_subset(engines.te(), unaliased_type_id, *map_type_id);
439
440 fn is_unified_type_subset(
446 type_engine: &TypeEngine,
447 mut left: TypeId,
448 mut right: TypeId,
449 ) -> bool {
450 loop {
453 let left_ty_info = &*type_engine.get_unaliased(left);
454 let right_ty_info = &*type_engine.get_unaliased(right);
455 match (left_ty_info, right_ty_info) {
456 (
457 TypeInfo::Ref {
458 to_mutable_value: l_to_mut,
459 ..
460 },
461 TypeInfo::Ref {
462 to_mutable_value: r_to_mut,
463 ..
464 },
465 ) if *l_to_mut != *r_to_mut => return false, (
467 TypeInfo::Ref {
468 referenced_type: l_ty,
469 ..
470 },
471 TypeInfo::Ref {
472 referenced_type: r_ty,
473 ..
474 },
475 ) => {
476 left = l_ty.type_id;
477 right = r_ty.type_id;
478 }
479 _ => return true,
480 }
481 }
482 }
483
484 let mut traits_are_subset = true;
485 if *map_trait_name_suffix != trait_name.suffix
486 || map_trait_type_args.len() != trait_type_args.len()
487 {
488 traits_are_subset = false;
489 } else {
490 for (map_arg_type, arg_type) in
491 map_trait_type_args.iter().zip(trait_type_args.iter())
492 {
493 if !unify_checker.check(arg_type.type_id(), map_arg_type.type_id()) {
494 traits_are_subset = false;
495 }
496 }
497 }
498
499 let should_check = matches!(is_impl_interface_surface, IsImplInterfaceSurface::No);
500 if should_check {
501 if matches!(is_extending_existing_impl, IsExtendingExistingImpl::No)
502 && types_are_subset
503 && traits_are_subset
504 && matches!(is_impl_self, IsImplSelf::No)
505 && matches!(map_is_impl_interface_surface, IsImplInterfaceSurface::No)
506 {
507 handler.emit_err(CompileError::ConflictingImplsForTraitAndType {
508 trait_name: trait_name.to_string_with_args(engines, &trait_type_args),
509 type_implementing_for: engines.help_out(type_id).to_string(),
510 type_implementing_for_unaliased: engines
511 .help_out(unaliased_type_id)
512 .to_string(),
513 existing_impl_span: existing_impl_span.clone(),
514 second_impl_span: impl_span.clone(),
515 });
516 } else if types_are_subset
517 && (traits_are_subset || matches!(is_impl_self, IsImplSelf::Yes))
518 && matches!(map_is_impl_interface_surface, IsImplInterfaceSurface::No)
519 {
520 for name in trait_items.keys() {
521 let item = &trait_items[name];
522 match item {
523 ResolvedTraitImplItem::Parsed(_item) => todo!(),
524 ResolvedTraitImplItem::Typed(item) => match item {
525 ty::TyTraitItem::Fn(decl_ref) => {
526 if let Some(existing_item) = map_trait_items.get(name) {
527 handler.emit_err(
528 CompileError::DuplicateDeclDefinedForType {
529 decl_kind: "method".into(),
530 decl_name: decl_ref.name().to_string(),
531 type_implementing_for: engines
532 .help_out(type_id)
533 .to_string(),
534 type_implementing_for_unaliased: engines
535 .help_out(unaliased_type_id)
536 .to_string(),
537 existing_impl_span: existing_item
538 .span(engines)
539 .clone(),
540 second_impl_span: decl_ref.name().span(),
541 },
542 );
543 }
544 }
545 ty::TyTraitItem::Constant(decl_ref) => {
546 if let Some(existing_item) = map_trait_items.get(name) {
547 handler.emit_err(
548 CompileError::DuplicateDeclDefinedForType {
549 decl_kind: "constant".into(),
550 decl_name: decl_ref.name().to_string(),
551 type_implementing_for: engines
552 .help_out(type_id)
553 .to_string(),
554 type_implementing_for_unaliased: engines
555 .help_out(unaliased_type_id)
556 .to_string(),
557 existing_impl_span: existing_item
558 .span(engines)
559 .clone(),
560 second_impl_span: decl_ref.name().span(),
561 },
562 );
563 }
564 }
565 ty::TyTraitItem::Type(decl_ref) => {
566 if let Some(existing_item) = map_trait_items.get(name) {
567 handler.emit_err(
568 CompileError::DuplicateDeclDefinedForType {
569 decl_kind: "type".into(),
570 decl_name: decl_ref.name().to_string(),
571 type_implementing_for: engines
572 .help_out(type_id)
573 .to_string(),
574 type_implementing_for_unaliased: engines
575 .help_out(unaliased_type_id)
576 .to_string(),
577 existing_impl_span: existing_item
578 .span(engines)
579 .clone(),
580 second_impl_span: decl_ref.name().span(),
581 },
582 );
583 }
584 }
585 },
586 }
587 }
588 }
589 }
590 }
591 let trait_name: TraitName = Arc::new(CallPath {
592 prefixes: trait_name.prefixes,
593 suffix: TraitSuffix {
594 name: trait_name.suffix,
595 args: trait_type_args,
596 },
597 callpath_type: trait_name.callpath_type,
598 });
599
600 self.insert_inner(
602 trait_name,
603 impl_span.clone(),
604 trait_decl_span,
605 unaliased_type_id,
606 impl_type_parameters,
607 trait_items,
608 is_impl_interface_surface,
609 engines,
610 );
611
612 Ok(())
613 })
614 }
615
616 #[allow(clippy::too_many_arguments)]
617 fn insert_inner(
618 &mut self,
619 trait_name: TraitName,
620 impl_span: Span,
621 trait_decl_span: Option<Span>,
622 type_id: TypeId,
623 impl_type_parameters: Vec<TypeId>,
624 trait_methods: TraitItems,
625 is_impl_interface_surface: IsImplInterfaceSurface,
626 engines: &Engines,
627 ) {
628 let key = TraitKey {
629 name: trait_name,
630 type_id,
631 trait_decl_span,
632 impl_type_parameters,
633 is_impl_interface_surface,
634 };
635 let value = TraitValue {
636 trait_items: trait_methods,
637 impl_span,
638 };
639 let mut trait_impls: TraitImpls = BTreeMap::new();
640 let type_root_filter = Self::get_type_root_filter(engines, type_id);
641 let entry = TraitEntry { key, value };
642 let impls_vector = vec![SharedTraitEntry {
643 inner: Arc::new(entry),
644 }];
645 trait_impls.insert(type_root_filter, impls_vector);
646
647 let trait_map = TraitMap {
648 trait_impls,
649 satisfied_cache: HashSet::default(),
650 };
651
652 self.extend(trait_map, engines);
653 }
654
655 pub(crate) fn extend(&mut self, other: TraitMap, engines: &Engines) {
658 for impls_key in other.trait_impls.keys() {
659 let oe_vec = &other.trait_impls[impls_key];
660 let self_vec = if let Some(self_vec) = self.trait_impls.get_mut(impls_key) {
661 self_vec
662 } else {
663 self.trait_impls.insert(impls_key.clone(), Vec::<_>::new());
664 self.trait_impls.get_mut(impls_key).unwrap()
665 };
666
667 for oe in oe_vec.iter() {
668 let pos = self_vec.binary_search_by(|se| {
669 se.inner
670 .key
671 .cmp(&oe.inner.key, &OrdWithEnginesContext::new(engines))
672 });
673
674 match pos {
675 Ok(pos) => self_vec[pos]
676 .fork_if_non_unique()
677 .get_mut()
678 .value
679 .trait_items
680 .extend(oe.inner.value.trait_items.clone()),
681 Err(pos) => self_vec.insert(pos, oe.clone()),
682 }
683 }
684 }
685 }
686
687 pub(crate) fn get_traits_types(
688 &self,
689 traits_types: &mut HashMap<CallPath, HashSet<TypeId>>,
690 ) -> Result<(), ErrorEmitted> {
691 for key in self.trait_impls.keys() {
692 for self_entry in self.trait_impls[key].iter() {
693 let callpath = CallPath {
694 prefixes: self_entry.inner.key.name.prefixes.clone(),
695 suffix: self_entry.inner.key.name.suffix.name.clone(),
696 callpath_type: self_entry.inner.key.name.callpath_type,
697 };
698 if let Some(set) = traits_types.get_mut(&callpath) {
699 set.insert(self_entry.inner.key.type_id);
700 } else {
701 traits_types.insert(
702 callpath,
703 vec![self_entry.inner.key.type_id].into_iter().collect(),
704 );
705 }
706 }
707 }
708 Ok(())
709 }
710
711 pub(crate) fn filter_by_trait_decl_span(&self, trait_decl_span: Span) -> TraitMap {
714 let mut trait_map = TraitMap::default();
715 for key in self.trait_impls.keys() {
716 let vec = &self.trait_impls[key];
717 for entry in vec {
718 if entry.inner.key.trait_decl_span.as_ref() == Some(&trait_decl_span) {
719 let trait_map_vec =
720 if let Some(trait_map_vec) = trait_map.trait_impls.get_mut(key) {
721 trait_map_vec
722 } else {
723 trait_map.trait_impls.insert(key.clone(), Vec::<_>::new());
724 trait_map.trait_impls.get_mut(key).unwrap()
725 };
726
727 trait_map_vec.push(entry.clone());
728 }
729 }
730 }
731 trait_map
732 }
733
734 pub(crate) fn filter_by_type_item_import(
793 &self,
794 type_id: TypeId,
795 engines: &Engines,
796 ) -> TraitMap {
797 let unify_checker = UnifyCheck::constraint_subset(engines);
798 let unify_checker_for_item_import = UnifyCheck::non_generic_constraint_subset(engines);
799
800 let decider = |left: TypeId, right: TypeId| {
802 unify_checker.check(left, right) || unify_checker_for_item_import.check(right, left)
803 };
804 let mut trait_map = self.filter_by_type_inner(engines, vec![type_id], decider);
805 let all_types = type_id
806 .extract_inner_types(engines, IncludeSelf::No)
807 .into_iter()
808 .collect::<Vec<_>>();
809 let decider2 = |left: TypeId, right: TypeId| unify_checker.check(left, right);
811
812 trait_map.extend(
813 self.filter_by_type_inner(engines, all_types, decider2),
814 engines,
815 );
816
817 for key in self.trait_impls.keys() {
819 for entry in self.trait_impls[key].iter() {
820 let TraitEntry {
821 key:
822 TraitKey {
823 name: trait_name,
824 type_id: trait_type_id,
825 trait_decl_span,
826 impl_type_parameters,
827 is_impl_interface_surface,
828 },
829 value:
830 TraitValue {
831 trait_items,
832 impl_span,
833 },
834 } = entry.inner.as_ref();
835
836 let decider3 =
837 |left: TypeId, right: TypeId| unify_checker_for_item_import.check(right, left);
838
839 let matches_generic_params = match *engines.te().get(*trait_type_id) {
840 TypeInfo::Enum(decl_id) => engines
841 .de()
842 .get(&decl_id)
843 .generic_parameters
844 .iter()
845 .any(|gp| gp.unifies(type_id, decider3)),
846 TypeInfo::Struct(decl_id) => engines
847 .de()
848 .get(&decl_id)
849 .generic_parameters
850 .iter()
851 .any(|gp| gp.unifies(type_id, decider3)),
852 _ => false,
853 };
854
855 if matches_generic_params
856 || impl_type_parameters.iter().any(|tp| decider(type_id, *tp))
857 {
858 trait_map.insert_inner(
859 trait_name.clone(),
860 impl_span.clone(),
861 trait_decl_span.clone(),
862 *trait_type_id,
863 impl_type_parameters.clone(),
864 trait_items.clone(),
865 is_impl_interface_surface.clone(),
866 engines,
867 );
868 }
869 }
870 }
871
872 trait_map
873 }
874
875 fn filter_by_type_inner(
876 &self,
877 engines: &Engines,
878 mut all_types: Vec<TypeId>,
879 decider: impl Fn(TypeId, TypeId) -> bool,
880 ) -> TraitMap {
881 let type_engine = engines.te();
882 let mut trait_map = TraitMap::default();
883 for type_id in all_types.iter_mut() {
884 let type_info = type_engine.get(*type_id);
885 self.for_each_impls(engines, *type_id, true, |entry| {
886 let TraitEntry {
887 key:
888 TraitKey {
889 name: map_trait_name,
890 type_id: map_type_id,
891 trait_decl_span: map_trait_decl_span,
892 impl_type_parameters: map_impl_type_parameters,
893 is_impl_interface_surface: _,
894 },
895 value:
896 TraitValue {
897 trait_items: map_trait_items,
898 impl_span,
899 },
900 } = entry.inner.as_ref();
901
902 if !type_engine.is_type_changeable(engines, &type_info) && *type_id == *map_type_id
903 {
904 trait_map.insert_inner(
905 map_trait_name.clone(),
906 impl_span.clone(),
907 map_trait_decl_span.clone(),
908 *type_id,
909 map_impl_type_parameters.clone(),
910 map_trait_items.clone(),
911 IsImplInterfaceSurface::No,
912 engines,
913 );
914 } else if decider(*type_id, *map_type_id) {
915 trait_map.insert_inner(
916 map_trait_name.clone(),
917 impl_span.clone(),
918 map_trait_decl_span.clone(),
919 *map_type_id,
920 map_impl_type_parameters.clone(),
921 Self::filter_dummy_methods(
922 map_trait_items,
923 *type_id,
924 *map_type_id,
925 engines,
926 )
927 .map(|(name, item)| (name.to_string(), item))
928 .collect(),
929 IsImplInterfaceSurface::No,
930 engines,
931 );
932 }
933 });
934 }
935 trait_map
936 }
937
938 fn filter_dummy_methods<'a>(
939 map_trait_items: &'a TraitItems,
940 type_id: TypeId,
941 map_type_id: TypeId,
942 engines: &'a Engines,
943 ) -> impl Iterator<Item = (&'a str, ResolvedTraitImplItem)> + 'a {
944 let maybe_is_from_type_parameter = engines.te().map(map_type_id, |x| match x {
945 TypeInfo::UnknownGeneric {
946 is_from_type_parameter,
947 ..
948 } => Some(*is_from_type_parameter),
949 _ => None,
950 });
951 let insertable = if let Some(is_from_type_parameter) = maybe_is_from_type_parameter {
952 !is_from_type_parameter
953 || matches!(*engines.te().get(type_id), TypeInfo::UnknownGeneric { .. })
954 } else {
955 true
956 };
957
958 map_trait_items
959 .iter()
960 .filter_map(move |(name, item)| match item {
961 ResolvedTraitImplItem::Parsed(_item) => todo!(),
962 ResolvedTraitImplItem::Typed(item) => match item {
963 ty::TyTraitItem::Fn(decl_ref) => engines.de().map(decl_ref.id(), |decl| {
964 if decl.is_trait_method_dummy && !insertable {
965 None
966 } else {
967 Some((
968 name.as_str(),
969 ResolvedTraitImplItem::Typed(TyImplItem::Fn(decl_ref.clone())),
970 ))
971 }
972 }),
973 ty::TyTraitItem::Constant(decl_ref) => Some((
974 name.as_str(),
975 ResolvedTraitImplItem::Typed(TyImplItem::Constant(decl_ref.clone())),
976 )),
977 ty::TyTraitItem::Type(decl_ref) => Some((
978 name.as_str(),
979 ResolvedTraitImplItem::Typed(TyImplItem::Type(decl_ref.clone())),
980 )),
981 },
982 })
983 }
984
985 fn make_item_for_type_mapping(
986 handler: &Handler,
987 engines: &Engines,
988 item: ResolvedTraitImplItem,
989 mut type_mapping: TypeSubstMap,
990 type_id: TypeId,
991 code_block_first_pass: CodeBlockFirstPass,
992 ) -> ResolvedTraitImplItem {
993 let decl_engine = engines.de();
994 match &item {
995 ResolvedTraitImplItem::Parsed(_item) => todo!(),
996 ResolvedTraitImplItem::Typed(item) => match item {
997 ty::TyTraitItem::Fn(decl_ref) => {
998 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
999 if let Some(decl_implementing_for) = decl.implementing_for {
1000 type_mapping.insert(decl_implementing_for, type_id);
1001 }
1002 decl.subst(&SubstTypesContext::new(
1003 handler,
1004 engines,
1005 &type_mapping,
1006 matches!(code_block_first_pass, CodeBlockFirstPass::No),
1007 ));
1008
1009 let new_ref = decl_engine
1010 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref())
1011 .with_parent(decl_engine, decl_ref.id().into());
1012
1013 ResolvedTraitImplItem::Typed(TyImplItem::Fn(new_ref))
1014 }
1015 ty::TyTraitItem::Constant(decl_ref) => {
1016 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
1017 decl.subst(&SubstTypesContext::new(
1018 handler,
1019 engines,
1020 &type_mapping,
1021 matches!(code_block_first_pass, CodeBlockFirstPass::No),
1022 ));
1023 let new_ref = decl_engine
1024 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref());
1025 ResolvedTraitImplItem::Typed(TyImplItem::Constant(new_ref))
1026 }
1027 ty::TyTraitItem::Type(decl_ref) => {
1028 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
1029 decl.subst(&SubstTypesContext::new(
1030 handler,
1031 engines,
1032 &type_mapping,
1033 matches!(code_block_first_pass, CodeBlockFirstPass::No),
1034 ));
1035 let new_ref = decl_engine
1036 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref());
1037 ResolvedTraitImplItem::Typed(TyImplItem::Type(new_ref))
1038 }
1039 },
1040 }
1041 }
1042
1043 pub(crate) fn append_items_for_type(
1053 module: &Module,
1054 engines: &Engines,
1055 type_id: TypeId,
1056 items: &mut Vec<ResolvedTraitImplItem>,
1057 ) {
1058 TraitMap::find_items_and_trait_key_for_type(module, engines, type_id, &mut |item, _| {
1059 items.push(item);
1060 });
1061 }
1062
1063 pub(crate) fn find_items_and_trait_key_for_type(
1064 module: &Module,
1065 engines: &Engines,
1066 type_id: TypeId,
1067 callback: &mut impl FnMut(ResolvedTraitImplItem, TraitKey),
1068 ) {
1069 let type_engine = engines.te();
1070 let type_id = engines.te().get_unaliased_type_id(type_id);
1071
1072 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1074 return;
1075 }
1076
1077 let unify_check = UnifyCheck::constraint_subset(engines);
1078
1079 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1080 lexical_scope.items.implemented_traits.for_each_impls(
1081 engines,
1082 type_id,
1083 true,
1084 |entry| {
1085 if unify_check.check(type_id, entry.inner.key.type_id) {
1086 let trait_items = Self::filter_dummy_methods(
1087 &entry.inner.value.trait_items,
1088 type_id,
1089 entry.inner.key.type_id,
1090 engines,
1091 )
1092 .map(|(_, i)| (i, entry.inner.key.clone()));
1093
1094 for i in trait_items {
1095 callback(i.0, i.1);
1096 }
1097 }
1098 },
1099 );
1100
1101 Ok(None::<()>)
1102 });
1103 }
1104
1105 pub fn get_impl_spans_for_type(
1115 module: &Module,
1116 engines: &Engines,
1117 type_id: &TypeId,
1118 ) -> Vec<Span> {
1119 let type_engine = engines.te();
1120 let unify_check = UnifyCheck::constraint_subset(engines);
1121
1122 let type_id = &engines.te().get_unaliased_type_id(*type_id);
1123
1124 let mut spans = vec![];
1125 if matches!(&*type_engine.get(*type_id), TypeInfo::ErrorRecovery(_)) {
1127 return spans;
1128 }
1129 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1130 lexical_scope.items.implemented_traits.for_each_impls(
1131 engines,
1132 *type_id,
1133 false,
1134 |entry| {
1135 if unify_check.check(*type_id, entry.inner.key.type_id) {
1136 spans.push(entry.inner.value.impl_span.clone());
1137 }
1138 },
1139 );
1140
1141 Ok(None::<()>)
1142 });
1143
1144 spans
1145 }
1146
1147 pub fn get_impl_spans_for_decl(
1149 module: &Module,
1150 engines: &Engines,
1151 ty_decl: &TyDecl,
1152 ) -> Vec<Span> {
1153 let handler = Handler::default();
1154 ty_decl
1155 .return_type(&handler, engines)
1156 .map(|type_id| TraitMap::get_impl_spans_for_type(module, engines, &type_id))
1157 .unwrap_or_default()
1158 }
1159
1160 pub fn get_impl_spans_for_trait_name(module: &Module, trait_name: &CallPath) -> Vec<Span> {
1163 let mut spans = vec![];
1164 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1165 spans.push(
1166 lexical_scope
1167 .items
1168 .implemented_traits
1169 .trait_impls
1170 .values()
1171 .map(|impls| {
1172 impls
1173 .iter()
1174 .filter_map(|entry| {
1175 let map_trait_name = CallPath {
1176 prefixes: entry.inner.key.name.prefixes.clone(),
1177 suffix: entry.inner.key.name.suffix.name.clone(),
1178 callpath_type: entry.inner.key.name.callpath_type,
1179 };
1180 if &map_trait_name == trait_name {
1181 Some(entry.inner.value.impl_span.clone())
1182 } else {
1183 None
1184 }
1185 })
1186 .collect::<Vec<Span>>()
1187 })
1188 .collect::<Vec<Vec<Span>>>()
1189 .concat(),
1190 );
1191 Ok(None::<()>)
1192 });
1193
1194 spans.concat()
1195 }
1196
1197 pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments(
1208 handler: &Handler,
1209 module: &Module,
1210 engines: &Engines,
1211 type_id: TypeId,
1212 trait_name: &CallPath,
1213 trait_type_args: &[GenericArgument],
1214 ) -> Vec<ResolvedTraitImplItem> {
1215 let type_id = engines.te().get_unaliased_type_id(type_id);
1216
1217 let type_engine = engines.te();
1218 let unify_check = UnifyCheck::constraint_subset(engines);
1219 let mut items = vec![];
1220 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1222 return items;
1223 }
1224 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1225 lexical_scope
1226 .items
1227 .implemented_traits
1228 .for_each_impls(engines, type_id, false, |e| {
1229 let map_trait_name = CallPath {
1230 prefixes: e.inner.key.name.prefixes.clone(),
1231 suffix: e.inner.key.name.suffix.name.clone(),
1232 callpath_type: e.inner.key.name.callpath_type,
1233 };
1234 if &map_trait_name == trait_name
1235 && unify_check.check(type_id, e.inner.key.type_id)
1236 && trait_type_args.len() == e.inner.key.name.suffix.args.len()
1237 && trait_type_args
1238 .iter()
1239 .zip(e.inner.key.name.suffix.args.iter())
1240 .all(|(t1, t2)| unify_check.check(t1.type_id(), t2.type_id()))
1241 {
1242 let type_mapping = TypeSubstMap::from_superset_and_subset(
1243 engines,
1244 e.inner.key.type_id,
1245 type_id,
1246 );
1247
1248 let mut trait_items = Self::filter_dummy_methods(
1249 &e.inner.value.trait_items,
1250 type_id,
1251 e.inner.key.type_id,
1252 engines,
1253 )
1254 .map(|(_, i)| {
1255 Self::make_item_for_type_mapping(
1256 handler,
1257 engines,
1258 i,
1259 type_mapping.clone(),
1260 type_id,
1261 CodeBlockFirstPass::No,
1262 )
1263 })
1264 .collect::<Vec<_>>();
1265
1266 items.append(&mut trait_items);
1267 }
1268 });
1269 Ok(None::<()>)
1270 });
1271 items
1272 }
1273
1274 pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments_typed(
1285 handler: &Handler,
1286 module: &Module,
1287 engines: &Engines,
1288 type_id: TypeId,
1289 trait_name: &CallPath,
1290 trait_type_args: &[GenericArgument],
1291 ) -> Vec<ty::TyTraitItem> {
1292 TraitMap::get_items_for_type_and_trait_name_and_trait_type_arguments(
1293 handler,
1294 module,
1295 engines,
1296 type_id,
1297 trait_name,
1298 trait_type_args,
1299 )
1300 .into_iter()
1301 .map(|item| item.expect_typed())
1302 .collect::<Vec<_>>()
1303 }
1304
1305 pub(crate) fn get_trait_names_and_type_arguments_for_type(
1306 module: &Module,
1307 engines: &Engines,
1308 type_id: TypeId,
1309 ) -> Vec<(CallPath, Vec<GenericArgument>)> {
1310 let type_id = engines.te().get_unaliased_type_id(type_id);
1311
1312 let type_engine = engines.te();
1313 let unify_check = UnifyCheck::constraint_subset(engines);
1314 let mut trait_names = vec![];
1315 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1317 return trait_names;
1318 }
1319 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1320 lexical_scope.items.implemented_traits.for_each_impls(
1321 engines,
1322 type_id,
1323 false,
1324 |entry| {
1325 if unify_check.check(type_id, entry.inner.key.type_id) {
1326 let trait_call_path = CallPath {
1327 prefixes: entry.inner.key.name.prefixes.clone(),
1328 suffix: entry.inner.key.name.suffix.name.clone(),
1329 callpath_type: entry.inner.key.name.callpath_type,
1330 };
1331 trait_names
1332 .push((trait_call_path, entry.inner.key.name.suffix.args.clone()));
1333 }
1334 },
1335 );
1336 Ok(None::<()>)
1337 });
1338 trait_names
1339 }
1340
1341 pub(crate) fn type_implements_trait<F: Fn(&SharedTraitEntry) -> bool>(
1344 module: &Module,
1345 engines: &Engines,
1346 type_id: TypeId,
1347 predicate: F,
1348 ) -> bool {
1349 let type_id = engines.te().get_unaliased_type_id(type_id);
1350
1351 if matches!(&*engines.te().get(type_id), TypeInfo::ErrorRecovery(_)) {
1353 return false;
1354 }
1355
1356 let unify_check = UnifyCheck::constraint_subset(engines);
1357 let mut implements_trait = false;
1358 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1359 lexical_scope.items.implemented_traits.for_each_impls(
1360 engines,
1361 type_id,
1362 false,
1363 |entry| {
1364 if !implements_trait
1367 && unify_check.check(type_id, entry.inner.key.type_id)
1368 && predicate(entry)
1369 {
1370 implements_trait = true;
1371 }
1372 },
1373 );
1374 Ok(None::<()>)
1375 });
1376 implements_trait
1377 }
1378
1379 pub(crate) fn get_trait_item_for_type(
1380 module: &Module,
1381 handler: &Handler,
1382 engines: &Engines,
1383 symbol: &Ident,
1384 type_id: TypeId,
1385 as_trait: Option<CallPath>,
1386 ) -> Result<ResolvedTraitImplItem, ErrorEmitted> {
1387 let type_id = engines.te().get_unaliased_type_id(type_id);
1388
1389 let mut candidates = HashMap::<String, ResolvedTraitImplItem>::new();
1390
1391 TraitMap::find_items_and_trait_key_for_type(
1392 module,
1393 engines,
1394 type_id,
1395 &mut |trait_item, trait_key| match trait_item {
1396 ResolvedTraitImplItem::Parsed(impl_item) => match impl_item {
1397 ImplItem::Fn(fn_ref) => {
1398 let decl = engines.pe().get_function(&fn_ref);
1399 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1400 if decl.name.as_str() == symbol.as_str()
1401 && (as_trait.is_none()
1402 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1403 {
1404 candidates.insert(
1405 trait_call_path_string,
1406 ResolvedTraitImplItem::Parsed(ImplItem::Fn(fn_ref)),
1407 );
1408 }
1409 }
1410 ImplItem::Constant(const_ref) => {
1411 let decl = engines.pe().get_constant(&const_ref);
1412 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1413 if decl.name.as_str() == symbol.as_str()
1414 && (as_trait.is_none()
1415 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1416 {
1417 candidates.insert(
1418 trait_call_path_string,
1419 ResolvedTraitImplItem::Parsed(ImplItem::Constant(const_ref)),
1420 );
1421 }
1422 }
1423 ImplItem::Type(type_ref) => {
1424 let decl = engines.pe().get_trait_type(&type_ref);
1425 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1426 if decl.name.as_str() == symbol.as_str()
1427 && (as_trait.is_none()
1428 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1429 {
1430 candidates.insert(
1431 trait_call_path_string,
1432 ResolvedTraitImplItem::Parsed(ImplItem::Type(type_ref)),
1433 );
1434 }
1435 }
1436 },
1437 ResolvedTraitImplItem::Typed(ty_impl_item) => match ty_impl_item {
1438 ty::TyTraitItem::Fn(fn_ref) => {
1439 let decl = engines.de().get_function(&fn_ref);
1440 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1441 if decl.name.as_str() == symbol.as_str()
1442 && (as_trait.is_none()
1443 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1444 {
1445 candidates.insert(
1446 trait_call_path_string,
1447 ResolvedTraitImplItem::Typed(TyTraitItem::Fn(fn_ref)),
1448 );
1449 }
1450 }
1451 ty::TyTraitItem::Constant(const_ref) => {
1452 let decl = engines.de().get_constant(&const_ref);
1453 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1454 if decl.call_path.suffix.as_str() == symbol.as_str()
1455 && (as_trait.is_none()
1456 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1457 {
1458 candidates.insert(
1459 trait_call_path_string,
1460 ResolvedTraitImplItem::Typed(TyTraitItem::Constant(const_ref)),
1461 );
1462 }
1463 }
1464 ty::TyTraitItem::Type(type_ref) => {
1465 let decl = engines.de().get_type(&type_ref);
1466 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1467 if decl.name.as_str() == symbol.as_str()
1468 && (as_trait.is_none()
1469 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1470 {
1471 candidates.insert(
1472 trait_call_path_string,
1473 ResolvedTraitImplItem::Typed(TyTraitItem::Type(type_ref)),
1474 );
1475 }
1476 }
1477 },
1478 },
1479 );
1480
1481 match candidates.len().cmp(&1) {
1482 Ordering::Greater => Err(handler.emit_err(
1483 CompileError::MultipleApplicableItemsInScope {
1484 item_name: symbol.as_str().to_string(),
1485 item_kind: "item".to_string(),
1486 as_traits: candidates
1487 .keys()
1488 .map(|k| {
1489 (
1490 k.clone()
1491 .split("::")
1492 .collect::<Vec<_>>()
1493 .last()
1494 .unwrap()
1495 .to_string(),
1496 engines.help_out(type_id).to_string(),
1497 )
1498 })
1499 .collect::<Vec<_>>(),
1500 span: symbol.span(),
1501 },
1502 )),
1503 Ordering::Less => Err(handler.emit_err(CompileError::SymbolNotFound {
1504 name: symbol.clone(),
1505 span: symbol.span(),
1506 })),
1507 Ordering::Equal => Ok(candidates.values().next().unwrap().clone()),
1508 }
1509 }
1510
1511 #[allow(clippy::too_many_arguments)]
1513 pub(crate) fn check_if_trait_constraints_are_satisfied_for_type(
1514 handler: &Handler,
1515 module: &mut Module,
1516 type_id: TypeId,
1517 constraints: &[TraitConstraint],
1518 access_span: &Span,
1519 engines: &Engines,
1520 ) -> Result<(), ErrorEmitted> {
1521 let type_engine = engines.te();
1522
1523 let type_id = type_engine.get_unaliased_type_id(type_id);
1524
1525 type_engine.decay_numeric(handler, engines, type_id, access_span)?;
1527
1528 if constraints.is_empty() {
1529 return Ok(());
1530 }
1531
1532 let mut hasher = DefaultHasher::default();
1534 type_id.hash(&mut hasher);
1535 for c in constraints {
1536 c.hash(&mut hasher, engines);
1537 }
1538 let hash = hasher.finish();
1539
1540 {
1541 let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1542 if trait_map.satisfied_cache.contains(&hash) {
1543 return Ok(());
1544 }
1545 }
1546
1547 let all_impld_traits: BTreeSet<(Ident, TypeId)> =
1548 Self::get_all_implemented_traits(module, type_id, engines);
1549
1550 match Self::check_if_trait_constraints_are_satisfied_for_type_inner(
1552 handler,
1553 type_id,
1554 constraints,
1555 access_span,
1556 engines,
1557 all_impld_traits,
1558 ) {
1559 Ok(()) => {
1560 let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1561 trait_map.satisfied_cache.insert(hash);
1562 Ok(())
1563 }
1564 r => r,
1565 }
1566 }
1567
1568 fn get_all_implemented_traits(
1569 module: &Module,
1570 type_id: TypeId,
1571 engines: &Engines,
1572 ) -> BTreeSet<(Ident, TypeId)> {
1573 let mut all_impld_traits: BTreeSet<(Ident, TypeId)> = Default::default();
1574 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1575 all_impld_traits.extend(
1576 lexical_scope
1577 .items
1578 .implemented_traits
1579 .get_implemented_traits(type_id, engines),
1580 );
1581 Ok(None::<()>)
1582 });
1583 all_impld_traits
1584 }
1585
1586 fn get_implemented_traits(
1587 &self,
1588 type_id: TypeId,
1589 engines: &Engines,
1590 ) -> BTreeSet<(Ident, TypeId)> {
1591 let type_engine = engines.te();
1592 let unify_check = UnifyCheck::constraint_subset(engines);
1593 let mut all_impld_traits = BTreeSet::<(Ident, TypeId)>::new();
1594 self.for_each_impls(engines, type_id, true, |e| {
1595 let key = &e.inner.key;
1596 let suffix = &key.name.suffix;
1597 if unify_check.check(type_id, key.type_id) {
1598 let map_trait_type_id = type_engine.new_custom(
1599 engines,
1600 suffix.name.clone().into(),
1601 if suffix.args.is_empty() {
1602 None
1603 } else {
1604 Some(suffix.args.to_vec())
1605 },
1606 );
1607 all_impld_traits.insert((suffix.name.clone(), map_trait_type_id));
1608 }
1609 });
1610 all_impld_traits
1611 }
1612
1613 #[allow(clippy::too_many_arguments)]
1614 fn check_if_trait_constraints_are_satisfied_for_type_inner(
1615 handler: &Handler,
1616 type_id: TypeId,
1617 constraints: &[TraitConstraint],
1618 access_span: &Span,
1619 engines: &Engines,
1620 all_impld_traits: BTreeSet<(Ident, TypeId)>,
1621 ) -> Result<(), ErrorEmitted> {
1622 let type_engine = engines.te();
1623 let unify_check = UnifyCheck::constraint_subset(engines);
1624
1625 let required_traits: BTreeSet<(Ident, TypeId)> = constraints
1626 .iter()
1627 .map(|c| {
1628 let TraitConstraint {
1629 trait_name: constraint_trait_name,
1630 type_arguments: constraint_type_arguments,
1631 } = c;
1632 let constraint_type_id = type_engine.new_custom(
1633 engines,
1634 constraint_trait_name.suffix.clone().into(),
1635 if constraint_type_arguments.is_empty() {
1636 None
1637 } else {
1638 Some(constraint_type_arguments.clone())
1639 },
1640 );
1641 (c.trait_name.suffix.clone(), constraint_type_id)
1642 })
1643 .collect();
1644
1645 let traits_not_found: BTreeSet<(BaseIdent, TypeId)> = required_traits
1646 .into_iter()
1647 .filter(|(required_trait_name, required_trait_type_id)| {
1648 !all_impld_traits
1649 .iter()
1650 .any(|(trait_name, constraint_type_id)| {
1651 trait_name == required_trait_name
1652 && unify_check.check(*constraint_type_id, *required_trait_type_id)
1653 })
1654 })
1655 .collect();
1656
1657 handler.scope(|handler| {
1658 for (trait_name, constraint_type_id) in traits_not_found.iter() {
1659 let mut type_arguments_string = "".to_string();
1660 if let TypeInfo::Custom {
1661 qualified_call_path: _,
1662 type_arguments: Some(type_arguments),
1663 } = &*type_engine.get(*constraint_type_id)
1664 {
1665 type_arguments_string = format!("<{}>", engines.help_out(type_arguments));
1666 }
1667
1668 handler.emit_err(CompileError::TraitConstraintNotSatisfied {
1670 type_id: type_id.index(),
1671 ty: engines.help_out(type_id).to_string(),
1672 trait_name: format!("{trait_name}{type_arguments_string}"),
1673 span: access_span.clone(),
1674 });
1675 }
1676
1677 Ok(())
1678 })
1679 }
1680
1681 pub fn get_trait_constraints_are_satisfied_for_types(
1682 module: &Module,
1683 _handler: &Handler,
1684 type_id: TypeId,
1685 constraints: &[TraitConstraint],
1686 engines: &Engines,
1687 ) -> Result<Vec<(TypeId, String)>, ErrorEmitted> {
1688 let type_id = engines.te().get_unaliased_type_id(type_id);
1689
1690 let _decl_engine = engines.de();
1691 let unify_check = UnifyCheck::coercion(engines);
1692 let unify_check_equality = UnifyCheck::constraint_subset(engines);
1693
1694 let mut impld_traits_type_ids: Vec<Vec<(TypeId, String)>> = vec![];
1695 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1696 lexical_scope
1697 .items
1698 .implemented_traits
1699 .for_each_impls(engines, type_id, true, |e| {
1700 let mut traits: Vec<(TypeId, String)> = vec![];
1701
1702 let key = &e.inner.key;
1703 for constraint in constraints {
1704 if key.name.suffix.name == constraint.trait_name.suffix
1705 && key
1706 .name
1707 .suffix
1708 .args
1709 .iter()
1710 .zip(constraint.type_arguments.iter())
1711 .all(|(a1, a2)| {
1712 unify_check_equality.check(a1.type_id(), a2.type_id())
1713 })
1714 && unify_check.check(type_id, key.type_id)
1715 {
1716 let name_type_args = if !key.name.suffix.args.is_empty() {
1717 format!("<{}>", engines.help_out(key.name.suffix.args.clone()))
1718 } else {
1719 "".to_string()
1720 };
1721 let name =
1722 format!("{}{}", key.name.suffix.name.as_str(), name_type_args);
1723 traits.push((key.type_id, name));
1724 break;
1725 }
1726 }
1727 impld_traits_type_ids.push(traits);
1728 });
1729
1730 Ok(None::<()>)
1731 });
1732 Ok(impld_traits_type_ids.concat())
1733 }
1734
1735 fn get_impls_mut(&mut self, engines: &Engines, type_id: TypeId) -> &mut Vec<SharedTraitEntry> {
1736 let type_root_filter = Self::get_type_root_filter(engines, type_id);
1737 if !self.trait_impls.contains_key(&type_root_filter) {
1738 self.trait_impls
1739 .insert(type_root_filter.clone(), Vec::new());
1740 }
1741
1742 self.trait_impls.get_mut(&type_root_filter).unwrap()
1743 }
1744
1745 pub(crate) fn for_each_impls<F>(
1746 &self,
1747 engines: &Engines,
1748 type_id: TypeId,
1749 include_placeholder: bool,
1750 mut callback: F,
1751 ) where
1752 F: FnMut(&SharedTraitEntry),
1753 {
1754 let type_root_filter = Self::get_type_root_filter(engines, type_id);
1755 self.trait_impls
1756 .get(&type_root_filter)
1757 .iter()
1758 .for_each(|vec| vec.iter().for_each(&mut callback));
1759 if include_placeholder && type_root_filter != TypeRootFilter::Placeholder {
1760 self.trait_impls
1761 .get(&TypeRootFilter::Placeholder)
1762 .iter()
1763 .for_each(|vec| vec.iter().for_each(&mut callback));
1764 }
1765 }
1766
1767 fn get_type_root_filter(engines: &Engines, type_id: TypeId) -> TypeRootFilter {
1770 use TypeInfo::*;
1771 match &*engines.te().get(type_id) {
1772 Unknown => TypeRootFilter::Unknown,
1773 Never => TypeRootFilter::Never,
1774 UnknownGeneric { .. } | Placeholder(_) => TypeRootFilter::Placeholder,
1775 TypeParam(_param) => unreachable!(),
1776 StringSlice => TypeRootFilter::StringSlice,
1777 StringArray(_) => TypeRootFilter::StringArray,
1778 UnsignedInteger(x) => match x {
1779 IntegerBits::Eight => TypeRootFilter::U8,
1780 IntegerBits::Sixteen => TypeRootFilter::U16,
1781 IntegerBits::ThirtyTwo => TypeRootFilter::U32,
1782 IntegerBits::SixtyFour => TypeRootFilter::U64,
1783 IntegerBits::V256 => TypeRootFilter::U256,
1784 },
1785 Boolean => TypeRootFilter::Bool,
1786 Custom {
1787 qualified_call_path: call_path,
1788 ..
1789 } => TypeRootFilter::Custom(call_path.call_path.suffix.to_string()),
1790 B256 => TypeRootFilter::B256,
1791 Numeric => TypeRootFilter::U64, Contract => TypeRootFilter::Contract,
1793 ErrorRecovery(_) => TypeRootFilter::ErrorRecovery,
1794 Tuple(fields) => TypeRootFilter::Tuple(fields.len()),
1795 UntypedEnum(decl_id) => TypeRootFilter::Enum(*decl_id),
1796 UntypedStruct(decl_id) => TypeRootFilter::Struct(*decl_id),
1797 Enum(decl_id) => {
1798 TypeRootFilter::Enum(engines.de().get_parsed_decl_id(decl_id).unwrap())
1800 }
1801 Struct(decl_id) => {
1802 TypeRootFilter::Struct(engines.de().get_parsed_decl_id(decl_id).unwrap())
1804 }
1805 ContractCaller { abi_name, .. } => TypeRootFilter::ContractCaller(abi_name.to_string()),
1806 Array(_, _) => TypeRootFilter::Array,
1807 RawUntypedPtr => TypeRootFilter::RawUntypedPtr,
1808 RawUntypedSlice => TypeRootFilter::RawUntypedSlice,
1809 Ptr(_) => TypeRootFilter::Ptr,
1810 Slice(_) => TypeRootFilter::Slice,
1811 Alias { ty, .. } => Self::get_type_root_filter(engines, ty.type_id),
1812 TraitType { name, .. } => TypeRootFilter::TraitType(name.to_string()),
1813 Ref {
1814 referenced_type, ..
1815 } => Self::get_type_root_filter(engines, referenced_type.type_id),
1816 }
1817 }
1818}