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().into(),
390 });
391 }
392 }
393 TyImplItem::Constant(decl_ref) => {
394 trait_items.insert(decl_ref.name().to_string(), item.clone());
395 }
396 TyImplItem::Type(decl_ref) => {
397 trait_items.insert(decl_ref.name().to_string(), item.clone());
398 }
399 },
400 }
401 }
402
403 let trait_impls = self.get_impls_mut(engines, unaliased_type_id);
404
405 for entry in trait_impls.iter() {
407 let TraitEntry {
408 key:
409 TraitKey {
410 name: map_trait_name,
411 type_id: map_type_id,
412 trait_decl_span: _,
413 impl_type_parameters: _,
414 is_impl_interface_surface: map_is_impl_interface_surface,
415 },
416 value:
417 TraitValue {
418 trait_items: map_trait_items,
419 impl_span: existing_impl_span,
420 },
421 } = entry.inner.as_ref();
422 let CallPath {
423 suffix:
424 TraitSuffix {
425 name: map_trait_name_suffix,
426 args: map_trait_type_args,
427 },
428 ..
429 } = &*map_trait_name.clone();
430
431 let unify_checker = UnifyCheck::non_generic_constraint_subset(engines);
432
433 let types_are_subset = unify_checker.check(unaliased_type_id, *map_type_id)
437 && is_unified_type_subset(engines.te(), unaliased_type_id, *map_type_id);
438
439 fn is_unified_type_subset(
445 type_engine: &TypeEngine,
446 mut left: TypeId,
447 mut right: TypeId,
448 ) -> bool {
449 loop {
452 let left_ty_info = &*type_engine.get_unaliased(left);
453 let right_ty_info = &*type_engine.get_unaliased(right);
454 match (left_ty_info, right_ty_info) {
455 (
456 TypeInfo::Ref {
457 to_mutable_value: l_to_mut,
458 ..
459 },
460 TypeInfo::Ref {
461 to_mutable_value: r_to_mut,
462 ..
463 },
464 ) if *l_to_mut != *r_to_mut => return false, (
466 TypeInfo::Ref {
467 referenced_type: l_ty,
468 ..
469 },
470 TypeInfo::Ref {
471 referenced_type: r_ty,
472 ..
473 },
474 ) => {
475 left = l_ty.type_id;
476 right = r_ty.type_id;
477 }
478 _ => return true,
479 }
480 }
481 }
482
483 let mut traits_are_subset = true;
484 if *map_trait_name_suffix != trait_name.suffix
485 || map_trait_type_args.len() != trait_type_args.len()
486 {
487 traits_are_subset = false;
488 } else {
489 for (map_arg_type, arg_type) in
490 map_trait_type_args.iter().zip(trait_type_args.iter())
491 {
492 if !unify_checker.check(arg_type.type_id(), map_arg_type.type_id()) {
493 traits_are_subset = false;
494 }
495 }
496 }
497
498 let should_check = matches!(is_impl_interface_surface, IsImplInterfaceSurface::No);
499 if should_check {
500 if matches!(is_extending_existing_impl, IsExtendingExistingImpl::No)
501 && types_are_subset
502 && traits_are_subset
503 && matches!(is_impl_self, IsImplSelf::No)
504 && matches!(map_is_impl_interface_surface, IsImplInterfaceSurface::No)
505 {
506 handler.emit_err(CompileError::ConflictingImplsForTraitAndType {
507 trait_name: trait_name.to_string_with_args(engines, &trait_type_args),
508 type_implementing_for: engines.help_out(type_id).to_string(),
509 type_implementing_for_unaliased: engines
510 .help_out(unaliased_type_id)
511 .to_string(),
512 existing_impl_span: existing_impl_span.clone(),
513 second_impl_span: impl_span.clone(),
514 });
515 } else if types_are_subset
516 && (traits_are_subset || matches!(is_impl_self, IsImplSelf::Yes))
517 && matches!(map_is_impl_interface_surface, IsImplInterfaceSurface::No)
518 {
519 for name in trait_items.keys() {
520 let item = &trait_items[name];
521 match item {
522 ResolvedTraitImplItem::Parsed(_item) => todo!(),
523 ResolvedTraitImplItem::Typed(item) => match item {
524 ty::TyTraitItem::Fn(decl_ref) => {
525 if let Some(existing_item) = map_trait_items.get(name) {
526 handler.emit_err(
527 CompileError::DuplicateDeclDefinedForType {
528 decl_kind: "method".into(),
529 decl_name: decl_ref.name().to_string(),
530 type_implementing_for: engines
531 .help_out(type_id)
532 .to_string(),
533 type_implementing_for_unaliased: engines
534 .help_out(unaliased_type_id)
535 .to_string(),
536 existing_impl_span: existing_item
537 .span(engines)
538 .clone(),
539 second_impl_span: decl_ref.name().span(),
540 },
541 );
542 }
543 }
544 ty::TyTraitItem::Constant(decl_ref) => {
545 if let Some(existing_item) = map_trait_items.get(name) {
546 handler.emit_err(
547 CompileError::DuplicateDeclDefinedForType {
548 decl_kind: "constant".into(),
549 decl_name: decl_ref.name().to_string(),
550 type_implementing_for: engines
551 .help_out(type_id)
552 .to_string(),
553 type_implementing_for_unaliased: engines
554 .help_out(unaliased_type_id)
555 .to_string(),
556 existing_impl_span: existing_item
557 .span(engines)
558 .clone(),
559 second_impl_span: decl_ref.name().span(),
560 },
561 );
562 }
563 }
564 ty::TyTraitItem::Type(decl_ref) => {
565 if let Some(existing_item) = map_trait_items.get(name) {
566 handler.emit_err(
567 CompileError::DuplicateDeclDefinedForType {
568 decl_kind: "type".into(),
569 decl_name: decl_ref.name().to_string(),
570 type_implementing_for: engines
571 .help_out(type_id)
572 .to_string(),
573 type_implementing_for_unaliased: engines
574 .help_out(unaliased_type_id)
575 .to_string(),
576 existing_impl_span: existing_item
577 .span(engines)
578 .clone(),
579 second_impl_span: decl_ref.name().span(),
580 },
581 );
582 }
583 }
584 },
585 }
586 }
587 }
588 }
589 }
590 let trait_name: TraitName = Arc::new(CallPath {
591 prefixes: trait_name.prefixes,
592 suffix: TraitSuffix {
593 name: trait_name.suffix,
594 args: trait_type_args,
595 },
596 callpath_type: trait_name.callpath_type,
597 });
598
599 self.insert_inner(
601 trait_name,
602 impl_span.clone(),
603 trait_decl_span,
604 unaliased_type_id,
605 impl_type_parameters,
606 trait_items,
607 is_impl_interface_surface,
608 engines,
609 );
610
611 Ok(())
612 })
613 }
614
615 #[allow(clippy::too_many_arguments)]
616 fn insert_inner(
617 &mut self,
618 trait_name: TraitName,
619 impl_span: Span,
620 trait_decl_span: Option<Span>,
621 type_id: TypeId,
622 impl_type_parameters: Vec<TypeId>,
623 trait_methods: TraitItems,
624 is_impl_interface_surface: IsImplInterfaceSurface,
625 engines: &Engines,
626 ) {
627 let key = TraitKey {
628 name: trait_name,
629 type_id,
630 trait_decl_span,
631 impl_type_parameters,
632 is_impl_interface_surface,
633 };
634 let value = TraitValue {
635 trait_items: trait_methods,
636 impl_span,
637 };
638 let mut trait_impls: TraitImpls = BTreeMap::new();
639 let type_root_filter = Self::get_type_root_filter(engines, type_id);
640 let entry = TraitEntry { key, value };
641 let impls_vector = vec![SharedTraitEntry {
642 inner: Arc::new(entry),
643 }];
644 trait_impls.insert(type_root_filter, impls_vector);
645
646 let trait_map = TraitMap {
647 trait_impls,
648 satisfied_cache: HashSet::default(),
649 };
650
651 self.extend(trait_map, engines);
652 }
653
654 pub(crate) fn extend(&mut self, other: TraitMap, engines: &Engines) {
657 for impls_key in other.trait_impls.keys() {
658 let oe_vec = &other.trait_impls[impls_key];
659 let self_vec = if let Some(self_vec) = self.trait_impls.get_mut(impls_key) {
660 self_vec
661 } else {
662 self.trait_impls.insert(impls_key.clone(), Vec::<_>::new());
663 self.trait_impls.get_mut(impls_key).unwrap()
664 };
665
666 for oe in oe_vec.iter() {
667 let pos = self_vec.binary_search_by(|se| {
668 se.inner
669 .key
670 .cmp(&oe.inner.key, &OrdWithEnginesContext::new(engines))
671 });
672
673 match pos {
674 Ok(pos) => self_vec[pos]
675 .fork_if_non_unique()
676 .get_mut()
677 .value
678 .trait_items
679 .extend(oe.inner.value.trait_items.clone()),
680 Err(pos) => self_vec.insert(pos, oe.clone()),
681 }
682 }
683 }
684 }
685
686 pub(crate) fn get_traits_types(
687 &self,
688 traits_types: &mut HashMap<CallPath, HashSet<TypeId>>,
689 ) -> Result<(), ErrorEmitted> {
690 for key in self.trait_impls.keys() {
691 for self_entry in self.trait_impls[key].iter() {
692 let callpath = CallPath {
693 prefixes: self_entry.inner.key.name.prefixes.clone(),
694 suffix: self_entry.inner.key.name.suffix.name.clone(),
695 callpath_type: self_entry.inner.key.name.callpath_type,
696 };
697 if let Some(set) = traits_types.get_mut(&callpath) {
698 set.insert(self_entry.inner.key.type_id);
699 } else {
700 traits_types.insert(
701 callpath,
702 vec![self_entry.inner.key.type_id].into_iter().collect(),
703 );
704 }
705 }
706 }
707 Ok(())
708 }
709
710 pub(crate) fn filter_by_trait_decl_span(&self, trait_decl_span: Span) -> TraitMap {
713 let mut trait_map = TraitMap::default();
714 for key in self.trait_impls.keys() {
715 let vec = &self.trait_impls[key];
716 for entry in vec {
717 if entry.inner.key.trait_decl_span.as_ref() == Some(&trait_decl_span) {
718 let trait_map_vec =
719 if let Some(trait_map_vec) = trait_map.trait_impls.get_mut(key) {
720 trait_map_vec
721 } else {
722 trait_map.trait_impls.insert(key.clone(), Vec::<_>::new());
723 trait_map.trait_impls.get_mut(key).unwrap()
724 };
725
726 trait_map_vec.push(entry.clone());
727 }
728 }
729 }
730 trait_map
731 }
732
733 pub(crate) fn filter_by_type_item_import(
792 &self,
793 type_id: TypeId,
794 engines: &Engines,
795 ) -> TraitMap {
796 let unify_checker = UnifyCheck::constraint_subset(engines);
797 let unify_checker_for_item_import = UnifyCheck::non_generic_constraint_subset(engines);
798
799 let decider = |left: TypeId, right: TypeId| {
801 unify_checker.check(left, right) || unify_checker_for_item_import.check(right, left)
802 };
803 let mut trait_map = self.filter_by_type_inner(engines, vec![type_id], decider);
804 let all_types = type_id
805 .extract_inner_types(engines, IncludeSelf::No)
806 .into_iter()
807 .collect::<Vec<_>>();
808 let decider2 = |left: TypeId, right: TypeId| unify_checker.check(left, right);
810
811 trait_map.extend(
812 self.filter_by_type_inner(engines, all_types, decider2),
813 engines,
814 );
815
816 for key in self.trait_impls.keys() {
818 for entry in self.trait_impls[key].iter() {
819 let TraitEntry {
820 key:
821 TraitKey {
822 name: trait_name,
823 type_id: trait_type_id,
824 trait_decl_span,
825 impl_type_parameters,
826 is_impl_interface_surface,
827 },
828 value:
829 TraitValue {
830 trait_items,
831 impl_span,
832 },
833 } = entry.inner.as_ref();
834
835 let decider3 =
836 |left: TypeId, right: TypeId| unify_checker_for_item_import.check(right, left);
837
838 let matches_generic_params = match *engines.te().get(*trait_type_id) {
839 TypeInfo::Enum(decl_id) => engines
840 .de()
841 .get(&decl_id)
842 .generic_parameters
843 .iter()
844 .any(|gp| gp.unifies(type_id, decider3)),
845 TypeInfo::Struct(decl_id) => engines
846 .de()
847 .get(&decl_id)
848 .generic_parameters
849 .iter()
850 .any(|gp| gp.unifies(type_id, decider3)),
851 _ => false,
852 };
853
854 if matches_generic_params
855 || impl_type_parameters.iter().any(|tp| decider(type_id, *tp))
856 {
857 trait_map.insert_inner(
858 trait_name.clone(),
859 impl_span.clone(),
860 trait_decl_span.clone(),
861 *trait_type_id,
862 impl_type_parameters.clone(),
863 trait_items.clone(),
864 is_impl_interface_surface.clone(),
865 engines,
866 );
867 }
868 }
869 }
870
871 trait_map
872 }
873
874 fn filter_by_type_inner(
875 &self,
876 engines: &Engines,
877 mut all_types: Vec<TypeId>,
878 decider: impl Fn(TypeId, TypeId) -> bool,
879 ) -> TraitMap {
880 let type_engine = engines.te();
881 let mut trait_map = TraitMap::default();
882 for type_id in all_types.iter_mut() {
883 let type_info = type_engine.get(*type_id);
884 self.for_each_impls(engines, *type_id, true, |entry| {
885 let TraitEntry {
886 key:
887 TraitKey {
888 name: map_trait_name,
889 type_id: map_type_id,
890 trait_decl_span: map_trait_decl_span,
891 impl_type_parameters: map_impl_type_parameters,
892 is_impl_interface_surface: _,
893 },
894 value:
895 TraitValue {
896 trait_items: map_trait_items,
897 impl_span,
898 },
899 } = entry.inner.as_ref();
900
901 if !type_engine.is_type_changeable(engines, &type_info) && *type_id == *map_type_id
902 {
903 trait_map.insert_inner(
904 map_trait_name.clone(),
905 impl_span.clone(),
906 map_trait_decl_span.clone(),
907 *type_id,
908 map_impl_type_parameters.clone(),
909 map_trait_items.clone(),
910 IsImplInterfaceSurface::No,
911 engines,
912 );
913 } else if decider(*type_id, *map_type_id) {
914 trait_map.insert_inner(
915 map_trait_name.clone(),
916 impl_span.clone(),
917 map_trait_decl_span.clone(),
918 *map_type_id,
919 map_impl_type_parameters.clone(),
920 Self::filter_dummy_methods(
921 map_trait_items,
922 *type_id,
923 *map_type_id,
924 engines,
925 )
926 .map(|(name, item)| (name.to_string(), item))
927 .collect(),
928 IsImplInterfaceSurface::No,
929 engines,
930 );
931 }
932 });
933 }
934 trait_map
935 }
936
937 fn filter_dummy_methods<'a>(
938 map_trait_items: &'a TraitItems,
939 type_id: TypeId,
940 map_type_id: TypeId,
941 engines: &'a Engines,
942 ) -> impl Iterator<Item = (&'a str, ResolvedTraitImplItem)> + 'a {
943 let maybe_is_from_type_parameter = engines.te().map(map_type_id, |x| match x {
944 TypeInfo::UnknownGeneric {
945 is_from_type_parameter,
946 ..
947 } => Some(*is_from_type_parameter),
948 _ => None,
949 });
950 let insertable = if let Some(is_from_type_parameter) = maybe_is_from_type_parameter {
951 !is_from_type_parameter
952 || matches!(*engines.te().get(type_id), TypeInfo::UnknownGeneric { .. })
953 } else {
954 true
955 };
956
957 map_trait_items
958 .iter()
959 .filter_map(move |(name, item)| match item {
960 ResolvedTraitImplItem::Parsed(_item) => todo!(),
961 ResolvedTraitImplItem::Typed(item) => match item {
962 ty::TyTraitItem::Fn(decl_ref) => engines.de().map(decl_ref.id(), |decl| {
963 if decl.is_trait_method_dummy && !insertable {
964 None
965 } else {
966 Some((
967 name.as_str(),
968 ResolvedTraitImplItem::Typed(TyImplItem::Fn(decl_ref.clone())),
969 ))
970 }
971 }),
972 ty::TyTraitItem::Constant(decl_ref) => Some((
973 name.as_str(),
974 ResolvedTraitImplItem::Typed(TyImplItem::Constant(decl_ref.clone())),
975 )),
976 ty::TyTraitItem::Type(decl_ref) => Some((
977 name.as_str(),
978 ResolvedTraitImplItem::Typed(TyImplItem::Type(decl_ref.clone())),
979 )),
980 },
981 })
982 }
983
984 fn make_item_for_type_mapping(
985 handler: &Handler,
986 engines: &Engines,
987 item: ResolvedTraitImplItem,
988 mut type_mapping: TypeSubstMap,
989 type_id: TypeId,
990 code_block_first_pass: CodeBlockFirstPass,
991 ) -> ResolvedTraitImplItem {
992 let decl_engine = engines.de();
993 match &item {
994 ResolvedTraitImplItem::Parsed(_item) => todo!(),
995 ResolvedTraitImplItem::Typed(item) => match item {
996 ty::TyTraitItem::Fn(decl_ref) => {
997 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
998 if let Some(decl_implementing_for) = decl.implementing_for {
999 type_mapping.insert(decl_implementing_for, type_id);
1000 }
1001
1002 let new_ref = if decl
1003 .subst(&SubstTypesContext::new(
1004 handler,
1005 engines,
1006 &type_mapping,
1007 matches!(code_block_first_pass, CodeBlockFirstPass::No),
1008 ))
1009 .has_changes()
1010 {
1011 decl_engine
1012 .insert_modified(decl, *decl_ref.id())
1013 .with_parent(decl_engine, decl_ref.id().into())
1014 } else {
1015 decl_ref.clone()
1016 };
1017
1018 ResolvedTraitImplItem::Typed(TyImplItem::Fn(new_ref))
1019 }
1020 ty::TyTraitItem::Constant(decl_ref) => {
1021 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
1022
1023 let new_ref = if decl
1024 .subst(&SubstTypesContext::new(
1025 handler,
1026 engines,
1027 &type_mapping,
1028 matches!(code_block_first_pass, CodeBlockFirstPass::No),
1029 ))
1030 .has_changes()
1031 {
1032 decl_engine.insert_modified(decl, *decl_ref.id())
1033 } else {
1034 decl_ref.clone()
1035 };
1036
1037 ResolvedTraitImplItem::Typed(TyImplItem::Constant(new_ref))
1038 }
1039 ty::TyTraitItem::Type(decl_ref) => {
1040 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
1041
1042 let new_ref = if decl
1043 .subst(&SubstTypesContext::new(
1044 handler,
1045 engines,
1046 &type_mapping,
1047 matches!(code_block_first_pass, CodeBlockFirstPass::No),
1048 ))
1049 .has_changes()
1050 {
1051 decl_engine.insert_modified(decl, *decl_ref.id())
1052 } else {
1053 decl_ref.clone()
1054 };
1055
1056 ResolvedTraitImplItem::Typed(TyImplItem::Type(new_ref))
1057 }
1058 },
1059 }
1060 }
1061
1062 pub(crate) fn append_items_for_type(
1072 module: &Module,
1073 engines: &Engines,
1074 type_id: TypeId,
1075 items: &mut Vec<ResolvedTraitImplItem>,
1076 ) {
1077 TraitMap::find_items_and_trait_key_for_type(module, engines, type_id, &mut |item, _| {
1078 items.push(item);
1079 });
1080 }
1081
1082 pub(crate) fn find_items_and_trait_key_for_type(
1083 module: &Module,
1084 engines: &Engines,
1085 type_id: TypeId,
1086 callback: &mut impl FnMut(ResolvedTraitImplItem, TraitKey),
1087 ) {
1088 let type_engine = engines.te();
1089 let type_id = engines.te().get_unaliased_type_id(type_id);
1090
1091 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1093 return;
1094 }
1095
1096 let unify_check = UnifyCheck::constraint_subset(engines);
1097
1098 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1099 lexical_scope.items.implemented_traits.for_each_impls(
1100 engines,
1101 type_id,
1102 true,
1103 |entry| {
1104 if unify_check.check(type_id, entry.inner.key.type_id) {
1105 let trait_items = Self::filter_dummy_methods(
1106 &entry.inner.value.trait_items,
1107 type_id,
1108 entry.inner.key.type_id,
1109 engines,
1110 )
1111 .map(|(_, i)| (i, entry.inner.key.clone()));
1112
1113 for i in trait_items {
1114 callback(i.0, i.1);
1115 }
1116 }
1117 },
1118 );
1119
1120 Ok(None::<()>)
1121 });
1122 }
1123
1124 pub fn get_impl_spans_for_type(
1134 module: &Module,
1135 engines: &Engines,
1136 type_id: &TypeId,
1137 ) -> Vec<Span> {
1138 let type_engine = engines.te();
1139 let unify_check = UnifyCheck::constraint_subset(engines);
1140
1141 let type_id = &engines.te().get_unaliased_type_id(*type_id);
1142
1143 let mut spans = vec![];
1144 if matches!(&*type_engine.get(*type_id), TypeInfo::ErrorRecovery(_)) {
1146 return spans;
1147 }
1148 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1149 lexical_scope.items.implemented_traits.for_each_impls(
1150 engines,
1151 *type_id,
1152 false,
1153 |entry| {
1154 if unify_check.check(*type_id, entry.inner.key.type_id) {
1155 spans.push(entry.inner.value.impl_span.clone());
1156 }
1157 },
1158 );
1159
1160 Ok(None::<()>)
1161 });
1162
1163 spans
1164 }
1165
1166 pub fn get_impl_spans_for_decl(
1168 module: &Module,
1169 engines: &Engines,
1170 ty_decl: &TyDecl,
1171 ) -> Vec<Span> {
1172 let handler = Handler::default();
1173 ty_decl
1174 .return_type(&handler, engines)
1175 .map(|type_id| TraitMap::get_impl_spans_for_type(module, engines, &type_id))
1176 .unwrap_or_default()
1177 }
1178
1179 pub fn get_impl_spans_for_trait_name(module: &Module, trait_name: &CallPath) -> Vec<Span> {
1182 let mut spans = vec![];
1183 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1184 spans.push(
1185 lexical_scope
1186 .items
1187 .implemented_traits
1188 .trait_impls
1189 .values()
1190 .map(|impls| {
1191 impls
1192 .iter()
1193 .filter_map(|entry| {
1194 let map_trait_name = CallPath {
1195 prefixes: entry.inner.key.name.prefixes.clone(),
1196 suffix: entry.inner.key.name.suffix.name.clone(),
1197 callpath_type: entry.inner.key.name.callpath_type,
1198 };
1199 if &map_trait_name == trait_name {
1200 Some(entry.inner.value.impl_span.clone())
1201 } else {
1202 None
1203 }
1204 })
1205 .collect::<Vec<Span>>()
1206 })
1207 .collect::<Vec<Vec<Span>>>()
1208 .concat(),
1209 );
1210 Ok(None::<()>)
1211 });
1212
1213 spans.concat()
1214 }
1215
1216 pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments(
1227 handler: &Handler,
1228 module: &Module,
1229 engines: &Engines,
1230 type_id: TypeId,
1231 trait_name: &CallPath,
1232 trait_type_args: &[GenericArgument],
1233 ) -> Vec<ResolvedTraitImplItem> {
1234 let type_id = engines.te().get_unaliased_type_id(type_id);
1235
1236 let type_engine = engines.te();
1237 let unify_check = UnifyCheck::constraint_subset(engines);
1238 let mut items = vec![];
1239 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1241 return items;
1242 }
1243 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1244 lexical_scope
1245 .items
1246 .implemented_traits
1247 .for_each_impls(engines, type_id, false, |e| {
1248 let map_trait_name = CallPath {
1249 prefixes: e.inner.key.name.prefixes.clone(),
1250 suffix: e.inner.key.name.suffix.name.clone(),
1251 callpath_type: e.inner.key.name.callpath_type,
1252 };
1253 if &map_trait_name == trait_name
1254 && unify_check.check(type_id, e.inner.key.type_id)
1255 && trait_type_args.len() == e.inner.key.name.suffix.args.len()
1256 && trait_type_args
1257 .iter()
1258 .zip(e.inner.key.name.suffix.args.iter())
1259 .all(|(t1, t2)| unify_check.check(t1.type_id(), t2.type_id()))
1260 {
1261 let type_mapping = TypeSubstMap::from_superset_and_subset(
1262 engines,
1263 e.inner.key.type_id,
1264 type_id,
1265 );
1266
1267 let mut trait_items = Self::filter_dummy_methods(
1268 &e.inner.value.trait_items,
1269 type_id,
1270 e.inner.key.type_id,
1271 engines,
1272 )
1273 .map(|(_, i)| {
1274 Self::make_item_for_type_mapping(
1275 handler,
1276 engines,
1277 i,
1278 type_mapping.clone(),
1279 type_id,
1280 CodeBlockFirstPass::No,
1281 )
1282 })
1283 .collect::<Vec<_>>();
1284
1285 items.append(&mut trait_items);
1286 }
1287 });
1288 Ok(None::<()>)
1289 });
1290 items
1291 }
1292
1293 pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments_typed(
1304 handler: &Handler,
1305 module: &Module,
1306 engines: &Engines,
1307 type_id: TypeId,
1308 trait_name: &CallPath,
1309 trait_type_args: &[GenericArgument],
1310 ) -> Vec<ty::TyTraitItem> {
1311 TraitMap::get_items_for_type_and_trait_name_and_trait_type_arguments(
1312 handler,
1313 module,
1314 engines,
1315 type_id,
1316 trait_name,
1317 trait_type_args,
1318 )
1319 .into_iter()
1320 .map(|item| item.expect_typed())
1321 .collect::<Vec<_>>()
1322 }
1323
1324 pub(crate) fn get_trait_names_and_type_arguments_for_type(
1325 module: &Module,
1326 engines: &Engines,
1327 type_id: TypeId,
1328 ) -> Vec<(CallPath, Vec<GenericArgument>)> {
1329 let type_id = engines.te().get_unaliased_type_id(type_id);
1330
1331 let type_engine = engines.te();
1332 let unify_check = UnifyCheck::constraint_subset(engines);
1333 let mut trait_names = vec![];
1334 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1336 return trait_names;
1337 }
1338 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1339 lexical_scope.items.implemented_traits.for_each_impls(
1340 engines,
1341 type_id,
1342 false,
1343 |entry| {
1344 if unify_check.check(type_id, entry.inner.key.type_id) {
1345 let trait_call_path = CallPath {
1346 prefixes: entry.inner.key.name.prefixes.clone(),
1347 suffix: entry.inner.key.name.suffix.name.clone(),
1348 callpath_type: entry.inner.key.name.callpath_type,
1349 };
1350 trait_names
1351 .push((trait_call_path, entry.inner.key.name.suffix.args.clone()));
1352 }
1353 },
1354 );
1355 Ok(None::<()>)
1356 });
1357 trait_names
1358 }
1359
1360 pub(crate) fn type_implements_trait<F: Fn(&SharedTraitEntry) -> bool>(
1363 module: &Module,
1364 engines: &Engines,
1365 type_id: TypeId,
1366 predicate: F,
1367 ) -> bool {
1368 let type_id = engines.te().get_unaliased_type_id(type_id);
1369
1370 if matches!(&*engines.te().get(type_id), TypeInfo::ErrorRecovery(_)) {
1372 return false;
1373 }
1374
1375 let unify_check = UnifyCheck::constraint_subset(engines);
1376 let mut implements_trait = false;
1377 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1378 lexical_scope.items.implemented_traits.for_each_impls(
1379 engines,
1380 type_id,
1381 false,
1382 |entry| {
1383 if !implements_trait
1386 && unify_check.check(type_id, entry.inner.key.type_id)
1387 && predicate(entry)
1388 {
1389 implements_trait = true;
1390 }
1391 },
1392 );
1393 Ok(None::<()>)
1394 });
1395 implements_trait
1396 }
1397
1398 pub(crate) fn get_trait_item_for_type(
1399 module: &Module,
1400 handler: &Handler,
1401 engines: &Engines,
1402 symbol: &Ident,
1403 type_id: TypeId,
1404 as_trait: Option<CallPath>,
1405 ) -> Result<ResolvedTraitImplItem, ErrorEmitted> {
1406 let type_id = engines.te().get_unaliased_type_id(type_id);
1407
1408 let mut candidates = HashMap::<String, ResolvedTraitImplItem>::new();
1409
1410 TraitMap::find_items_and_trait_key_for_type(
1411 module,
1412 engines,
1413 type_id,
1414 &mut |trait_item, trait_key| match trait_item {
1415 ResolvedTraitImplItem::Parsed(impl_item) => match impl_item {
1416 ImplItem::Fn(fn_ref) => {
1417 let decl = engines.pe().get_function(&fn_ref);
1418 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1419 if decl.name.as_str() == symbol.as_str()
1420 && (as_trait.is_none()
1421 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1422 {
1423 candidates.insert(
1424 trait_call_path_string,
1425 ResolvedTraitImplItem::Parsed(ImplItem::Fn(fn_ref)),
1426 );
1427 }
1428 }
1429 ImplItem::Constant(const_ref) => {
1430 let decl = engines.pe().get_constant(&const_ref);
1431 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1432 if decl.name.as_str() == symbol.as_str()
1433 && (as_trait.is_none()
1434 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1435 {
1436 candidates.insert(
1437 trait_call_path_string,
1438 ResolvedTraitImplItem::Parsed(ImplItem::Constant(const_ref)),
1439 );
1440 }
1441 }
1442 ImplItem::Type(type_ref) => {
1443 let decl = engines.pe().get_trait_type(&type_ref);
1444 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1445 if decl.name.as_str() == symbol.as_str()
1446 && (as_trait.is_none()
1447 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1448 {
1449 candidates.insert(
1450 trait_call_path_string,
1451 ResolvedTraitImplItem::Parsed(ImplItem::Type(type_ref)),
1452 );
1453 }
1454 }
1455 },
1456 ResolvedTraitImplItem::Typed(ty_impl_item) => match ty_impl_item {
1457 ty::TyTraitItem::Fn(fn_ref) => {
1458 let decl = engines.de().get_function(&fn_ref);
1459 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1460 if decl.name.as_str() == symbol.as_str()
1461 && (as_trait.is_none()
1462 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1463 {
1464 candidates.insert(
1465 trait_call_path_string,
1466 ResolvedTraitImplItem::Typed(TyTraitItem::Fn(fn_ref)),
1467 );
1468 }
1469 }
1470 ty::TyTraitItem::Constant(const_ref) => {
1471 let decl = engines.de().get_constant(&const_ref);
1472 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1473 if decl.call_path.suffix.as_str() == symbol.as_str()
1474 && (as_trait.is_none()
1475 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1476 {
1477 candidates.insert(
1478 trait_call_path_string,
1479 ResolvedTraitImplItem::Typed(TyTraitItem::Constant(const_ref)),
1480 );
1481 }
1482 }
1483 ty::TyTraitItem::Type(type_ref) => {
1484 let decl = engines.de().get_type(&type_ref);
1485 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1486 if decl.name.as_str() == symbol.as_str()
1487 && (as_trait.is_none()
1488 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1489 {
1490 candidates.insert(
1491 trait_call_path_string,
1492 ResolvedTraitImplItem::Typed(TyTraitItem::Type(type_ref)),
1493 );
1494 }
1495 }
1496 },
1497 },
1498 );
1499
1500 match candidates.len().cmp(&1) {
1501 Ordering::Greater => Err(handler.emit_err(
1502 CompileError::MultipleApplicableItemsInScope {
1503 item_name: symbol.as_str().to_string(),
1504 item_kind: "item".to_string(),
1505 as_traits: candidates
1506 .keys()
1507 .map(|k| {
1508 (
1509 k.clone()
1510 .split("::")
1511 .collect::<Vec<_>>()
1512 .last()
1513 .unwrap()
1514 .to_string(),
1515 engines.help_out(type_id).to_string(),
1516 )
1517 })
1518 .collect::<Vec<_>>(),
1519 span: symbol.span(),
1520 },
1521 )),
1522 Ordering::Less => Err(handler.emit_err(CompileError::SymbolNotFound {
1523 name: symbol.into(),
1524 })),
1525 Ordering::Equal => Ok(candidates.values().next().unwrap().clone()),
1526 }
1527 }
1528
1529 #[allow(clippy::too_many_arguments)]
1531 pub(crate) fn check_if_trait_constraints_are_satisfied_for_type(
1532 handler: &Handler,
1533 module: &mut Module,
1534 type_id: TypeId,
1535 constraints: &[TraitConstraint],
1536 access_span: &Span,
1537 engines: &Engines,
1538 ) -> Result<(), ErrorEmitted> {
1539 let type_engine = engines.te();
1540
1541 let type_id = type_engine.get_unaliased_type_id(type_id);
1542
1543 type_engine.decay_numeric(handler, engines, type_id, access_span)?;
1545
1546 if constraints.is_empty() {
1547 return Ok(());
1548 }
1549
1550 let mut hasher = DefaultHasher::default();
1552 type_id.hash(&mut hasher);
1553 for c in constraints {
1554 c.hash(&mut hasher, engines);
1555 }
1556 let hash = hasher.finish();
1557
1558 {
1559 let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1560 if trait_map.satisfied_cache.contains(&hash) {
1561 return Ok(());
1562 }
1563 }
1564
1565 let all_impld_traits: BTreeSet<(Ident, TypeId)> =
1566 Self::get_all_implemented_traits(module, type_id, engines);
1567
1568 match Self::check_if_trait_constraints_are_satisfied_for_type_inner(
1570 handler,
1571 type_id,
1572 constraints,
1573 access_span,
1574 engines,
1575 all_impld_traits,
1576 ) {
1577 Ok(()) => {
1578 let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1579 trait_map.satisfied_cache.insert(hash);
1580 Ok(())
1581 }
1582 r => r,
1583 }
1584 }
1585
1586 fn get_all_implemented_traits(
1587 module: &Module,
1588 type_id: TypeId,
1589 engines: &Engines,
1590 ) -> BTreeSet<(Ident, TypeId)> {
1591 let mut all_impld_traits: BTreeSet<(Ident, TypeId)> = Default::default();
1592 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1593 all_impld_traits.extend(
1594 lexical_scope
1595 .items
1596 .implemented_traits
1597 .get_implemented_traits(type_id, engines),
1598 );
1599 Ok(None::<()>)
1600 });
1601 all_impld_traits
1602 }
1603
1604 fn get_implemented_traits(
1605 &self,
1606 type_id: TypeId,
1607 engines: &Engines,
1608 ) -> BTreeSet<(Ident, TypeId)> {
1609 let type_engine = engines.te();
1610 let unify_check = UnifyCheck::constraint_subset(engines);
1611 let mut all_impld_traits = BTreeSet::<(Ident, TypeId)>::new();
1612 self.for_each_impls(engines, type_id, true, |e| {
1613 let key = &e.inner.key;
1614 let suffix = &key.name.suffix;
1615 if unify_check.check(type_id, key.type_id) {
1616 let map_trait_type_id = type_engine.new_custom(
1617 engines,
1618 suffix.name.clone().into(),
1619 if suffix.args.is_empty() {
1620 None
1621 } else {
1622 Some(suffix.args.to_vec())
1623 },
1624 );
1625 all_impld_traits.insert((suffix.name.clone(), map_trait_type_id));
1626 }
1627 });
1628 all_impld_traits
1629 }
1630
1631 #[allow(clippy::too_many_arguments)]
1632 fn check_if_trait_constraints_are_satisfied_for_type_inner(
1633 handler: &Handler,
1634 type_id: TypeId,
1635 constraints: &[TraitConstraint],
1636 access_span: &Span,
1637 engines: &Engines,
1638 all_impld_traits: BTreeSet<(Ident, TypeId)>,
1639 ) -> Result<(), ErrorEmitted> {
1640 let type_engine = engines.te();
1641 let unify_check = UnifyCheck::constraint_subset(engines);
1642
1643 let required_traits: BTreeSet<(Ident, TypeId)> = constraints
1644 .iter()
1645 .map(|c| {
1646 let TraitConstraint {
1647 trait_name: constraint_trait_name,
1648 type_arguments: constraint_type_arguments,
1649 } = c;
1650 let constraint_type_id = type_engine.new_custom(
1651 engines,
1652 constraint_trait_name.suffix.clone().into(),
1653 if constraint_type_arguments.is_empty() {
1654 None
1655 } else {
1656 Some(constraint_type_arguments.clone())
1657 },
1658 );
1659 (c.trait_name.suffix.clone(), constraint_type_id)
1660 })
1661 .collect();
1662
1663 let traits_not_found: BTreeSet<(BaseIdent, TypeId)> = required_traits
1664 .into_iter()
1665 .filter(|(required_trait_name, required_trait_type_id)| {
1666 !all_impld_traits
1667 .iter()
1668 .any(|(trait_name, constraint_type_id)| {
1669 trait_name == required_trait_name
1670 && unify_check.check(*constraint_type_id, *required_trait_type_id)
1671 })
1672 })
1673 .collect();
1674
1675 handler.scope(|handler| {
1676 for (trait_name, constraint_type_id) in traits_not_found.iter() {
1677 let mut type_arguments_string = "".to_string();
1678 if let TypeInfo::Custom {
1679 qualified_call_path: _,
1680 type_arguments: Some(type_arguments),
1681 } = &*type_engine.get(*constraint_type_id)
1682 {
1683 type_arguments_string = format!("<{}>", engines.help_out(type_arguments));
1684 }
1685
1686 handler.emit_err(CompileError::TraitConstraintNotSatisfied {
1688 type_id: type_id.index(),
1689 ty: engines.help_out(type_id).to_string(),
1690 trait_name: format!("{trait_name}{type_arguments_string}"),
1691 span: access_span.clone(),
1692 });
1693 }
1694
1695 Ok(())
1696 })
1697 }
1698
1699 pub fn get_trait_constraints_are_satisfied_for_types(
1700 module: &Module,
1701 _handler: &Handler,
1702 type_id: TypeId,
1703 constraints: &[TraitConstraint],
1704 engines: &Engines,
1705 ) -> Result<Vec<(TypeId, String)>, ErrorEmitted> {
1706 let type_id = engines.te().get_unaliased_type_id(type_id);
1707
1708 let _decl_engine = engines.de();
1709 let unify_check = UnifyCheck::coercion(engines);
1710 let unify_check_equality = UnifyCheck::constraint_subset(engines);
1711
1712 let mut impld_traits_type_ids: Vec<Vec<(TypeId, String)>> = vec![];
1713 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1714 lexical_scope
1715 .items
1716 .implemented_traits
1717 .for_each_impls(engines, type_id, true, |e| {
1718 let mut traits: Vec<(TypeId, String)> = vec![];
1719
1720 let key = &e.inner.key;
1721 for constraint in constraints {
1722 if key.name.suffix.name == constraint.trait_name.suffix
1723 && key
1724 .name
1725 .suffix
1726 .args
1727 .iter()
1728 .zip(constraint.type_arguments.iter())
1729 .all(|(a1, a2)| {
1730 unify_check_equality.check(a1.type_id(), a2.type_id())
1731 })
1732 && unify_check.check(type_id, key.type_id)
1733 {
1734 let name_type_args = if !key.name.suffix.args.is_empty() {
1735 format!("<{}>", engines.help_out(key.name.suffix.args.clone()))
1736 } else {
1737 "".to_string()
1738 };
1739 let name =
1740 format!("{}{}", key.name.suffix.name.as_str(), name_type_args);
1741 traits.push((key.type_id, name));
1742 break;
1743 }
1744 }
1745 impld_traits_type_ids.push(traits);
1746 });
1747
1748 Ok(None::<()>)
1749 });
1750 Ok(impld_traits_type_ids.concat())
1751 }
1752
1753 fn get_impls_mut(&mut self, engines: &Engines, type_id: TypeId) -> &mut Vec<SharedTraitEntry> {
1754 let type_root_filter = Self::get_type_root_filter(engines, type_id);
1755 if !self.trait_impls.contains_key(&type_root_filter) {
1756 self.trait_impls
1757 .insert(type_root_filter.clone(), Vec::new());
1758 }
1759
1760 self.trait_impls.get_mut(&type_root_filter).unwrap()
1761 }
1762
1763 pub(crate) fn for_each_impls<F>(
1764 &self,
1765 engines: &Engines,
1766 type_id: TypeId,
1767 include_placeholder: bool,
1768 mut callback: F,
1769 ) where
1770 F: FnMut(&SharedTraitEntry),
1771 {
1772 let type_root_filter = Self::get_type_root_filter(engines, type_id);
1773 self.trait_impls
1774 .get(&type_root_filter)
1775 .iter()
1776 .for_each(|vec| vec.iter().for_each(&mut callback));
1777 if include_placeholder && type_root_filter != TypeRootFilter::Placeholder {
1778 self.trait_impls
1779 .get(&TypeRootFilter::Placeholder)
1780 .iter()
1781 .for_each(|vec| vec.iter().for_each(&mut callback));
1782 }
1783 }
1784
1785 fn get_type_root_filter(engines: &Engines, type_id: TypeId) -> TypeRootFilter {
1788 use TypeInfo::*;
1789 match &*engines.te().get(type_id) {
1790 Unknown => TypeRootFilter::Unknown,
1791 Never => TypeRootFilter::Never,
1792 UnknownGeneric { .. } | Placeholder(_) => TypeRootFilter::Placeholder,
1793 TypeParam(_param) => unreachable!(),
1794 StringSlice => TypeRootFilter::StringSlice,
1795 StringArray(_) => TypeRootFilter::StringArray,
1796 UnsignedInteger(x) => match x {
1797 IntegerBits::Eight => TypeRootFilter::U8,
1798 IntegerBits::Sixteen => TypeRootFilter::U16,
1799 IntegerBits::ThirtyTwo => TypeRootFilter::U32,
1800 IntegerBits::SixtyFour => TypeRootFilter::U64,
1801 IntegerBits::V256 => TypeRootFilter::U256,
1802 },
1803 Boolean => TypeRootFilter::Bool,
1804 Custom {
1805 qualified_call_path: call_path,
1806 ..
1807 } => TypeRootFilter::Custom(call_path.call_path.suffix.to_string()),
1808 B256 => TypeRootFilter::B256,
1809 Numeric => TypeRootFilter::U64, Contract => TypeRootFilter::Contract,
1811 ErrorRecovery(_) => TypeRootFilter::ErrorRecovery,
1812 Tuple(fields) => TypeRootFilter::Tuple(fields.len()),
1813 UntypedEnum(decl_id) => TypeRootFilter::Enum(*decl_id),
1814 UntypedStruct(decl_id) => TypeRootFilter::Struct(*decl_id),
1815 Enum(decl_id) => {
1816 TypeRootFilter::Enum(engines.de().get_parsed_decl_id(decl_id).unwrap())
1818 }
1819 Struct(decl_id) => {
1820 TypeRootFilter::Struct(engines.de().get_parsed_decl_id(decl_id).unwrap())
1822 }
1823 ContractCaller { abi_name, .. } => TypeRootFilter::ContractCaller(abi_name.to_string()),
1824 Array(_, _) => TypeRootFilter::Array,
1825 RawUntypedPtr => TypeRootFilter::RawUntypedPtr,
1826 RawUntypedSlice => TypeRootFilter::RawUntypedSlice,
1827 Ptr(_) => TypeRootFilter::Ptr,
1828 Slice(_) => TypeRootFilter::Slice,
1829 Alias { ty, .. } => Self::get_type_root_filter(engines, ty.type_id),
1830 TraitType { name, .. } => TypeRootFilter::TraitType(name.to_string()),
1831 Ref {
1832 referenced_type, ..
1833 } => Self::get_type_root_filter(engines, referenced_type.type_id),
1834 }
1835 }
1836}