1use std::{
2 cmp::Ordering,
3 collections::{BTreeMap, BTreeSet, HashMap, HashSet},
4 fmt,
5 hash::{DefaultHasher, Hash, Hasher},
6 sync::Arc,
7};
8
9use sway_error::{
10 error::CompileError,
11 handler::{ErrorEmitted, Handler},
12};
13use sway_types::{integer_bits::IntegerBits, BaseIdent, Ident, Span, Spanned};
14
15use crate::{
16 decl_engine::{
17 parsed_id::ParsedDeclId, DeclEngineGet, DeclEngineGetParsedDeclId, DeclEngineInsert,
18 },
19 engine_threading::*,
20 language::{
21 parsed::{EnumDeclaration, ImplItem, StructDeclaration},
22 ty::{self, TyDecl, TyImplItem, TyTraitItem},
23 CallPath,
24 },
25 type_system::{SubstTypes, TypeId},
26 IncludeSelf, SubstTypesContext, TraitConstraint, TypeArgument, TypeEngine, TypeInfo,
27 TypeSubstMap, UnifyCheck,
28};
29
30use super::Module;
31
32#[derive(Debug, Clone)]
35pub enum TryInsertingTraitImplOnFailure {
36 Yes,
37 No,
38}
39
40#[derive(Clone)]
41pub enum CodeBlockFirstPass {
42 Yes,
43 No,
44}
45
46impl From<bool> for CodeBlockFirstPass {
47 fn from(value: bool) -> Self {
48 if value {
49 CodeBlockFirstPass::Yes
50 } else {
51 CodeBlockFirstPass::No
52 }
53 }
54}
55
56#[derive(Clone, Debug)]
57pub(crate) struct TraitSuffix {
58 pub(crate) name: Ident,
59 pub(crate) args: Vec<TypeArgument>,
60}
61impl PartialEqWithEngines for TraitSuffix {
62 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
63 self.name == other.name && self.args.eq(&other.args, ctx)
64 }
65}
66impl OrdWithEngines for TraitSuffix {
67 fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> std::cmp::Ordering {
68 self.name
69 .cmp(&other.name)
70 .then_with(|| self.args.cmp(&other.args, ctx))
71 }
72}
73
74impl DisplayWithEngines for TraitSuffix {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
76 let res = write!(f, "{}", self.name.as_str());
77 if !self.args.is_empty() {
78 write!(
79 f,
80 "<{}>",
81 self.args
82 .iter()
83 .map(|i| engines.help_out(i.type_id).to_string())
84 .collect::<Vec<_>>()
85 .join(", ")
86 )
87 } else {
88 res
89 }
90 }
91}
92
93impl DebugWithEngines for TraitSuffix {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
95 write!(f, "{}", engines.help_out(self))
96 }
97}
98
99type TraitName = Arc<CallPath<TraitSuffix>>;
100
101#[derive(Clone, Debug)]
102pub(crate) struct TraitKey {
103 pub(crate) name: TraitName,
104 pub(crate) type_id: TypeId,
105 pub(crate) impl_type_parameters: Vec<TypeId>,
106 pub(crate) trait_decl_span: Option<Span>,
107}
108
109impl OrdWithEngines for TraitKey {
110 fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> std::cmp::Ordering {
111 self.name.cmp(&other.name, ctx).then_with(|| {
112 self.type_id
113 .cmp(&other.type_id)
114 .then_with(|| self.impl_type_parameters.cmp(&other.impl_type_parameters))
115 })
116 }
117}
118
119#[derive(Clone, Debug)]
120pub enum ResolvedTraitImplItem {
121 Parsed(ImplItem),
122 Typed(TyImplItem),
123}
124
125impl DebugWithEngines for ResolvedTraitImplItem {
126 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
127 match self {
128 ResolvedTraitImplItem::Parsed(_) => panic!(),
129 ResolvedTraitImplItem::Typed(ty) => write!(f, "{:?}", engines.help_out(ty)),
130 }
131 }
132}
133
134impl ResolvedTraitImplItem {
135 fn expect_typed(self) -> TyImplItem {
136 match self {
137 ResolvedTraitImplItem::Parsed(_) => panic!(),
138 ResolvedTraitImplItem::Typed(ty) => ty,
139 }
140 }
141
142 pub fn span(&self, engines: &Engines) -> Span {
143 match self {
144 ResolvedTraitImplItem::Parsed(item) => item.span(engines),
145 ResolvedTraitImplItem::Typed(item) => item.span(),
146 }
147 }
148}
149
150type TraitItems = BTreeMap<String, ResolvedTraitImplItem>;
152
153#[derive(Clone, Debug)]
154pub(crate) struct TraitValue {
155 pub(crate) trait_items: TraitItems,
156 pub(crate) impl_span: Span,
158}
159
160#[derive(Clone, Debug)]
161pub(crate) struct TraitEntry {
162 pub(crate) key: TraitKey,
163 pub(crate) value: TraitValue,
164}
165
166pub(crate) type TraitImpls = BTreeMap<TypeRootFilter, Vec<TraitEntry>>;
170
171#[derive(Clone, Hash, Eq, PartialOrd, Ord, PartialEq, Debug)]
172pub(crate) enum TypeRootFilter {
173 Unknown,
174 Never,
175 Placeholder,
176 StringSlice,
177 StringArray(usize),
178 U8,
179 U16,
180 U32,
181 U64,
182 U256,
183 Bool,
184 Custom(String),
185 B256,
186 Contract,
187 ErrorRecovery,
188 Tuple(usize),
189 Enum(ParsedDeclId<EnumDeclaration>),
190 Struct(ParsedDeclId<StructDeclaration>),
191 ContractCaller(String),
192 Array,
193 RawUntypedPtr,
194 RawUntypedSlice,
195 Ptr,
196 Slice,
197 TraitType(String),
198}
199
200#[derive(Clone, Debug, Default)]
205pub struct TraitMap {
206 pub(crate) trait_impls: TraitImpls,
207 satisfied_cache: HashSet<u64>,
208}
209
210pub(crate) enum IsImplSelf {
211 Yes,
212 No,
213}
214
215pub(crate) enum IsExtendingExistingImpl {
216 Yes,
217 No,
218}
219
220impl TraitMap {
221 #[allow(clippy::too_many_arguments)]
229 pub(crate) fn insert(
230 &mut self,
231 handler: &Handler,
232 trait_name: CallPath,
233 trait_type_args: Vec<TypeArgument>,
234 type_id: TypeId,
235 impl_type_parameters: Vec<TypeId>,
236 items: &[ResolvedTraitImplItem],
237 impl_span: &Span,
238 trait_decl_span: Option<Span>,
239 is_impl_self: IsImplSelf,
240 is_extending_existing_impl: IsExtendingExistingImpl,
241 engines: &Engines,
242 ) -> Result<(), ErrorEmitted> {
243 let unaliased_type_id = engines.te().get_unaliased_type_id(type_id);
244
245 handler.scope(|handler| {
246 let mut trait_items: TraitItems = BTreeMap::new();
247 for item in items.iter() {
248 match item {
249 ResolvedTraitImplItem::Parsed(_) => todo!(),
250 ResolvedTraitImplItem::Typed(ty_item) => match ty_item {
251 TyImplItem::Fn(decl_ref) => {
252 if trait_items
253 .insert(decl_ref.name().clone().to_string(), item.clone())
254 .is_some()
255 {
256 handler.emit_err(CompileError::MultipleDefinitionsOfName {
258 name: decl_ref.name().clone(),
259 span: decl_ref.span(),
260 });
261 }
262 }
263 TyImplItem::Constant(decl_ref) => {
264 trait_items.insert(decl_ref.name().to_string(), item.clone());
265 }
266 TyImplItem::Type(decl_ref) => {
267 trait_items.insert(decl_ref.name().to_string(), item.clone());
268 }
269 },
270 }
271 }
272
273 let trait_impls = self.get_impls_mut(engines, unaliased_type_id);
274
275 for TraitEntry {
277 key:
278 TraitKey {
279 name: map_trait_name,
280 type_id: map_type_id,
281 trait_decl_span: _,
282 impl_type_parameters: _,
283 },
284 value:
285 TraitValue {
286 trait_items: map_trait_items,
287 impl_span: existing_impl_span,
288 },
289 } in trait_impls.iter()
290 {
291 let CallPath {
292 suffix:
293 TraitSuffix {
294 name: map_trait_name_suffix,
295 args: map_trait_type_args,
296 },
297 ..
298 } = &*map_trait_name.clone();
299
300 let unify_checker = UnifyCheck::non_generic_constraint_subset(engines);
301
302 let types_are_subset = unify_checker.check(unaliased_type_id, *map_type_id)
306 && is_unified_type_subset(engines.te(), unaliased_type_id, *map_type_id);
307
308 fn is_unified_type_subset(
314 type_engine: &TypeEngine,
315 mut left: TypeId,
316 mut right: TypeId,
317 ) -> bool {
318 loop {
321 let left_ty_info = &*type_engine.get_unaliased(left);
322 let right_ty_info = &*type_engine.get_unaliased(right);
323 match (left_ty_info, right_ty_info) {
324 (
325 TypeInfo::Ref {
326 to_mutable_value: l_to_mut,
327 ..
328 },
329 TypeInfo::Ref {
330 to_mutable_value: r_to_mut,
331 ..
332 },
333 ) if *l_to_mut != *r_to_mut => return false, (
335 TypeInfo::Ref {
336 referenced_type: l_ty,
337 ..
338 },
339 TypeInfo::Ref {
340 referenced_type: r_ty,
341 ..
342 },
343 ) => {
344 left = l_ty.type_id;
345 right = r_ty.type_id;
346 }
347 _ => return true,
348 }
349 }
350 }
351
352 let mut traits_are_subset = true;
353 if *map_trait_name_suffix != trait_name.suffix
354 || map_trait_type_args.len() != trait_type_args.len()
355 {
356 traits_are_subset = false;
357 } else {
358 for (map_arg_type, arg_type) in
359 map_trait_type_args.iter().zip(trait_type_args.iter())
360 {
361 if !unify_checker.check(arg_type.type_id, map_arg_type.type_id) {
362 traits_are_subset = false;
363 }
364 }
365 }
366
367 if matches!(is_extending_existing_impl, IsExtendingExistingImpl::No)
368 && types_are_subset
369 && traits_are_subset
370 && matches!(is_impl_self, IsImplSelf::No)
371 {
372 handler.emit_err(CompileError::ConflictingImplsForTraitAndType {
373 trait_name: trait_name.to_string_with_args(engines, &trait_type_args),
374 type_implementing_for: engines.help_out(type_id).to_string(),
375 type_implementing_for_unaliased: engines
376 .help_out(unaliased_type_id)
377 .to_string(),
378 existing_impl_span: existing_impl_span.clone(),
379 second_impl_span: impl_span.clone(),
380 });
381 } else if types_are_subset
382 && (traits_are_subset || matches!(is_impl_self, IsImplSelf::Yes))
383 {
384 for name in trait_items.keys() {
385 let item = &trait_items[name];
386 match item {
387 ResolvedTraitImplItem::Parsed(_item) => todo!(),
388 ResolvedTraitImplItem::Typed(item) => match item {
389 ty::TyTraitItem::Fn(decl_ref) => {
390 if let Some(existing_item) = map_trait_items.get(name) {
391 handler.emit_err(
392 CompileError::DuplicateDeclDefinedForType {
393 decl_kind: "method".into(),
394 decl_name: decl_ref.name().to_string(),
395 type_implementing_for: engines
396 .help_out(type_id)
397 .to_string(),
398 type_implementing_for_unaliased: engines
399 .help_out(unaliased_type_id)
400 .to_string(),
401 existing_impl_span: existing_item
402 .span(engines)
403 .clone(),
404 second_impl_span: decl_ref.name().span(),
405 },
406 );
407 }
408 }
409 ty::TyTraitItem::Constant(decl_ref) => {
410 if let Some(existing_item) = map_trait_items.get(name) {
411 handler.emit_err(
412 CompileError::DuplicateDeclDefinedForType {
413 decl_kind: "constant".into(),
414 decl_name: decl_ref.name().to_string(),
415 type_implementing_for: engines
416 .help_out(type_id)
417 .to_string(),
418 type_implementing_for_unaliased: engines
419 .help_out(unaliased_type_id)
420 .to_string(),
421 existing_impl_span: existing_item
422 .span(engines)
423 .clone(),
424 second_impl_span: decl_ref.name().span(),
425 },
426 );
427 }
428 }
429 ty::TyTraitItem::Type(decl_ref) => {
430 if let Some(existing_item) = map_trait_items.get(name) {
431 handler.emit_err(
432 CompileError::DuplicateDeclDefinedForType {
433 decl_kind: "type".into(),
434 decl_name: decl_ref.name().to_string(),
435 type_implementing_for: engines
436 .help_out(type_id)
437 .to_string(),
438 type_implementing_for_unaliased: engines
439 .help_out(unaliased_type_id)
440 .to_string(),
441 existing_impl_span: existing_item
442 .span(engines)
443 .clone(),
444 second_impl_span: decl_ref.name().span(),
445 },
446 );
447 }
448 }
449 },
450 }
451 }
452 }
453 }
454 let trait_name: TraitName = Arc::new(CallPath {
455 prefixes: trait_name.prefixes,
456 suffix: TraitSuffix {
457 name: trait_name.suffix,
458 args: trait_type_args,
459 },
460 callpath_type: trait_name.callpath_type,
461 });
462
463 self.insert_inner(
465 trait_name,
466 impl_span.clone(),
467 trait_decl_span,
468 unaliased_type_id,
469 impl_type_parameters,
470 trait_items,
471 engines,
472 );
473
474 Ok(())
475 })
476 }
477
478 #[allow(clippy::too_many_arguments)]
479 fn insert_inner(
480 &mut self,
481 trait_name: TraitName,
482 impl_span: Span,
483 trait_decl_span: Option<Span>,
484 type_id: TypeId,
485 impl_type_parameters: Vec<TypeId>,
486 trait_methods: TraitItems,
487 engines: &Engines,
488 ) {
489 let key = TraitKey {
490 name: trait_name,
491 type_id,
492 trait_decl_span,
493 impl_type_parameters,
494 };
495 let value = TraitValue {
496 trait_items: trait_methods,
497 impl_span,
498 };
499 let entry = TraitEntry { key, value };
500 let mut trait_impls: TraitImpls = BTreeMap::<TypeRootFilter, Vec<TraitEntry>>::new();
501 let type_root_filter = Self::get_type_root_filter(engines, type_id);
502 let impls_vector = vec![entry];
503 trait_impls.insert(type_root_filter, impls_vector);
504
505 let trait_map = TraitMap {
506 trait_impls,
507 satisfied_cache: HashSet::default(),
508 };
509
510 self.extend(trait_map, engines);
511 }
512
513 pub(crate) fn extend(&mut self, other: TraitMap, engines: &Engines) {
516 for impls_key in other.trait_impls.keys() {
517 let oe_vec = &other.trait_impls[impls_key];
518 let self_vec = if let Some(self_vec) = self.trait_impls.get_mut(impls_key) {
519 self_vec
520 } else {
521 self.trait_impls
522 .insert(impls_key.clone(), Vec::<TraitEntry>::new());
523 self.trait_impls.get_mut(impls_key).unwrap()
524 };
525
526 for oe in oe_vec.iter() {
527 let pos = self_vec.binary_search_by(|se| {
528 se.key.cmp(&oe.key, &OrdWithEnginesContext::new(engines))
529 });
530
531 match pos {
532 Ok(pos) => self_vec[pos]
533 .value
534 .trait_items
535 .extend(oe.value.trait_items.clone()),
536 Err(pos) => self_vec.insert(pos, oe.clone()),
537 }
538 }
539 }
540 }
541
542 pub(crate) fn filter_by_trait_decl_span(&self, trait_decl_span: Span) -> TraitMap {
545 let mut trait_map = TraitMap::default();
546 for key in self.trait_impls.keys() {
547 let vec = &self.trait_impls[key];
548 for entry in vec {
549 if entry.key.trait_decl_span.as_ref() == Some(&trait_decl_span) {
550 let trait_map_vec =
551 if let Some(trait_map_vec) = trait_map.trait_impls.get_mut(key) {
552 trait_map_vec
553 } else {
554 trait_map
555 .trait_impls
556 .insert(key.clone(), Vec::<TraitEntry>::new());
557 trait_map.trait_impls.get_mut(key).unwrap()
558 };
559
560 trait_map_vec.push(entry.clone());
561 }
562 }
563 }
564 trait_map
565 }
566
567 pub(crate) fn filter_by_type_item_import(
626 &self,
627 type_id: TypeId,
628 engines: &Engines,
629 ) -> TraitMap {
630 let unify_checker = UnifyCheck::constraint_subset(engines);
631 let unify_checker_for_item_import = UnifyCheck::non_generic_constraint_subset(engines);
632
633 let decider = |left: TypeId, right: TypeId| {
635 unify_checker.check(left, right) || unify_checker_for_item_import.check(right, left)
636 };
637 let mut trait_map = self.filter_by_type_inner(engines, vec![type_id], decider);
638 let all_types = type_id
639 .extract_inner_types(engines, IncludeSelf::No)
640 .into_iter()
641 .collect::<Vec<_>>();
642 let decider2 = |left: TypeId, right: TypeId| unify_checker.check(left, right);
644
645 trait_map.extend(
646 self.filter_by_type_inner(engines, all_types, decider2),
647 engines,
648 );
649 trait_map
650 }
651
652 fn filter_by_type_inner(
653 &self,
654 engines: &Engines,
655 mut all_types: Vec<TypeId>,
656 decider: impl Fn(TypeId, TypeId) -> bool,
657 ) -> TraitMap {
658 let type_engine = engines.te();
659 let mut trait_map = TraitMap::default();
660 for type_id in all_types.iter_mut() {
661 let type_info = type_engine.get(*type_id);
662 self.for_each_impls(
663 engines,
664 *type_id,
665 true,
666 |TraitEntry {
667 key:
668 TraitKey {
669 name: map_trait_name,
670 type_id: map_type_id,
671 trait_decl_span: map_trait_decl_span,
672 impl_type_parameters: map_impl_type_parameters,
673 },
674 value:
675 TraitValue {
676 trait_items: map_trait_items,
677 impl_span,
678 },
679 }| {
680 if !type_engine.is_type_changeable(engines, &type_info)
681 && *type_id == *map_type_id
682 {
683 trait_map.insert_inner(
684 map_trait_name.clone(),
685 impl_span.clone(),
686 map_trait_decl_span.clone(),
687 *type_id,
688 map_impl_type_parameters.clone(),
689 map_trait_items.clone(),
690 engines,
691 );
692 } else if decider(*type_id, *map_type_id) {
693 trait_map.insert_inner(
694 map_trait_name.clone(),
695 impl_span.clone(),
696 map_trait_decl_span.clone(),
697 *map_type_id,
698 map_impl_type_parameters.clone(),
699 Self::filter_dummy_methods(
700 map_trait_items,
701 *type_id,
702 *map_type_id,
703 engines,
704 ),
705 engines,
706 );
707 }
708 },
709 );
710 }
711 trait_map
712 }
713
714 fn filter_dummy_methods(
715 map_trait_items: &TraitItems,
716 type_id: TypeId,
717 map_type_id: TypeId,
718 engines: &Engines,
719 ) -> TraitItems {
720 let mut insertable = true;
721 if let TypeInfo::UnknownGeneric {
722 is_from_type_parameter,
723 ..
724 } = *engines.te().get(map_type_id)
725 {
726 insertable = !is_from_type_parameter
727 || matches!(*engines.te().get(type_id), TypeInfo::UnknownGeneric { .. });
728 }
729
730 map_trait_items
731 .iter()
732 .filter_map(|(name, item)| match item {
733 ResolvedTraitImplItem::Parsed(_item) => todo!(),
734 ResolvedTraitImplItem::Typed(item) => match item {
735 ty::TyTraitItem::Fn(decl_ref) => {
736 let decl = (*engines.de().get(decl_ref.id())).clone();
737 if decl.is_trait_method_dummy && !insertable {
738 None
739 } else {
740 Some((
741 name.clone(),
742 ResolvedTraitImplItem::Typed(TyImplItem::Fn(decl_ref.clone())),
743 ))
744 }
745 }
746 ty::TyTraitItem::Constant(decl_ref) => Some((
747 name.clone(),
748 ResolvedTraitImplItem::Typed(TyImplItem::Constant(decl_ref.clone())),
749 )),
750 ty::TyTraitItem::Type(decl_ref) => Some((
751 name.clone(),
752 ResolvedTraitImplItem::Typed(TyImplItem::Type(decl_ref.clone())),
753 )),
754 },
755 })
756 .collect()
757 }
758
759 fn make_item_for_type_mapping(
760 engines: &Engines,
761 item: ResolvedTraitImplItem,
762 mut type_mapping: TypeSubstMap,
763 type_id: TypeId,
764 code_block_first_pass: CodeBlockFirstPass,
765 ) -> ResolvedTraitImplItem {
766 let decl_engine = engines.de();
767 match &item {
768 ResolvedTraitImplItem::Parsed(_item) => todo!(),
769 ResolvedTraitImplItem::Typed(item) => match item {
770 ty::TyTraitItem::Fn(decl_ref) => {
771 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
772 if let Some(decl_implementing_for_typeid) = decl.implementing_for_typeid {
773 type_mapping.insert(decl_implementing_for_typeid, type_id);
774 }
775 decl.subst(&SubstTypesContext::new(
776 engines,
777 &type_mapping,
778 matches!(code_block_first_pass, CodeBlockFirstPass::No),
779 ));
780
781 let new_ref = decl_engine
782 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref())
783 .with_parent(decl_engine, decl_ref.id().into());
784
785 ResolvedTraitImplItem::Typed(TyImplItem::Fn(new_ref))
786 }
787 ty::TyTraitItem::Constant(decl_ref) => {
788 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
789 decl.subst(&SubstTypesContext::new(
790 engines,
791 &type_mapping,
792 matches!(code_block_first_pass, CodeBlockFirstPass::No),
793 ));
794 let new_ref = decl_engine
795 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref());
796 ResolvedTraitImplItem::Typed(TyImplItem::Constant(new_ref))
797 }
798 ty::TyTraitItem::Type(decl_ref) => {
799 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
800 decl.subst(&SubstTypesContext::new(
801 engines,
802 &type_mapping,
803 matches!(code_block_first_pass, CodeBlockFirstPass::No),
804 ));
805 let new_ref = decl_engine
806 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref());
807 ResolvedTraitImplItem::Typed(TyImplItem::Type(new_ref))
808 }
809 },
810 }
811 }
812
813 pub(crate) fn get_items_for_type(
823 module: &Module,
824 engines: &Engines,
825 type_id: TypeId,
826 ) -> Vec<ResolvedTraitImplItem> {
827 TraitMap::get_items_and_trait_key_for_type(module, engines, type_id)
828 .iter()
829 .map(|i| i.0.clone())
830 .collect::<Vec<_>>()
831 }
832
833 fn get_items_and_trait_key_for_type(
834 module: &Module,
835 engines: &Engines,
836 type_id: TypeId,
837 ) -> Vec<(ResolvedTraitImplItem, TraitKey)> {
838 let type_engine = engines.te();
839 let unify_check = UnifyCheck::constraint_subset(engines);
840
841 let type_id = engines.te().get_unaliased_type_id(type_id);
842
843 let mut items = vec![];
844 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
846 return items;
847 }
848
849 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
850 lexical_scope.items.implemented_traits.for_each_impls(
851 engines,
852 type_id,
853 true,
854 |entry| {
855 if unify_check.check(type_id, entry.key.type_id) {
856 let trait_items = Self::filter_dummy_methods(
857 &entry.value.trait_items,
858 type_id,
859 entry.key.type_id,
860 engines,
861 )
862 .values()
863 .cloned()
864 .map(|i| (i, entry.key.clone()))
865 .collect::<Vec<_>>();
866
867 items.extend(trait_items);
868 }
869 },
870 );
871
872 Ok(None::<()>)
873 });
874 items
875 }
876
877 pub fn get_impl_spans_for_type(
887 module: &Module,
888 engines: &Engines,
889 type_id: &TypeId,
890 ) -> Vec<Span> {
891 let type_engine = engines.te();
892 let unify_check = UnifyCheck::constraint_subset(engines);
893
894 let type_id = &engines.te().get_unaliased_type_id(*type_id);
895
896 let mut spans = vec![];
897 if matches!(&*type_engine.get(*type_id), TypeInfo::ErrorRecovery(_)) {
899 return spans;
900 }
901 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
902 lexical_scope.items.implemented_traits.for_each_impls(
903 engines,
904 *type_id,
905 false,
906 |entry| {
907 if unify_check.check(*type_id, entry.key.type_id) {
908 spans.push(entry.value.impl_span.clone());
909 }
910 },
911 );
912
913 Ok(None::<()>)
914 });
915
916 spans
917 }
918
919 pub fn get_impl_spans_for_decl(
921 module: &Module,
922 engines: &Engines,
923 ty_decl: &TyDecl,
924 ) -> Vec<Span> {
925 let handler = Handler::default();
926 ty_decl
927 .return_type(&handler, engines)
928 .map(|type_id| TraitMap::get_impl_spans_for_type(module, engines, &type_id))
929 .unwrap_or_default()
930 }
931
932 pub fn get_impl_spans_for_trait_name(module: &Module, trait_name: &CallPath) -> Vec<Span> {
935 let mut spans = vec![];
936 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
937 spans.push(
938 lexical_scope
939 .items
940 .implemented_traits
941 .trait_impls
942 .values()
943 .map(|impls| {
944 impls
945 .iter()
946 .filter_map(|entry| {
947 let map_trait_name = CallPath {
948 prefixes: entry.key.name.prefixes.clone(),
949 suffix: entry.key.name.suffix.name.clone(),
950 callpath_type: entry.key.name.callpath_type,
951 };
952 if &map_trait_name == trait_name {
953 Some(entry.value.impl_span.clone())
954 } else {
955 None
956 }
957 })
958 .collect::<Vec<Span>>()
959 })
960 .collect::<Vec<Vec<Span>>>()
961 .concat(),
962 );
963 Ok(None::<()>)
964 });
965
966 spans.concat()
967 }
968
969 pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments(
980 module: &Module,
981 engines: &Engines,
982 type_id: TypeId,
983 trait_name: &CallPath,
984 trait_type_args: &[TypeArgument],
985 ) -> Vec<ResolvedTraitImplItem> {
986 let type_id = engines.te().get_unaliased_type_id(type_id);
987
988 let type_engine = engines.te();
989 let unify_check = UnifyCheck::constraint_subset(engines);
990 let mut items = vec![];
991 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
993 return items;
994 }
995 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
996 lexical_scope
997 .items
998 .implemented_traits
999 .for_each_impls(engines, type_id, false, |e| {
1000 let map_trait_name = CallPath {
1001 prefixes: e.key.name.prefixes.clone(),
1002 suffix: e.key.name.suffix.name.clone(),
1003 callpath_type: e.key.name.callpath_type,
1004 };
1005 if &map_trait_name == trait_name
1006 && unify_check.check(type_id, e.key.type_id)
1007 && trait_type_args.len() == e.key.name.suffix.args.len()
1008 && trait_type_args
1009 .iter()
1010 .zip(e.key.name.suffix.args.iter())
1011 .all(|(t1, t2)| unify_check.check(t1.type_id, t2.type_id))
1012 {
1013 let type_mapping =
1014 TypeSubstMap::from_superset_and_subset(engines, e.key.type_id, type_id);
1015
1016 let mut trait_items = Self::filter_dummy_methods(
1017 &e.value.trait_items,
1018 type_id,
1019 e.key.type_id,
1020 engines,
1021 )
1022 .values()
1023 .cloned()
1024 .map(|i| {
1025 Self::make_item_for_type_mapping(
1026 engines,
1027 i,
1028 type_mapping.clone(),
1029 type_id,
1030 CodeBlockFirstPass::No,
1031 )
1032 })
1033 .collect::<Vec<_>>();
1034
1035 items.append(&mut trait_items);
1036 }
1037 });
1038 Ok(None::<()>)
1039 });
1040 items
1041 }
1042
1043 pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments_typed(
1054 module: &Module,
1055 engines: &Engines,
1056 type_id: TypeId,
1057 trait_name: &CallPath,
1058 trait_type_args: &[TypeArgument],
1059 ) -> Vec<ty::TyTraitItem> {
1060 TraitMap::get_items_for_type_and_trait_name_and_trait_type_arguments(
1061 module,
1062 engines,
1063 type_id,
1064 trait_name,
1065 trait_type_args,
1066 )
1067 .into_iter()
1068 .map(|item| item.expect_typed())
1069 .collect::<Vec<_>>()
1070 }
1071
1072 pub(crate) fn get_trait_names_and_type_arguments_for_type(
1073 module: &Module,
1074 engines: &Engines,
1075 type_id: TypeId,
1076 ) -> Vec<(CallPath, Vec<TypeArgument>)> {
1077 let type_id = engines.te().get_unaliased_type_id(type_id);
1078
1079 let type_engine = engines.te();
1080 let unify_check = UnifyCheck::constraint_subset(engines);
1081 let mut trait_names = vec![];
1082 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1084 return trait_names;
1085 }
1086 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1087 lexical_scope.items.implemented_traits.for_each_impls(
1088 engines,
1089 type_id,
1090 false,
1091 |entry| {
1092 if unify_check.check(type_id, entry.key.type_id) {
1093 let trait_call_path = CallPath {
1094 prefixes: entry.key.name.prefixes.clone(),
1095 suffix: entry.key.name.suffix.name.clone(),
1096 callpath_type: entry.key.name.callpath_type,
1097 };
1098 trait_names.push((trait_call_path, entry.key.name.suffix.args.clone()));
1099 }
1100 },
1101 );
1102 Ok(None::<()>)
1103 });
1104 trait_names
1105 }
1106
1107 pub(crate) fn get_trait_item_for_type(
1108 module: &Module,
1109 handler: &Handler,
1110 engines: &Engines,
1111 symbol: &Ident,
1112 type_id: TypeId,
1113 as_trait: Option<CallPath>,
1114 ) -> Result<ResolvedTraitImplItem, ErrorEmitted> {
1115 let type_id = engines.te().get_unaliased_type_id(type_id);
1116
1117 let mut candidates = HashMap::<String, ResolvedTraitImplItem>::new();
1118 for (trait_item, trait_key) in
1119 TraitMap::get_items_and_trait_key_for_type(module, engines, type_id)
1120 {
1121 match trait_item {
1122 ResolvedTraitImplItem::Parsed(impl_item) => match impl_item {
1123 ImplItem::Fn(fn_ref) => {
1124 let decl = engines.pe().get_function(&fn_ref);
1125 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1126 if decl.name.as_str() == symbol.as_str()
1127 && (as_trait.is_none()
1128 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1129 {
1130 candidates.insert(
1131 trait_call_path_string,
1132 ResolvedTraitImplItem::Parsed(ImplItem::Fn(fn_ref)),
1133 );
1134 }
1135 }
1136 ImplItem::Constant(const_ref) => {
1137 let decl = engines.pe().get_constant(&const_ref);
1138 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1139 if decl.name.as_str() == symbol.as_str()
1140 && (as_trait.is_none()
1141 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1142 {
1143 candidates.insert(
1144 trait_call_path_string,
1145 ResolvedTraitImplItem::Parsed(ImplItem::Constant(const_ref)),
1146 );
1147 }
1148 }
1149 ImplItem::Type(type_ref) => {
1150 let decl = engines.pe().get_trait_type(&type_ref);
1151 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1152 if decl.name.as_str() == symbol.as_str()
1153 && (as_trait.is_none()
1154 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1155 {
1156 candidates.insert(
1157 trait_call_path_string,
1158 ResolvedTraitImplItem::Parsed(ImplItem::Type(type_ref)),
1159 );
1160 }
1161 }
1162 },
1163 ResolvedTraitImplItem::Typed(ty_impl_item) => match ty_impl_item {
1164 ty::TyTraitItem::Fn(fn_ref) => {
1165 let decl = engines.de().get_function(&fn_ref);
1166 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1167 if decl.name.as_str() == symbol.as_str()
1168 && (as_trait.is_none()
1169 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1170 {
1171 candidates.insert(
1172 trait_call_path_string,
1173 ResolvedTraitImplItem::Typed(TyTraitItem::Fn(fn_ref)),
1174 );
1175 }
1176 }
1177 ty::TyTraitItem::Constant(const_ref) => {
1178 let decl = engines.de().get_constant(&const_ref);
1179 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1180 if decl.call_path.suffix.as_str() == symbol.as_str()
1181 && (as_trait.is_none()
1182 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1183 {
1184 candidates.insert(
1185 trait_call_path_string,
1186 ResolvedTraitImplItem::Typed(TyTraitItem::Constant(const_ref)),
1187 );
1188 }
1189 }
1190 ty::TyTraitItem::Type(type_ref) => {
1191 let decl = engines.de().get_type(&type_ref);
1192 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1193 if decl.name.as_str() == symbol.as_str()
1194 && (as_trait.is_none()
1195 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1196 {
1197 candidates.insert(
1198 trait_call_path_string,
1199 ResolvedTraitImplItem::Typed(TyTraitItem::Type(type_ref)),
1200 );
1201 }
1202 }
1203 },
1204 }
1205 }
1206
1207 match candidates.len().cmp(&1) {
1208 Ordering::Greater => Err(handler.emit_err(
1209 CompileError::MultipleApplicableItemsInScope {
1210 item_name: symbol.as_str().to_string(),
1211 item_kind: "item".to_string(),
1212 as_traits: candidates
1213 .keys()
1214 .map(|k| {
1215 (
1216 k.clone()
1217 .split("::")
1218 .collect::<Vec<_>>()
1219 .last()
1220 .unwrap()
1221 .to_string(),
1222 engines.help_out(type_id).to_string(),
1223 )
1224 })
1225 .collect::<Vec<_>>(),
1226 span: symbol.span(),
1227 },
1228 )),
1229 Ordering::Less => Err(handler.emit_err(CompileError::SymbolNotFound {
1230 name: symbol.clone(),
1231 span: symbol.span(),
1232 })),
1233 Ordering::Equal => Ok(candidates.values().next().unwrap().clone()),
1234 }
1235 }
1236
1237 #[allow(clippy::too_many_arguments)]
1239 pub(crate) fn check_if_trait_constraints_are_satisfied_for_type(
1240 handler: &Handler,
1241 module: &mut Module,
1242 type_id: TypeId,
1243 constraints: &[TraitConstraint],
1244 access_span: &Span,
1245 engines: &Engines,
1246 ) -> Result<(), ErrorEmitted> {
1247 let type_engine = engines.te();
1248
1249 let type_id = type_engine.get_unaliased_type_id(type_id);
1250
1251 type_engine.decay_numeric(handler, engines, type_id, access_span)?;
1253
1254 if constraints.is_empty() {
1255 return Ok(());
1256 }
1257
1258 let mut hasher = DefaultHasher::default();
1260 type_id.hash(&mut hasher);
1261 for c in constraints {
1262 c.hash(&mut hasher, engines);
1263 }
1264 let hash = hasher.finish();
1265
1266 {
1267 let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1268 if trait_map.satisfied_cache.contains(&hash) {
1269 return Ok(());
1270 }
1271 }
1272
1273 let all_impld_traits: BTreeSet<(Ident, TypeId)> =
1274 Self::get_all_implemented_traits(module, type_id, engines);
1275
1276 match Self::check_if_trait_constraints_are_satisfied_for_type_inner(
1278 handler,
1279 type_id,
1280 constraints,
1281 access_span,
1282 engines,
1283 all_impld_traits,
1284 ) {
1285 Ok(()) => {
1286 let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1287 trait_map.satisfied_cache.insert(hash);
1288 Ok(())
1289 }
1290 r => r,
1291 }
1292 }
1293
1294 fn get_all_implemented_traits(
1295 module: &Module,
1296 type_id: TypeId,
1297 engines: &Engines,
1298 ) -> BTreeSet<(Ident, TypeId)> {
1299 let mut all_impld_traits: BTreeSet<(Ident, TypeId)> = Default::default();
1300 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1301 all_impld_traits.extend(
1302 lexical_scope
1303 .items
1304 .implemented_traits
1305 .get_implemented_traits(type_id, engines),
1306 );
1307 Ok(None::<()>)
1308 });
1309 all_impld_traits
1310 }
1311
1312 fn get_implemented_traits(
1313 &self,
1314 type_id: TypeId,
1315 engines: &Engines,
1316 ) -> BTreeSet<(Ident, TypeId)> {
1317 let type_engine = engines.te();
1318 let unify_check = UnifyCheck::constraint_subset(engines);
1319 let mut all_impld_traits = BTreeSet::<(Ident, TypeId)>::new();
1320 self.for_each_impls(engines, type_id, true, |e| {
1321 let key = &e.key;
1322 let suffix = &key.name.suffix;
1323 if unify_check.check(type_id, key.type_id) {
1324 let map_trait_type_id = type_engine.new_custom(
1325 engines,
1326 suffix.name.clone().into(),
1327 if suffix.args.is_empty() {
1328 None
1329 } else {
1330 Some(suffix.args.to_vec())
1331 },
1332 );
1333 all_impld_traits.insert((suffix.name.clone(), map_trait_type_id));
1334 }
1335 });
1336 all_impld_traits
1337 }
1338
1339 #[allow(clippy::too_many_arguments)]
1340 fn check_if_trait_constraints_are_satisfied_for_type_inner(
1341 handler: &Handler,
1342 type_id: TypeId,
1343 constraints: &[TraitConstraint],
1344 access_span: &Span,
1345 engines: &Engines,
1346 all_impld_traits: BTreeSet<(Ident, TypeId)>,
1347 ) -> Result<(), ErrorEmitted> {
1348 let type_engine = engines.te();
1349 let unify_check = UnifyCheck::constraint_subset(engines);
1350
1351 let required_traits: BTreeSet<(Ident, TypeId)> = constraints
1352 .iter()
1353 .map(|c| {
1354 let TraitConstraint {
1355 trait_name: constraint_trait_name,
1356 type_arguments: constraint_type_arguments,
1357 } = c;
1358 let constraint_type_id = type_engine.new_custom(
1359 engines,
1360 constraint_trait_name.suffix.clone().into(),
1361 if constraint_type_arguments.is_empty() {
1362 None
1363 } else {
1364 Some(constraint_type_arguments.clone())
1365 },
1366 );
1367 (c.trait_name.suffix.clone(), constraint_type_id)
1368 })
1369 .collect();
1370
1371 let traits_not_found: BTreeSet<(BaseIdent, TypeId)> = required_traits
1372 .into_iter()
1373 .filter(|(required_trait_name, required_trait_type_id)| {
1374 !all_impld_traits
1375 .iter()
1376 .any(|(trait_name, constraint_type_id)| {
1377 trait_name == required_trait_name
1378 && unify_check.check(*constraint_type_id, *required_trait_type_id)
1379 })
1380 })
1381 .collect();
1382
1383 handler.scope(|handler| {
1384 for (trait_name, constraint_type_id) in traits_not_found.iter() {
1385 let mut type_arguments_string = "".to_string();
1386 if let TypeInfo::Custom {
1387 qualified_call_path: _,
1388 type_arguments: Some(type_arguments),
1389 } = &*type_engine.get(*constraint_type_id)
1390 {
1391 type_arguments_string = format!("<{}>", engines.help_out(type_arguments));
1392 }
1393
1394 handler.emit_err(CompileError::TraitConstraintNotSatisfied {
1396 type_id: type_id.index(),
1397 ty: engines.help_out(type_id).to_string(),
1398 trait_name: format!("{}{}", trait_name, type_arguments_string),
1399 span: access_span.clone(),
1400 });
1401 }
1402
1403 Ok(())
1404 })
1405 }
1406
1407 pub fn get_trait_constraints_are_satisfied_for_types(
1408 module: &Module,
1409 _handler: &Handler,
1410 type_id: TypeId,
1411 constraints: &[TraitConstraint],
1412 engines: &Engines,
1413 ) -> Result<Vec<(TypeId, String)>, ErrorEmitted> {
1414 let type_id = engines.te().get_unaliased_type_id(type_id);
1415
1416 let _decl_engine = engines.de();
1417 let unify_check = UnifyCheck::coercion(engines);
1418 let unify_check_equality = UnifyCheck::constraint_subset(engines);
1419
1420 let mut impld_traits_type_ids: Vec<Vec<(TypeId, String)>> = vec![];
1421 let _ = module.walk_scope_chain_early_return(|lexical_scope| {
1422 lexical_scope
1423 .items
1424 .implemented_traits
1425 .for_each_impls(engines, type_id, true, |e| {
1426 let mut traits: Vec<(TypeId, String)> = vec![];
1427
1428 let key = &e.key;
1429 for constraint in constraints {
1430 if key.name.suffix.name == constraint.trait_name.suffix
1431 && key
1432 .name
1433 .suffix
1434 .args
1435 .iter()
1436 .zip(constraint.type_arguments.iter())
1437 .all(|(a1, a2)| unify_check_equality.check(a1.type_id, a2.type_id))
1438 && unify_check.check(type_id, key.type_id)
1439 {
1440 let name_type_args = if !key.name.suffix.args.is_empty() {
1441 format!("<{}>", engines.help_out(key.name.suffix.args.clone()))
1442 } else {
1443 "".to_string()
1444 };
1445 let name =
1446 format!("{}{}", key.name.suffix.name.as_str(), name_type_args);
1447 traits.push((key.type_id, name));
1448 break;
1449 }
1450 }
1451 impld_traits_type_ids.push(traits);
1452 });
1453
1454 Ok(None::<()>)
1455 });
1456 Ok(impld_traits_type_ids.concat())
1457 }
1458
1459 fn get_impls_mut(&mut self, engines: &Engines, type_id: TypeId) -> &mut Vec<TraitEntry> {
1460 let type_root_filter = Self::get_type_root_filter(engines, type_id);
1461 if !self.trait_impls.contains_key(&type_root_filter) {
1462 self.trait_impls
1463 .insert(type_root_filter.clone(), Vec::new());
1464 }
1465
1466 self.trait_impls.get_mut(&type_root_filter).unwrap()
1467 }
1468
1469 pub(crate) fn for_each_impls<F>(
1470 &self,
1471 engines: &Engines,
1472 type_id: TypeId,
1473 include_placeholder: bool,
1474 mut callback: F,
1475 ) where
1476 F: FnMut(&TraitEntry),
1477 {
1478 let type_root_filter = Self::get_type_root_filter(engines, type_id);
1479 self.trait_impls
1480 .get(&type_root_filter)
1481 .iter()
1482 .for_each(|vec| vec.iter().for_each(&mut callback));
1483 if include_placeholder && type_root_filter != TypeRootFilter::Placeholder {
1484 self.trait_impls
1485 .get(&TypeRootFilter::Placeholder)
1486 .iter()
1487 .for_each(|vec| vec.iter().for_each(&mut callback));
1488 }
1489 }
1490
1491 fn get_type_root_filter(engines: &Engines, type_id: TypeId) -> TypeRootFilter {
1494 use TypeInfo::*;
1495 match &*engines.te().get(type_id) {
1496 Unknown => TypeRootFilter::Unknown,
1497 Never => TypeRootFilter::Never,
1498 UnknownGeneric { .. } | Placeholder(_) => TypeRootFilter::Placeholder,
1499 TypeParam(_param) => unreachable!(),
1500 StringSlice => TypeRootFilter::StringSlice,
1501 StringArray(x) => TypeRootFilter::StringArray(x.val()),
1502 UnsignedInteger(x) => match x {
1503 IntegerBits::Eight => TypeRootFilter::U8,
1504 IntegerBits::Sixteen => TypeRootFilter::U16,
1505 IntegerBits::ThirtyTwo => TypeRootFilter::U32,
1506 IntegerBits::SixtyFour => TypeRootFilter::U64,
1507 IntegerBits::V256 => TypeRootFilter::U256,
1508 },
1509 Boolean => TypeRootFilter::Bool,
1510 Custom {
1511 qualified_call_path: call_path,
1512 ..
1513 } => TypeRootFilter::Custom(call_path.call_path.suffix.to_string()),
1514 B256 => TypeRootFilter::B256,
1515 Numeric => TypeRootFilter::U64, Contract => TypeRootFilter::Contract,
1517 ErrorRecovery(_) => TypeRootFilter::ErrorRecovery,
1518 Tuple(fields) => TypeRootFilter::Tuple(fields.len()),
1519 UntypedEnum(decl_id) => TypeRootFilter::Enum(*decl_id),
1520 UntypedStruct(decl_id) => TypeRootFilter::Struct(*decl_id),
1521 Enum(decl_id) => {
1522 TypeRootFilter::Enum(engines.de().get_parsed_decl_id(decl_id).unwrap())
1524 }
1525 Struct(decl_id) => {
1526 TypeRootFilter::Struct(engines.de().get_parsed_decl_id(decl_id).unwrap())
1528 }
1529 ContractCaller { abi_name, .. } => TypeRootFilter::ContractCaller(abi_name.to_string()),
1530 Array(_, _) => TypeRootFilter::Array,
1531 RawUntypedPtr => TypeRootFilter::RawUntypedPtr,
1532 RawUntypedSlice => TypeRootFilter::RawUntypedSlice,
1533 Ptr(_) => TypeRootFilter::Ptr,
1534 Slice(_) => TypeRootFilter::Slice,
1535 Alias { ty, .. } => Self::get_type_root_filter(engines, ty.type_id),
1536 TraitType { name, .. } => TypeRootFilter::TraitType(name.to_string()),
1537 Ref {
1538 referenced_type, ..
1539 } => Self::get_type_root_filter(engines, referenced_type.type_id),
1540 }
1541 }
1542}