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 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_typeid) = decl.implementing_for_typeid {
999 type_mapping.insert(decl_implementing_for_typeid, type_id);
1000 }
1001 decl.subst(&SubstTypesContext::new(
1002 engines,
1003 &type_mapping,
1004 matches!(code_block_first_pass, CodeBlockFirstPass::No),
1005 ));
1006
1007 let new_ref = decl_engine
1008 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref())
1009 .with_parent(decl_engine, decl_ref.id().into());
1010
1011 ResolvedTraitImplItem::Typed(TyImplItem::Fn(new_ref))
1012 }
1013 ty::TyTraitItem::Constant(decl_ref) => {
1014 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
1015 decl.subst(&SubstTypesContext::new(
1016 engines,
1017 &type_mapping,
1018 matches!(code_block_first_pass, CodeBlockFirstPass::No),
1019 ));
1020 let new_ref = decl_engine
1021 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref());
1022 ResolvedTraitImplItem::Typed(TyImplItem::Constant(new_ref))
1023 }
1024 ty::TyTraitItem::Type(decl_ref) => {
1025 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
1026 decl.subst(&SubstTypesContext::new(
1027 engines,
1028 &type_mapping,
1029 matches!(code_block_first_pass, CodeBlockFirstPass::No),
1030 ));
1031 let new_ref = decl_engine
1032 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref());
1033 ResolvedTraitImplItem::Typed(TyImplItem::Type(new_ref))
1034 }
1035 },
1036 }
1037 }
1038
1039 pub(crate) fn append_items_for_type(
1049 module: &Module,
1050 engines: &Engines,
1051 type_id: TypeId,
1052 items: &mut Vec<ResolvedTraitImplItem>,
1053 ) {
1054 TraitMap::find_items_and_trait_key_for_type(module, engines, type_id, &mut |item, _| {
1055 items.push(item);
1056 });
1057 }
1058
1059 pub(crate) fn find_items_and_trait_key_for_type(
1060 module: &Module,
1061 engines: &Engines,
1062 type_id: TypeId,
1063 callback: &mut impl FnMut(ResolvedTraitImplItem, TraitKey),
1064 ) {
1065 let type_engine = engines.te();
1066 let type_id = engines.te().get_unaliased_type_id(type_id);
1067
1068 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1070 return;
1071 }
1072
1073 let unify_check = UnifyCheck::constraint_subset(engines);
1074
1075 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1076 lexical_scope.items.implemented_traits.for_each_impls(
1077 engines,
1078 type_id,
1079 true,
1080 |entry| {
1081 if unify_check.check(type_id, entry.inner.key.type_id) {
1082 let trait_items = Self::filter_dummy_methods(
1083 &entry.inner.value.trait_items,
1084 type_id,
1085 entry.inner.key.type_id,
1086 engines,
1087 )
1088 .map(|(_, i)| (i, entry.inner.key.clone()));
1089
1090 for i in trait_items {
1091 callback(i.0, i.1);
1092 }
1093 }
1094 },
1095 );
1096
1097 Ok(None::<()>)
1098 });
1099 }
1100
1101 pub fn get_impl_spans_for_type(
1111 module: &Module,
1112 engines: &Engines,
1113 type_id: &TypeId,
1114 ) -> Vec<Span> {
1115 let type_engine = engines.te();
1116 let unify_check = UnifyCheck::constraint_subset(engines);
1117
1118 let type_id = &engines.te().get_unaliased_type_id(*type_id);
1119
1120 let mut spans = vec![];
1121 if matches!(&*type_engine.get(*type_id), TypeInfo::ErrorRecovery(_)) {
1123 return spans;
1124 }
1125 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1126 lexical_scope.items.implemented_traits.for_each_impls(
1127 engines,
1128 *type_id,
1129 false,
1130 |entry| {
1131 if unify_check.check(*type_id, entry.inner.key.type_id) {
1132 spans.push(entry.inner.value.impl_span.clone());
1133 }
1134 },
1135 );
1136
1137 Ok(None::<()>)
1138 });
1139
1140 spans
1141 }
1142
1143 pub fn get_impl_spans_for_decl(
1145 module: &Module,
1146 engines: &Engines,
1147 ty_decl: &TyDecl,
1148 ) -> Vec<Span> {
1149 let handler = Handler::default();
1150 ty_decl
1151 .return_type(&handler, engines)
1152 .map(|type_id| TraitMap::get_impl_spans_for_type(module, engines, &type_id))
1153 .unwrap_or_default()
1154 }
1155
1156 pub fn get_impl_spans_for_trait_name(module: &Module, trait_name: &CallPath) -> Vec<Span> {
1159 let mut spans = vec![];
1160 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1161 spans.push(
1162 lexical_scope
1163 .items
1164 .implemented_traits
1165 .trait_impls
1166 .values()
1167 .map(|impls| {
1168 impls
1169 .iter()
1170 .filter_map(|entry| {
1171 let map_trait_name = CallPath {
1172 prefixes: entry.inner.key.name.prefixes.clone(),
1173 suffix: entry.inner.key.name.suffix.name.clone(),
1174 callpath_type: entry.inner.key.name.callpath_type,
1175 };
1176 if &map_trait_name == trait_name {
1177 Some(entry.inner.value.impl_span.clone())
1178 } else {
1179 None
1180 }
1181 })
1182 .collect::<Vec<Span>>()
1183 })
1184 .collect::<Vec<Vec<Span>>>()
1185 .concat(),
1186 );
1187 Ok(None::<()>)
1188 });
1189
1190 spans.concat()
1191 }
1192
1193 pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments(
1204 module: &Module,
1205 engines: &Engines,
1206 type_id: TypeId,
1207 trait_name: &CallPath,
1208 trait_type_args: &[GenericArgument],
1209 ) -> Vec<ResolvedTraitImplItem> {
1210 let type_id = engines.te().get_unaliased_type_id(type_id);
1211
1212 let type_engine = engines.te();
1213 let unify_check = UnifyCheck::constraint_subset(engines);
1214 let mut items = vec![];
1215 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1217 return items;
1218 }
1219 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1220 lexical_scope
1221 .items
1222 .implemented_traits
1223 .for_each_impls(engines, type_id, false, |e| {
1224 let map_trait_name = CallPath {
1225 prefixes: e.inner.key.name.prefixes.clone(),
1226 suffix: e.inner.key.name.suffix.name.clone(),
1227 callpath_type: e.inner.key.name.callpath_type,
1228 };
1229 if &map_trait_name == trait_name
1230 && unify_check.check(type_id, e.inner.key.type_id)
1231 && trait_type_args.len() == e.inner.key.name.suffix.args.len()
1232 && trait_type_args
1233 .iter()
1234 .zip(e.inner.key.name.suffix.args.iter())
1235 .all(|(t1, t2)| unify_check.check(t1.type_id(), t2.type_id()))
1236 {
1237 let type_mapping = TypeSubstMap::from_superset_and_subset(
1238 engines,
1239 e.inner.key.type_id,
1240 type_id,
1241 );
1242
1243 let mut trait_items = Self::filter_dummy_methods(
1244 &e.inner.value.trait_items,
1245 type_id,
1246 e.inner.key.type_id,
1247 engines,
1248 )
1249 .map(|(_, i)| {
1250 Self::make_item_for_type_mapping(
1251 engines,
1252 i,
1253 type_mapping.clone(),
1254 type_id,
1255 CodeBlockFirstPass::No,
1256 )
1257 })
1258 .collect::<Vec<_>>();
1259
1260 items.append(&mut trait_items);
1261 }
1262 });
1263 Ok(None::<()>)
1264 });
1265 items
1266 }
1267
1268 pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments_typed(
1279 module: &Module,
1280 engines: &Engines,
1281 type_id: TypeId,
1282 trait_name: &CallPath,
1283 trait_type_args: &[GenericArgument],
1284 ) -> Vec<ty::TyTraitItem> {
1285 TraitMap::get_items_for_type_and_trait_name_and_trait_type_arguments(
1286 module,
1287 engines,
1288 type_id,
1289 trait_name,
1290 trait_type_args,
1291 )
1292 .into_iter()
1293 .map(|item| item.expect_typed())
1294 .collect::<Vec<_>>()
1295 }
1296
1297 pub(crate) fn get_trait_names_and_type_arguments_for_type(
1298 module: &Module,
1299 engines: &Engines,
1300 type_id: TypeId,
1301 ) -> Vec<(CallPath, Vec<GenericArgument>)> {
1302 let type_id = engines.te().get_unaliased_type_id(type_id);
1303
1304 let type_engine = engines.te();
1305 let unify_check = UnifyCheck::constraint_subset(engines);
1306 let mut trait_names = vec![];
1307 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1309 return trait_names;
1310 }
1311 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1312 lexical_scope.items.implemented_traits.for_each_impls(
1313 engines,
1314 type_id,
1315 false,
1316 |entry| {
1317 if unify_check.check(type_id, entry.inner.key.type_id) {
1318 let trait_call_path = CallPath {
1319 prefixes: entry.inner.key.name.prefixes.clone(),
1320 suffix: entry.inner.key.name.suffix.name.clone(),
1321 callpath_type: entry.inner.key.name.callpath_type,
1322 };
1323 trait_names
1324 .push((trait_call_path, entry.inner.key.name.suffix.args.clone()));
1325 }
1326 },
1327 );
1328 Ok(None::<()>)
1329 });
1330 trait_names
1331 }
1332
1333 pub(crate) fn type_implements_trait<F: Fn(&SharedTraitEntry) -> bool>(
1336 module: &Module,
1337 engines: &Engines,
1338 type_id: TypeId,
1339 predicate: F,
1340 ) -> bool {
1341 let type_id = engines.te().get_unaliased_type_id(type_id);
1342
1343 if matches!(&*engines.te().get(type_id), TypeInfo::ErrorRecovery(_)) {
1345 return false;
1346 }
1347
1348 let unify_check = UnifyCheck::constraint_subset(engines);
1349 let mut implements_trait = false;
1350 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1351 lexical_scope.items.implemented_traits.for_each_impls(
1352 engines,
1353 type_id,
1354 false,
1355 |entry| {
1356 if !implements_trait
1359 && unify_check.check(type_id, entry.inner.key.type_id)
1360 && predicate(entry)
1361 {
1362 implements_trait = true;
1363 }
1364 },
1365 );
1366 Ok(None::<()>)
1367 });
1368 implements_trait
1369 }
1370
1371 pub(crate) fn get_trait_item_for_type(
1372 module: &Module,
1373 handler: &Handler,
1374 engines: &Engines,
1375 symbol: &Ident,
1376 type_id: TypeId,
1377 as_trait: Option<CallPath>,
1378 ) -> Result<ResolvedTraitImplItem, ErrorEmitted> {
1379 let type_id = engines.te().get_unaliased_type_id(type_id);
1380
1381 let mut candidates = HashMap::<String, ResolvedTraitImplItem>::new();
1382
1383 TraitMap::find_items_and_trait_key_for_type(
1384 module,
1385 engines,
1386 type_id,
1387 &mut |trait_item, trait_key| match trait_item {
1388 ResolvedTraitImplItem::Parsed(impl_item) => match impl_item {
1389 ImplItem::Fn(fn_ref) => {
1390 let decl = engines.pe().get_function(&fn_ref);
1391 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1392 if decl.name.as_str() == symbol.as_str()
1393 && (as_trait.is_none()
1394 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1395 {
1396 candidates.insert(
1397 trait_call_path_string,
1398 ResolvedTraitImplItem::Parsed(ImplItem::Fn(fn_ref)),
1399 );
1400 }
1401 }
1402 ImplItem::Constant(const_ref) => {
1403 let decl = engines.pe().get_constant(&const_ref);
1404 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1405 if decl.name.as_str() == symbol.as_str()
1406 && (as_trait.is_none()
1407 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1408 {
1409 candidates.insert(
1410 trait_call_path_string,
1411 ResolvedTraitImplItem::Parsed(ImplItem::Constant(const_ref)),
1412 );
1413 }
1414 }
1415 ImplItem::Type(type_ref) => {
1416 let decl = engines.pe().get_trait_type(&type_ref);
1417 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1418 if decl.name.as_str() == symbol.as_str()
1419 && (as_trait.is_none()
1420 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1421 {
1422 candidates.insert(
1423 trait_call_path_string,
1424 ResolvedTraitImplItem::Parsed(ImplItem::Type(type_ref)),
1425 );
1426 }
1427 }
1428 },
1429 ResolvedTraitImplItem::Typed(ty_impl_item) => match ty_impl_item {
1430 ty::TyTraitItem::Fn(fn_ref) => {
1431 let decl = engines.de().get_function(&fn_ref);
1432 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1433 if decl.name.as_str() == symbol.as_str()
1434 && (as_trait.is_none()
1435 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1436 {
1437 candidates.insert(
1438 trait_call_path_string,
1439 ResolvedTraitImplItem::Typed(TyTraitItem::Fn(fn_ref)),
1440 );
1441 }
1442 }
1443 ty::TyTraitItem::Constant(const_ref) => {
1444 let decl = engines.de().get_constant(&const_ref);
1445 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1446 if decl.call_path.suffix.as_str() == symbol.as_str()
1447 && (as_trait.is_none()
1448 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1449 {
1450 candidates.insert(
1451 trait_call_path_string,
1452 ResolvedTraitImplItem::Typed(TyTraitItem::Constant(const_ref)),
1453 );
1454 }
1455 }
1456 ty::TyTraitItem::Type(type_ref) => {
1457 let decl = engines.de().get_type(&type_ref);
1458 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1459 if decl.name.as_str() == symbol.as_str()
1460 && (as_trait.is_none()
1461 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1462 {
1463 candidates.insert(
1464 trait_call_path_string,
1465 ResolvedTraitImplItem::Typed(TyTraitItem::Type(type_ref)),
1466 );
1467 }
1468 }
1469 },
1470 },
1471 );
1472
1473 match candidates.len().cmp(&1) {
1474 Ordering::Greater => Err(handler.emit_err(
1475 CompileError::MultipleApplicableItemsInScope {
1476 item_name: symbol.as_str().to_string(),
1477 item_kind: "item".to_string(),
1478 as_traits: candidates
1479 .keys()
1480 .map(|k| {
1481 (
1482 k.clone()
1483 .split("::")
1484 .collect::<Vec<_>>()
1485 .last()
1486 .unwrap()
1487 .to_string(),
1488 engines.help_out(type_id).to_string(),
1489 )
1490 })
1491 .collect::<Vec<_>>(),
1492 span: symbol.span(),
1493 },
1494 )),
1495 Ordering::Less => Err(handler.emit_err(CompileError::SymbolNotFound {
1496 name: symbol.clone(),
1497 span: symbol.span(),
1498 })),
1499 Ordering::Equal => Ok(candidates.values().next().unwrap().clone()),
1500 }
1501 }
1502
1503 #[allow(clippy::too_many_arguments)]
1505 pub(crate) fn check_if_trait_constraints_are_satisfied_for_type(
1506 handler: &Handler,
1507 module: &mut Module,
1508 type_id: TypeId,
1509 constraints: &[TraitConstraint],
1510 access_span: &Span,
1511 engines: &Engines,
1512 ) -> Result<(), ErrorEmitted> {
1513 let type_engine = engines.te();
1514
1515 let type_id = type_engine.get_unaliased_type_id(type_id);
1516
1517 type_engine.decay_numeric(handler, engines, type_id, access_span)?;
1519
1520 if constraints.is_empty() {
1521 return Ok(());
1522 }
1523
1524 let mut hasher = DefaultHasher::default();
1526 type_id.hash(&mut hasher);
1527 for c in constraints {
1528 c.hash(&mut hasher, engines);
1529 }
1530 let hash = hasher.finish();
1531
1532 {
1533 let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1534 if trait_map.satisfied_cache.contains(&hash) {
1535 return Ok(());
1536 }
1537 }
1538
1539 let all_impld_traits: BTreeSet<(Ident, TypeId)> =
1540 Self::get_all_implemented_traits(module, type_id, engines);
1541
1542 match Self::check_if_trait_constraints_are_satisfied_for_type_inner(
1544 handler,
1545 type_id,
1546 constraints,
1547 access_span,
1548 engines,
1549 all_impld_traits,
1550 ) {
1551 Ok(()) => {
1552 let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1553 trait_map.satisfied_cache.insert(hash);
1554 Ok(())
1555 }
1556 r => r,
1557 }
1558 }
1559
1560 fn get_all_implemented_traits(
1561 module: &Module,
1562 type_id: TypeId,
1563 engines: &Engines,
1564 ) -> BTreeSet<(Ident, TypeId)> {
1565 let mut all_impld_traits: BTreeSet<(Ident, TypeId)> = Default::default();
1566 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1567 all_impld_traits.extend(
1568 lexical_scope
1569 .items
1570 .implemented_traits
1571 .get_implemented_traits(type_id, engines),
1572 );
1573 Ok(None::<()>)
1574 });
1575 all_impld_traits
1576 }
1577
1578 fn get_implemented_traits(
1579 &self,
1580 type_id: TypeId,
1581 engines: &Engines,
1582 ) -> BTreeSet<(Ident, TypeId)> {
1583 let type_engine = engines.te();
1584 let unify_check = UnifyCheck::constraint_subset(engines);
1585 let mut all_impld_traits = BTreeSet::<(Ident, TypeId)>::new();
1586 self.for_each_impls(engines, type_id, true, |e| {
1587 let key = &e.inner.key;
1588 let suffix = &key.name.suffix;
1589 if unify_check.check(type_id, key.type_id) {
1590 let map_trait_type_id = type_engine.new_custom(
1591 engines,
1592 suffix.name.clone().into(),
1593 if suffix.args.is_empty() {
1594 None
1595 } else {
1596 Some(suffix.args.to_vec())
1597 },
1598 );
1599 all_impld_traits.insert((suffix.name.clone(), map_trait_type_id));
1600 }
1601 });
1602 all_impld_traits
1603 }
1604
1605 #[allow(clippy::too_many_arguments)]
1606 fn check_if_trait_constraints_are_satisfied_for_type_inner(
1607 handler: &Handler,
1608 type_id: TypeId,
1609 constraints: &[TraitConstraint],
1610 access_span: &Span,
1611 engines: &Engines,
1612 all_impld_traits: BTreeSet<(Ident, TypeId)>,
1613 ) -> Result<(), ErrorEmitted> {
1614 let type_engine = engines.te();
1615 let unify_check = UnifyCheck::constraint_subset(engines);
1616
1617 let required_traits: BTreeSet<(Ident, TypeId)> = constraints
1618 .iter()
1619 .map(|c| {
1620 let TraitConstraint {
1621 trait_name: constraint_trait_name,
1622 type_arguments: constraint_type_arguments,
1623 } = c;
1624 let constraint_type_id = type_engine.new_custom(
1625 engines,
1626 constraint_trait_name.suffix.clone().into(),
1627 if constraint_type_arguments.is_empty() {
1628 None
1629 } else {
1630 Some(constraint_type_arguments.clone())
1631 },
1632 );
1633 (c.trait_name.suffix.clone(), constraint_type_id)
1634 })
1635 .collect();
1636
1637 let traits_not_found: BTreeSet<(BaseIdent, TypeId)> = required_traits
1638 .into_iter()
1639 .filter(|(required_trait_name, required_trait_type_id)| {
1640 !all_impld_traits
1641 .iter()
1642 .any(|(trait_name, constraint_type_id)| {
1643 trait_name == required_trait_name
1644 && unify_check.check(*constraint_type_id, *required_trait_type_id)
1645 })
1646 })
1647 .collect();
1648
1649 handler.scope(|handler| {
1650 for (trait_name, constraint_type_id) in traits_not_found.iter() {
1651 let mut type_arguments_string = "".to_string();
1652 if let TypeInfo::Custom {
1653 qualified_call_path: _,
1654 type_arguments: Some(type_arguments),
1655 } = &*type_engine.get(*constraint_type_id)
1656 {
1657 type_arguments_string = format!("<{}>", engines.help_out(type_arguments));
1658 }
1659
1660 handler.emit_err(CompileError::TraitConstraintNotSatisfied {
1662 type_id: type_id.index(),
1663 ty: engines.help_out(type_id).to_string(),
1664 trait_name: format!("{trait_name}{type_arguments_string}"),
1665 span: access_span.clone(),
1666 });
1667 }
1668
1669 Ok(())
1670 })
1671 }
1672
1673 pub fn get_trait_constraints_are_satisfied_for_types(
1674 module: &Module,
1675 _handler: &Handler,
1676 type_id: TypeId,
1677 constraints: &[TraitConstraint],
1678 engines: &Engines,
1679 ) -> Result<Vec<(TypeId, String)>, ErrorEmitted> {
1680 let type_id = engines.te().get_unaliased_type_id(type_id);
1681
1682 let _decl_engine = engines.de();
1683 let unify_check = UnifyCheck::coercion(engines);
1684 let unify_check_equality = UnifyCheck::constraint_subset(engines);
1685
1686 let mut impld_traits_type_ids: Vec<Vec<(TypeId, String)>> = vec![];
1687 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1688 lexical_scope
1689 .items
1690 .implemented_traits
1691 .for_each_impls(engines, type_id, true, |e| {
1692 let mut traits: Vec<(TypeId, String)> = vec![];
1693
1694 let key = &e.inner.key;
1695 for constraint in constraints {
1696 if key.name.suffix.name == constraint.trait_name.suffix
1697 && key
1698 .name
1699 .suffix
1700 .args
1701 .iter()
1702 .zip(constraint.type_arguments.iter())
1703 .all(|(a1, a2)| {
1704 unify_check_equality.check(a1.type_id(), a2.type_id())
1705 })
1706 && unify_check.check(type_id, key.type_id)
1707 {
1708 let name_type_args = if !key.name.suffix.args.is_empty() {
1709 format!("<{}>", engines.help_out(key.name.suffix.args.clone()))
1710 } else {
1711 "".to_string()
1712 };
1713 let name =
1714 format!("{}{}", key.name.suffix.name.as_str(), name_type_args);
1715 traits.push((key.type_id, name));
1716 break;
1717 }
1718 }
1719 impld_traits_type_ids.push(traits);
1720 });
1721
1722 Ok(None::<()>)
1723 });
1724 Ok(impld_traits_type_ids.concat())
1725 }
1726
1727 fn get_impls_mut(&mut self, engines: &Engines, type_id: TypeId) -> &mut Vec<SharedTraitEntry> {
1728 let type_root_filter = Self::get_type_root_filter(engines, type_id);
1729 if !self.trait_impls.contains_key(&type_root_filter) {
1730 self.trait_impls
1731 .insert(type_root_filter.clone(), Vec::new());
1732 }
1733
1734 self.trait_impls.get_mut(&type_root_filter).unwrap()
1735 }
1736
1737 pub(crate) fn for_each_impls<F>(
1738 &self,
1739 engines: &Engines,
1740 type_id: TypeId,
1741 include_placeholder: bool,
1742 mut callback: F,
1743 ) where
1744 F: FnMut(&SharedTraitEntry),
1745 {
1746 let type_root_filter = Self::get_type_root_filter(engines, type_id);
1747 self.trait_impls
1748 .get(&type_root_filter)
1749 .iter()
1750 .for_each(|vec| vec.iter().for_each(&mut callback));
1751 if include_placeholder && type_root_filter != TypeRootFilter::Placeholder {
1752 self.trait_impls
1753 .get(&TypeRootFilter::Placeholder)
1754 .iter()
1755 .for_each(|vec| vec.iter().for_each(&mut callback));
1756 }
1757 }
1758
1759 fn get_type_root_filter(engines: &Engines, type_id: TypeId) -> TypeRootFilter {
1762 use TypeInfo::*;
1763 match &*engines.te().get(type_id) {
1764 Unknown => TypeRootFilter::Unknown,
1765 Never => TypeRootFilter::Never,
1766 UnknownGeneric { .. } | Placeholder(_) => TypeRootFilter::Placeholder,
1767 TypeParam(_param) => unreachable!(),
1768 StringSlice => TypeRootFilter::StringSlice,
1769 StringArray(_) => TypeRootFilter::StringArray,
1770 UnsignedInteger(x) => match x {
1771 IntegerBits::Eight => TypeRootFilter::U8,
1772 IntegerBits::Sixteen => TypeRootFilter::U16,
1773 IntegerBits::ThirtyTwo => TypeRootFilter::U32,
1774 IntegerBits::SixtyFour => TypeRootFilter::U64,
1775 IntegerBits::V256 => TypeRootFilter::U256,
1776 },
1777 Boolean => TypeRootFilter::Bool,
1778 Custom {
1779 qualified_call_path: call_path,
1780 ..
1781 } => TypeRootFilter::Custom(call_path.call_path.suffix.to_string()),
1782 B256 => TypeRootFilter::B256,
1783 Numeric => TypeRootFilter::U64, Contract => TypeRootFilter::Contract,
1785 ErrorRecovery(_) => TypeRootFilter::ErrorRecovery,
1786 Tuple(fields) => TypeRootFilter::Tuple(fields.len()),
1787 UntypedEnum(decl_id) => TypeRootFilter::Enum(*decl_id),
1788 UntypedStruct(decl_id) => TypeRootFilter::Struct(*decl_id),
1789 Enum(decl_id) => {
1790 TypeRootFilter::Enum(engines.de().get_parsed_decl_id(decl_id).unwrap())
1792 }
1793 Struct(decl_id) => {
1794 TypeRootFilter::Struct(engines.de().get_parsed_decl_id(decl_id).unwrap())
1796 }
1797 ContractCaller { abi_name, .. } => TypeRootFilter::ContractCaller(abi_name.to_string()),
1798 Array(_, _) => TypeRootFilter::Array,
1799 RawUntypedPtr => TypeRootFilter::RawUntypedPtr,
1800 RawUntypedSlice => TypeRootFilter::RawUntypedSlice,
1801 Ptr(_) => TypeRootFilter::Ptr,
1802 Slice(_) => TypeRootFilter::Slice,
1803 Alias { ty, .. } => Self::get_type_root_filter(engines, ty.type_id()),
1804 TraitType { name, .. } => TypeRootFilter::TraitType(name.to_string()),
1805 Ref {
1806 referenced_type, ..
1807 } => Self::get_type_root_filter(engines, referenced_type.type_id()),
1808 }
1809 }
1810}