1use std::{
2 cmp::Ordering,
3 collections::{BTreeSet, HashMap, HashSet},
4 fmt,
5 hash::{DefaultHasher, Hash, Hasher},
6 sync::Arc,
7};
8
9use sway_error::{
10 error::CompileError,
11 handler::{ErrorEmitted, Handler},
12};
13use sway_types::{integer_bits::IntegerBits, BaseIdent, Ident, Span, Spanned};
14
15use crate::{
16 decl_engine::{
17 parsed_id::ParsedDeclId, DeclEngineGet, DeclEngineGetParsedDeclId, DeclEngineInsert,
18 },
19 engine_threading::*,
20 language::{
21 parsed::{EnumDeclaration, ImplItem, StructDeclaration},
22 ty::{self, TyDecl, TyImplItem, TyTraitItem},
23 CallPath,
24 },
25 type_system::{SubstTypes, TypeId},
26 IncludeSelf, SubstTypesContext, TraitConstraint, TypeArgument, TypeEngine, TypeInfo,
27 TypeSubstMap, UnifyCheck,
28};
29
30use super::Module;
31
32#[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 = HashMap<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 = HashMap<TypeRootFilter, Vec<TraitEntry>>;
170
171#[derive(Clone, Hash, Eq, PartialOrd, Ord, PartialEq, Debug)]
172pub(crate) enum TypeRootFilter {
173 Unknown,
174 Never,
175 Placeholder,
176 StringSlice,
177 StringArray(usize),
178 U8,
179 U16,
180 U32,
181 U64,
182 U256,
183 Bool,
184 Custom(String),
185 B256,
186 Contract,
187 ErrorRecovery,
188 Tuple(usize),
189 Enum(ParsedDeclId<EnumDeclaration>),
190 Struct(ParsedDeclId<StructDeclaration>),
191 ContractCaller(String),
192 Array,
193 RawUntypedPtr,
194 RawUntypedSlice,
195 Ptr,
196 Slice,
197 TraitType(String),
198}
199
200#[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 = HashMap::new();
247 for item in items.iter() {
248 match item {
249 ResolvedTraitImplItem::Parsed(_) => todo!(),
250 ResolvedTraitImplItem::Typed(ty_item) => match ty_item {
251 TyImplItem::Fn(decl_ref) => {
252 if trait_items
253 .insert(decl_ref.name().clone().to_string(), item.clone())
254 .is_some()
255 {
256 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 let mut names = trait_items.keys().clone().collect::<Vec<_>>();
385 names.sort();
386 for name in names {
387 let item = &trait_items[name];
388 match item {
389 ResolvedTraitImplItem::Parsed(_item) => todo!(),
390 ResolvedTraitImplItem::Typed(item) => match item {
391 ty::TyTraitItem::Fn(decl_ref) => {
392 if let Some(existing_item) = map_trait_items.get(name) {
393 handler.emit_err(
394 CompileError::DuplicateDeclDefinedForType {
395 decl_kind: "method".into(),
396 decl_name: decl_ref.name().to_string(),
397 type_implementing_for: engines
398 .help_out(type_id)
399 .to_string(),
400 type_implementing_for_unaliased: engines
401 .help_out(unaliased_type_id)
402 .to_string(),
403 existing_impl_span: existing_item
404 .span(engines)
405 .clone(),
406 second_impl_span: decl_ref.name().span(),
407 },
408 );
409 }
410 }
411 ty::TyTraitItem::Constant(decl_ref) => {
412 if let Some(existing_item) = map_trait_items.get(name) {
413 handler.emit_err(
414 CompileError::DuplicateDeclDefinedForType {
415 decl_kind: "constant".into(),
416 decl_name: decl_ref.name().to_string(),
417 type_implementing_for: engines
418 .help_out(type_id)
419 .to_string(),
420 type_implementing_for_unaliased: engines
421 .help_out(unaliased_type_id)
422 .to_string(),
423 existing_impl_span: existing_item
424 .span(engines)
425 .clone(),
426 second_impl_span: decl_ref.name().span(),
427 },
428 );
429 }
430 }
431 ty::TyTraitItem::Type(decl_ref) => {
432 if let Some(existing_item) = map_trait_items.get(name) {
433 handler.emit_err(
434 CompileError::DuplicateDeclDefinedForType {
435 decl_kind: "type".into(),
436 decl_name: decl_ref.name().to_string(),
437 type_implementing_for: engines
438 .help_out(type_id)
439 .to_string(),
440 type_implementing_for_unaliased: engines
441 .help_out(unaliased_type_id)
442 .to_string(),
443 existing_impl_span: existing_item
444 .span(engines)
445 .clone(),
446 second_impl_span: decl_ref.name().span(),
447 },
448 );
449 }
450 }
451 },
452 }
453 }
454 }
455 }
456 let trait_name: TraitName = Arc::new(CallPath {
457 prefixes: trait_name.prefixes,
458 suffix: TraitSuffix {
459 name: trait_name.suffix,
460 args: trait_type_args,
461 },
462 callpath_type: trait_name.callpath_type,
463 });
464
465 self.insert_inner(
467 trait_name,
468 impl_span.clone(),
469 trait_decl_span,
470 unaliased_type_id,
471 impl_type_parameters,
472 trait_items,
473 engines,
474 );
475
476 Ok(())
477 })
478 }
479
480 #[allow(clippy::too_many_arguments)]
481 fn insert_inner(
482 &mut self,
483 trait_name: TraitName,
484 impl_span: Span,
485 trait_decl_span: Option<Span>,
486 type_id: TypeId,
487 impl_type_parameters: Vec<TypeId>,
488 trait_methods: TraitItems,
489 engines: &Engines,
490 ) {
491 let key = TraitKey {
492 name: trait_name,
493 type_id,
494 trait_decl_span,
495 impl_type_parameters,
496 };
497 let value = TraitValue {
498 trait_items: trait_methods,
499 impl_span,
500 };
501 let entry = TraitEntry { key, value };
502 let mut trait_impls: TraitImpls = HashMap::<TypeRootFilter, Vec<TraitEntry>>::new();
503 let type_root_filter = Self::get_type_root_filter(engines, type_id);
504 let impls_vector = vec![entry];
505 trait_impls.insert(type_root_filter, impls_vector);
506
507 let trait_map = TraitMap {
508 trait_impls,
509 satisfied_cache: HashSet::default(),
510 };
511
512 self.extend(trait_map, engines);
513 }
514
515 pub(crate) fn extend(&mut self, other: TraitMap, engines: &Engines) {
518 let mut impls_keys = other.trait_impls.keys().clone().collect::<Vec<_>>();
519 impls_keys.sort();
520 for impls_key in impls_keys {
521 let oe_vec = &other.trait_impls[impls_key];
522 let self_vec = if let Some(self_vec) = self.trait_impls.get_mut(impls_key) {
523 self_vec
524 } else {
525 self.trait_impls
526 .insert(impls_key.clone(), Vec::<TraitEntry>::new());
527 self.trait_impls.get_mut(impls_key).unwrap()
528 };
529
530 for oe in oe_vec.iter() {
531 let pos = self_vec.binary_search_by(|se| {
532 se.key.cmp(&oe.key, &OrdWithEnginesContext::new(engines))
533 });
534
535 match pos {
536 Ok(pos) => self_vec[pos]
537 .value
538 .trait_items
539 .extend(oe.value.trait_items.clone()),
540 Err(pos) => self_vec.insert(pos, oe.clone()),
541 }
542 }
543 }
544 }
545
546 pub(crate) fn filter_by_trait_decl_span(&self, trait_decl_span: Span) -> TraitMap {
549 let mut trait_map = TraitMap::default();
550 let mut keys = self.trait_impls.keys().clone().collect::<Vec<_>>();
551 keys.sort();
552 for key in keys {
553 let vec = &self.trait_impls[key];
554 for entry in vec {
555 if entry.key.trait_decl_span.as_ref() == Some(&trait_decl_span) {
556 let trait_map_vec =
557 if let Some(trait_map_vec) = trait_map.trait_impls.get_mut(key) {
558 trait_map_vec
559 } else {
560 trait_map
561 .trait_impls
562 .insert(key.clone(), Vec::<TraitEntry>::new());
563 trait_map.trait_impls.get_mut(key).unwrap()
564 };
565
566 trait_map_vec.push(entry.clone());
567 }
568 }
569 }
570 trait_map
571 }
572
573 pub(crate) fn filter_by_type_item_import(
632 &self,
633 type_id: TypeId,
634 engines: &Engines,
635 ) -> TraitMap {
636 let unify_checker = UnifyCheck::constraint_subset(engines);
637 let unify_checker_for_item_import = UnifyCheck::non_generic_constraint_subset(engines);
638
639 let decider = |left: TypeId, right: TypeId| {
641 unify_checker.check(left, right) || unify_checker_for_item_import.check(right, left)
642 };
643 let mut trait_map = self.filter_by_type_inner(engines, vec![type_id], decider);
644 let all_types = type_id
645 .extract_inner_types(engines, IncludeSelf::No)
646 .into_iter()
647 .collect::<Vec<_>>();
648 let decider2 = |left: TypeId, right: TypeId| unify_checker.check(left, right);
650
651 trait_map.extend(
652 self.filter_by_type_inner(engines, all_types, decider2),
653 engines,
654 );
655 trait_map
656 }
657
658 fn filter_by_type_inner(
659 &self,
660 engines: &Engines,
661 mut all_types: Vec<TypeId>,
662 decider: impl Fn(TypeId, TypeId) -> bool,
663 ) -> TraitMap {
664 let type_engine = engines.te();
665 let mut trait_map = TraitMap::default();
666 for type_id in all_types.iter_mut() {
667 let type_info = type_engine.get(*type_id);
668 let impls = self.get_impls(engines, *type_id, true);
669 for TraitEntry {
670 key:
671 TraitKey {
672 name: map_trait_name,
673 type_id: map_type_id,
674 trait_decl_span: map_trait_decl_span,
675 impl_type_parameters: map_impl_type_parameters,
676 },
677 value:
678 TraitValue {
679 trait_items: map_trait_items,
680 impl_span,
681 },
682 } in impls.iter()
683 {
684 if !type_engine.is_type_changeable(engines, &type_info) && *type_id == *map_type_id
685 {
686 trait_map.insert_inner(
687 map_trait_name.clone(),
688 impl_span.clone(),
689 map_trait_decl_span.clone(),
690 *type_id,
691 map_impl_type_parameters.clone(),
692 map_trait_items.clone(),
693 engines,
694 );
695 } else if decider(*type_id, *map_type_id) {
696 trait_map.insert_inner(
697 map_trait_name.clone(),
698 impl_span.clone(),
699 map_trait_decl_span.clone(),
700 *map_type_id,
701 map_impl_type_parameters.clone(),
702 Self::filter_dummy_methods(
703 map_trait_items.clone(),
704 *type_id,
705 *map_type_id,
706 engines,
707 ),
708 engines,
709 );
710 }
711 }
712 }
713 trait_map
714 }
715
716 fn filter_dummy_methods(
717 map_trait_items: TraitItems,
718 type_id: TypeId,
719 map_type_id: TypeId,
720 engines: &Engines,
721 ) -> TraitItems {
722 let mut insertable = true;
723 if let TypeInfo::UnknownGeneric {
724 is_from_type_parameter,
725 ..
726 } = *engines.te().get(map_type_id)
727 {
728 insertable = !is_from_type_parameter
729 || matches!(*engines.te().get(type_id), TypeInfo::UnknownGeneric { .. });
730 }
731
732 map_trait_items
733 .clone()
734 .into_iter()
735 .filter_map(|(name, item)| match item {
736 ResolvedTraitImplItem::Parsed(_item) => todo!(),
737 ResolvedTraitImplItem::Typed(item) => match item {
738 ty::TyTraitItem::Fn(decl_ref) => {
739 let decl = (*engines.de().get(decl_ref.id())).clone();
740 if decl.is_trait_method_dummy && !insertable {
741 None
742 } else {
743 Some((name, ResolvedTraitImplItem::Typed(TyImplItem::Fn(decl_ref))))
744 }
745 }
746 ty::TyTraitItem::Constant(decl_ref) => Some((
747 name,
748 ResolvedTraitImplItem::Typed(TyImplItem::Constant(decl_ref)),
749 )),
750 ty::TyTraitItem::Type(decl_ref) => Some((
751 name,
752 ResolvedTraitImplItem::Typed(TyImplItem::Type(decl_ref)),
753 )),
754 },
755 })
756 .collect()
757 }
758
759 fn make_item_for_type_mapping(
760 engines: &Engines,
761 item: ResolvedTraitImplItem,
762 mut type_mapping: TypeSubstMap,
763 type_id: TypeId,
764 code_block_first_pass: CodeBlockFirstPass,
765 ) -> ResolvedTraitImplItem {
766 let decl_engine = engines.de();
767 match &item {
768 ResolvedTraitImplItem::Parsed(_item) => todo!(),
769 ResolvedTraitImplItem::Typed(item) => match item {
770 ty::TyTraitItem::Fn(decl_ref) => {
771 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
772 if let Some(decl_implementing_for_typeid) = decl.implementing_for_typeid {
773 type_mapping.insert(decl_implementing_for_typeid, type_id);
774 }
775 decl.subst(&SubstTypesContext::new(
776 engines,
777 &type_mapping,
778 matches!(code_block_first_pass, CodeBlockFirstPass::No),
779 ));
780
781 let new_ref = decl_engine
782 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref())
783 .with_parent(decl_engine, decl_ref.id().into());
784
785 ResolvedTraitImplItem::Typed(TyImplItem::Fn(new_ref))
786 }
787 ty::TyTraitItem::Constant(decl_ref) => {
788 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
789 decl.subst(&SubstTypesContext::new(
790 engines,
791 &type_mapping,
792 matches!(code_block_first_pass, CodeBlockFirstPass::No),
793 ));
794 let new_ref = decl_engine
795 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref());
796 ResolvedTraitImplItem::Typed(TyImplItem::Constant(new_ref))
797 }
798 ty::TyTraitItem::Type(decl_ref) => {
799 let mut decl = (*decl_engine.get(decl_ref.id())).clone();
800 decl.subst(&SubstTypesContext::new(
801 engines,
802 &type_mapping,
803 matches!(code_block_first_pass, CodeBlockFirstPass::No),
804 ));
805 let new_ref = decl_engine
806 .insert(decl, decl_engine.get_parsed_decl_id(decl_ref.id()).as_ref());
807 ResolvedTraitImplItem::Typed(TyImplItem::Type(new_ref))
808 }
809 },
810 }
811 }
812
813 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(|lexical_scope| {
850 let impls = lexical_scope
851 .items
852 .implemented_traits
853 .get_impls(engines, type_id, true);
854 for entry in impls {
855 if unify_check.check(type_id, entry.key.type_id) {
856 let trait_items = Self::filter_dummy_methods(
857 entry.value.trait_items,
858 type_id,
859 entry.key.type_id,
860 engines,
861 )
862 .values()
863 .cloned()
864 .map(|i| (i, entry.key.clone()))
865 .collect::<Vec<_>>();
866
867 items.extend(trait_items);
868 }
869 }
870 Ok(None::<()>)
871 });
872 items
873 }
874
875 pub fn get_impl_spans_for_type(
885 module: &Module,
886 engines: &Engines,
887 type_id: &TypeId,
888 ) -> Vec<Span> {
889 let type_engine = engines.te();
890 let unify_check = UnifyCheck::constraint_subset(engines);
891
892 let type_id = &engines.te().get_unaliased_type_id(*type_id);
893
894 let mut spans = vec![];
895 if matches!(&*type_engine.get(*type_id), TypeInfo::ErrorRecovery(_)) {
897 return spans;
898 }
899 let _ = module.walk_scope_chain(|lexical_scope| {
900 let impls = lexical_scope
901 .items
902 .implemented_traits
903 .get_impls(engines, *type_id, false);
904 for entry in impls {
905 if unify_check.check(*type_id, entry.key.type_id) {
906 spans.push(entry.value.impl_span.clone());
907 }
908 }
909 Ok(None::<()>)
910 });
911
912 spans
913 }
914
915 pub fn get_impl_spans_for_decl(
917 module: &Module,
918 engines: &Engines,
919 ty_decl: &TyDecl,
920 ) -> Vec<Span> {
921 let handler = Handler::default();
922 ty_decl
923 .return_type(&handler, engines)
924 .map(|type_id| TraitMap::get_impl_spans_for_type(module, engines, &type_id))
925 .unwrap_or_default()
926 }
927
928 pub fn get_impl_spans_for_trait_name(module: &Module, trait_name: &CallPath) -> Vec<Span> {
931 let mut spans = vec![];
932 let _ = module.walk_scope_chain(|lexical_scope| {
933 spans.push(
934 lexical_scope
935 .items
936 .implemented_traits
937 .trait_impls
938 .values()
939 .map(|impls| {
940 impls
941 .iter()
942 .filter_map(|entry| {
943 let map_trait_name = CallPath {
944 prefixes: entry.key.name.prefixes.clone(),
945 suffix: entry.key.name.suffix.name.clone(),
946 callpath_type: entry.key.name.callpath_type,
947 };
948 if &map_trait_name == trait_name {
949 Some(entry.value.impl_span.clone())
950 } else {
951 None
952 }
953 })
954 .collect::<Vec<Span>>()
955 })
956 .collect::<Vec<Vec<Span>>>()
957 .concat(),
958 );
959 Ok(None::<()>)
960 });
961
962 spans.concat()
963 }
964
965 pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments(
976 module: &Module,
977 engines: &Engines,
978 type_id: TypeId,
979 trait_name: &CallPath,
980 trait_type_args: &[TypeArgument],
981 ) -> Vec<ResolvedTraitImplItem> {
982 let type_id = engines.te().get_unaliased_type_id(type_id);
983
984 let type_engine = engines.te();
985 let unify_check = UnifyCheck::constraint_subset(engines);
986 let mut items = vec![];
987 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
989 return items;
990 }
991 let _ = module.walk_scope_chain(|lexical_scope| {
992 let impls = lexical_scope
993 .items
994 .implemented_traits
995 .get_impls(engines, type_id, false);
996 for e in impls {
997 let map_trait_name = CallPath {
998 prefixes: e.key.name.prefixes.clone(),
999 suffix: e.key.name.suffix.name.clone(),
1000 callpath_type: e.key.name.callpath_type,
1001 };
1002 if &map_trait_name == trait_name
1003 && unify_check.check(type_id, e.key.type_id)
1004 && trait_type_args.len() == e.key.name.suffix.args.len()
1005 && trait_type_args
1006 .iter()
1007 .zip(e.key.name.suffix.args.iter())
1008 .all(|(t1, t2)| unify_check.check(t1.type_id, t2.type_id))
1009 {
1010 let type_mapping =
1011 TypeSubstMap::from_superset_and_subset(engines, e.key.type_id, type_id);
1012
1013 let mut trait_items = Self::filter_dummy_methods(
1014 e.value.trait_items,
1015 type_id,
1016 e.key.type_id,
1017 engines,
1018 )
1019 .values()
1020 .cloned()
1021 .map(|i| {
1022 Self::make_item_for_type_mapping(
1023 engines,
1024 i,
1025 type_mapping.clone(),
1026 type_id,
1027 CodeBlockFirstPass::No,
1028 )
1029 })
1030 .collect::<Vec<_>>();
1031
1032 items.append(&mut trait_items);
1033 }
1034 }
1035 Ok(None::<()>)
1036 });
1037 items
1038 }
1039
1040 pub(crate) fn get_items_for_type_and_trait_name_and_trait_type_arguments_typed(
1051 module: &Module,
1052 engines: &Engines,
1053 type_id: TypeId,
1054 trait_name: &CallPath,
1055 trait_type_args: &[TypeArgument],
1056 ) -> Vec<ty::TyTraitItem> {
1057 TraitMap::get_items_for_type_and_trait_name_and_trait_type_arguments(
1058 module,
1059 engines,
1060 type_id,
1061 trait_name,
1062 trait_type_args,
1063 )
1064 .into_iter()
1065 .map(|item| item.expect_typed())
1066 .collect::<Vec<_>>()
1067 }
1068
1069 pub(crate) fn get_trait_names_and_type_arguments_for_type(
1070 module: &Module,
1071 engines: &Engines,
1072 type_id: TypeId,
1073 ) -> Vec<(CallPath, Vec<TypeArgument>)> {
1074 let type_id = engines.te().get_unaliased_type_id(type_id);
1075
1076 let type_engine = engines.te();
1077 let unify_check = UnifyCheck::constraint_subset(engines);
1078 let mut trait_names = vec![];
1079 if matches!(&*type_engine.get(type_id), TypeInfo::ErrorRecovery(_)) {
1081 return trait_names;
1082 }
1083 let _ = module.walk_scope_chain(|lexical_scope| {
1084 let impls = lexical_scope
1085 .items
1086 .implemented_traits
1087 .get_impls(engines, type_id, false);
1088 for entry in impls {
1089 if unify_check.check(type_id, entry.key.type_id) {
1090 let trait_call_path = CallPath {
1091 prefixes: entry.key.name.prefixes.clone(),
1092 suffix: entry.key.name.suffix.name.clone(),
1093 callpath_type: entry.key.name.callpath_type,
1094 };
1095 trait_names.push((trait_call_path, entry.key.name.suffix.args.clone()));
1096 }
1097 }
1098 Ok(None::<()>)
1099 });
1100 trait_names
1101 }
1102
1103 pub(crate) fn get_trait_item_for_type(
1104 module: &Module,
1105 handler: &Handler,
1106 engines: &Engines,
1107 symbol: &Ident,
1108 type_id: TypeId,
1109 as_trait: Option<CallPath>,
1110 ) -> Result<ResolvedTraitImplItem, ErrorEmitted> {
1111 let type_id = engines.te().get_unaliased_type_id(type_id);
1112
1113 let mut candidates = HashMap::<String, ResolvedTraitImplItem>::new();
1114 for (trait_item, trait_key) in
1115 TraitMap::get_items_and_trait_key_for_type(module, engines, type_id)
1116 {
1117 match trait_item {
1118 ResolvedTraitImplItem::Parsed(impl_item) => match impl_item {
1119 ImplItem::Fn(fn_ref) => {
1120 let decl = engines.pe().get_function(&fn_ref);
1121 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1122 if decl.name.as_str() == symbol.as_str()
1123 && (as_trait.is_none()
1124 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1125 {
1126 candidates.insert(
1127 trait_call_path_string,
1128 ResolvedTraitImplItem::Parsed(ImplItem::Fn(fn_ref)),
1129 );
1130 }
1131 }
1132 ImplItem::Constant(const_ref) => {
1133 let decl = engines.pe().get_constant(&const_ref);
1134 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1135 if decl.name.as_str() == symbol.as_str()
1136 && (as_trait.is_none()
1137 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1138 {
1139 candidates.insert(
1140 trait_call_path_string,
1141 ResolvedTraitImplItem::Parsed(ImplItem::Constant(const_ref)),
1142 );
1143 }
1144 }
1145 ImplItem::Type(type_ref) => {
1146 let decl = engines.pe().get_trait_type(&type_ref);
1147 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1148 if decl.name.as_str() == symbol.as_str()
1149 && (as_trait.is_none()
1150 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1151 {
1152 candidates.insert(
1153 trait_call_path_string,
1154 ResolvedTraitImplItem::Parsed(ImplItem::Type(type_ref)),
1155 );
1156 }
1157 }
1158 },
1159 ResolvedTraitImplItem::Typed(ty_impl_item) => match ty_impl_item {
1160 ty::TyTraitItem::Fn(fn_ref) => {
1161 let decl = engines.de().get_function(&fn_ref);
1162 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1163 if decl.name.as_str() == symbol.as_str()
1164 && (as_trait.is_none()
1165 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1166 {
1167 candidates.insert(
1168 trait_call_path_string,
1169 ResolvedTraitImplItem::Typed(TyTraitItem::Fn(fn_ref)),
1170 );
1171 }
1172 }
1173 ty::TyTraitItem::Constant(const_ref) => {
1174 let decl = engines.de().get_constant(&const_ref);
1175 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1176 if decl.call_path.suffix.as_str() == symbol.as_str()
1177 && (as_trait.is_none()
1178 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1179 {
1180 candidates.insert(
1181 trait_call_path_string,
1182 ResolvedTraitImplItem::Typed(TyTraitItem::Constant(const_ref)),
1183 );
1184 }
1185 }
1186 ty::TyTraitItem::Type(type_ref) => {
1187 let decl = engines.de().get_type(&type_ref);
1188 let trait_call_path_string = engines.help_out(&*trait_key.name).to_string();
1189 if decl.name.as_str() == symbol.as_str()
1190 && (as_trait.is_none()
1191 || as_trait.clone().unwrap().to_string() == trait_call_path_string)
1192 {
1193 candidates.insert(
1194 trait_call_path_string,
1195 ResolvedTraitImplItem::Typed(TyTraitItem::Type(type_ref)),
1196 );
1197 }
1198 }
1199 },
1200 }
1201 }
1202
1203 match candidates.len().cmp(&1) {
1204 Ordering::Greater => Err(handler.emit_err(
1205 CompileError::MultipleApplicableItemsInScope {
1206 item_name: symbol.as_str().to_string(),
1207 item_kind: "item".to_string(),
1208 as_traits: candidates
1209 .keys()
1210 .map(|k| {
1211 (
1212 k.clone()
1213 .split("::")
1214 .collect::<Vec<_>>()
1215 .last()
1216 .unwrap()
1217 .to_string(),
1218 engines.help_out(type_id).to_string(),
1219 )
1220 })
1221 .collect::<Vec<_>>(),
1222 span: symbol.span(),
1223 },
1224 )),
1225 Ordering::Less => Err(handler.emit_err(CompileError::SymbolNotFound {
1226 name: symbol.clone(),
1227 span: symbol.span(),
1228 })),
1229 Ordering::Equal => Ok(candidates.values().next().unwrap().clone()),
1230 }
1231 }
1232
1233 #[allow(clippy::too_many_arguments)]
1235 pub(crate) fn check_if_trait_constraints_are_satisfied_for_type(
1236 handler: &Handler,
1237 module: &mut Module,
1238 type_id: TypeId,
1239 constraints: &[TraitConstraint],
1240 access_span: &Span,
1241 engines: &Engines,
1242 ) -> Result<(), ErrorEmitted> {
1243 let type_engine = engines.te();
1244
1245 let type_id = type_engine.get_unaliased_type_id(type_id);
1246
1247 type_engine.decay_numeric(handler, engines, type_id, access_span)?;
1249
1250 if constraints.is_empty() {
1251 return Ok(());
1252 }
1253
1254 let mut hasher = DefaultHasher::default();
1256 type_id.hash(&mut hasher);
1257 for c in constraints {
1258 c.hash(&mut hasher, engines);
1259 }
1260 let hash = hasher.finish();
1261
1262 {
1263 let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1264 if trait_map.satisfied_cache.contains(&hash) {
1265 return Ok(());
1266 }
1267 }
1268
1269 let all_impld_traits: BTreeSet<(Ident, TypeId)> =
1270 Self::get_all_implemented_traits(module, type_id, engines);
1271
1272 match Self::check_if_trait_constraints_are_satisfied_for_type_inner(
1274 handler,
1275 type_id,
1276 constraints,
1277 access_span,
1278 engines,
1279 all_impld_traits,
1280 ) {
1281 Ok(()) => {
1282 let trait_map = &mut module.current_lexical_scope_mut().items.implemented_traits;
1283 trait_map.satisfied_cache.insert(hash);
1284 Ok(())
1285 }
1286 r => r,
1287 }
1288 }
1289
1290 fn get_all_implemented_traits(
1291 module: &Module,
1292 type_id: TypeId,
1293 engines: &Engines,
1294 ) -> BTreeSet<(Ident, TypeId)> {
1295 let mut all_impld_traits: BTreeSet<(Ident, TypeId)> = Default::default();
1296 let _ = module.walk_scope_chain(|lexical_scope| {
1297 all_impld_traits.extend(
1298 lexical_scope
1299 .items
1300 .implemented_traits
1301 .get_implemented_traits(type_id, engines),
1302 );
1303 Ok(None::<()>)
1304 });
1305 all_impld_traits
1306 }
1307
1308 fn get_implemented_traits(
1309 &self,
1310 type_id: TypeId,
1311 engines: &Engines,
1312 ) -> BTreeSet<(Ident, TypeId)> {
1313 let type_engine = engines.te();
1314 let unify_check = UnifyCheck::constraint_subset(engines);
1315
1316 let impls = self.get_impls(engines, type_id, true);
1317 let all_impld_traits: BTreeSet<(Ident, TypeId)> = impls
1318 .iter()
1319 .filter_map(|e| {
1320 let key = &e.key;
1321 let suffix = &key.name.suffix;
1322 if unify_check.check(type_id, key.type_id) {
1323 let map_trait_type_id = type_engine.new_custom(
1324 engines,
1325 suffix.name.clone().into(),
1326 if suffix.args.is_empty() {
1327 None
1328 } else {
1329 Some(suffix.args.to_vec())
1330 },
1331 );
1332 Some((suffix.name.clone(), map_trait_type_id))
1333 } else {
1334 None
1335 }
1336 })
1337 .collect();
1338
1339 all_impld_traits
1340 }
1341
1342 #[allow(clippy::too_many_arguments)]
1343 fn check_if_trait_constraints_are_satisfied_for_type_inner(
1344 handler: &Handler,
1345 type_id: TypeId,
1346 constraints: &[TraitConstraint],
1347 access_span: &Span,
1348 engines: &Engines,
1349 all_impld_traits: BTreeSet<(Ident, TypeId)>,
1350 ) -> Result<(), ErrorEmitted> {
1351 let type_engine = engines.te();
1352 let unify_check = UnifyCheck::constraint_subset(engines);
1353
1354 let required_traits: BTreeSet<(Ident, TypeId)> = constraints
1355 .iter()
1356 .map(|c| {
1357 let TraitConstraint {
1358 trait_name: constraint_trait_name,
1359 type_arguments: constraint_type_arguments,
1360 } = c;
1361 let constraint_type_id = type_engine.new_custom(
1362 engines,
1363 constraint_trait_name.suffix.clone().into(),
1364 if constraint_type_arguments.is_empty() {
1365 None
1366 } else {
1367 Some(constraint_type_arguments.clone())
1368 },
1369 );
1370 (c.trait_name.suffix.clone(), constraint_type_id)
1371 })
1372 .collect();
1373
1374 let traits_not_found: BTreeSet<(BaseIdent, TypeId)> = required_traits
1375 .into_iter()
1376 .filter(|(required_trait_name, required_trait_type_id)| {
1377 !all_impld_traits
1378 .iter()
1379 .any(|(trait_name, constraint_type_id)| {
1380 trait_name == required_trait_name
1381 && unify_check.check(*constraint_type_id, *required_trait_type_id)
1382 })
1383 })
1384 .collect();
1385
1386 handler.scope(|handler| {
1387 for (trait_name, constraint_type_id) in traits_not_found.iter() {
1388 let mut type_arguments_string = "".to_string();
1389 if let TypeInfo::Custom {
1390 qualified_call_path: _,
1391 type_arguments: Some(type_arguments),
1392 } = &*type_engine.get(*constraint_type_id)
1393 {
1394 type_arguments_string = format!("<{}>", engines.help_out(type_arguments));
1395 }
1396
1397 handler.emit_err(CompileError::TraitConstraintNotSatisfied {
1399 type_id: type_id.index(),
1400 ty: engines.help_out(type_id).to_string(),
1401 trait_name: format!("{}{}", trait_name, type_arguments_string),
1402 span: access_span.clone(),
1403 });
1404 }
1405
1406 Ok(())
1407 })
1408 }
1409
1410 pub fn get_trait_constraints_are_satisfied_for_types(
1411 module: &Module,
1412 _handler: &Handler,
1413 type_id: TypeId,
1414 constraints: &[TraitConstraint],
1415 engines: &Engines,
1416 ) -> Result<Vec<(TypeId, String)>, ErrorEmitted> {
1417 let type_id = engines.te().get_unaliased_type_id(type_id);
1418
1419 let _decl_engine = engines.de();
1420 let unify_check = UnifyCheck::coercion(engines);
1421 let unify_check_equality = UnifyCheck::constraint_subset(engines);
1422
1423 let mut impld_traits_type_ids: Vec<Vec<(TypeId, String)>> = vec![];
1424 let _ = module.walk_scope_chain(|lexical_scope| {
1425 let impls = lexical_scope
1426 .items
1427 .implemented_traits
1428 .get_impls(engines, type_id, true);
1429 impld_traits_type_ids.push(
1430 impls
1431 .iter()
1432 .filter_map(|e| {
1433 let key = &e.key;
1434 let mut res = None;
1435 for constraint in constraints {
1436 if key.name.suffix.name == constraint.trait_name.suffix
1437 && key
1438 .name
1439 .suffix
1440 .args
1441 .iter()
1442 .zip(constraint.type_arguments.iter())
1443 .all(|(a1, a2)| {
1444 unify_check_equality.check(a1.type_id, a2.type_id)
1445 })
1446 && unify_check.check(type_id, key.type_id)
1447 {
1448 let name_type_args = if !key.name.suffix.args.is_empty() {
1449 format!("<{}>", engines.help_out(key.name.suffix.args.clone()))
1450 } else {
1451 "".to_string()
1452 };
1453 let name =
1454 format!("{}{}", key.name.suffix.name.as_str(), name_type_args);
1455 res = Some((key.type_id, name));
1456 break;
1457 }
1458 }
1459 res
1460 })
1461 .collect(),
1462 );
1463
1464 Ok(None::<()>)
1465 });
1466 Ok(impld_traits_type_ids.concat())
1467 }
1468
1469 fn get_impls_mut(&mut self, engines: &Engines, type_id: TypeId) -> &mut Vec<TraitEntry> {
1470 let type_root_filter = Self::get_type_root_filter(engines, type_id);
1471 if !self.trait_impls.contains_key(&type_root_filter) {
1472 self.trait_impls
1473 .insert(type_root_filter.clone(), Vec::new());
1474 }
1475
1476 self.trait_impls.get_mut(&type_root_filter).unwrap()
1477 }
1478
1479 fn get_impls(
1480 &self,
1481 engines: &Engines,
1482 type_id: TypeId,
1483 extend_with_placeholder: bool,
1484 ) -> Vec<TraitEntry> {
1485 let type_root_filter = Self::get_type_root_filter(engines, type_id);
1486 let mut vec = self
1487 .trait_impls
1488 .get(&type_root_filter)
1489 .cloned()
1490 .unwrap_or_default();
1491 if extend_with_placeholder && type_root_filter != TypeRootFilter::Placeholder {
1492 vec.extend(
1493 self.trait_impls
1494 .get(&TypeRootFilter::Placeholder)
1495 .cloned()
1496 .unwrap_or_default(),
1497 );
1498 }
1499 vec
1500 }
1501
1502 fn get_type_root_filter(engines: &Engines, type_id: TypeId) -> TypeRootFilter {
1505 use TypeInfo::*;
1506 match &*engines.te().get(type_id) {
1507 Unknown => TypeRootFilter::Unknown,
1508 Never => TypeRootFilter::Never,
1509 UnknownGeneric { .. } | Placeholder(_) => TypeRootFilter::Placeholder,
1510 TypeParam(_param) => unreachable!(),
1511 StringSlice => TypeRootFilter::StringSlice,
1512 StringArray(x) => TypeRootFilter::StringArray(x.val()),
1513 UnsignedInteger(x) => match x {
1514 IntegerBits::Eight => TypeRootFilter::U8,
1515 IntegerBits::Sixteen => TypeRootFilter::U16,
1516 IntegerBits::ThirtyTwo => TypeRootFilter::U32,
1517 IntegerBits::SixtyFour => TypeRootFilter::U64,
1518 IntegerBits::V256 => TypeRootFilter::U256,
1519 },
1520 Boolean => TypeRootFilter::Bool,
1521 Custom {
1522 qualified_call_path: call_path,
1523 ..
1524 } => TypeRootFilter::Custom(call_path.call_path.suffix.to_string()),
1525 B256 => TypeRootFilter::B256,
1526 Numeric => TypeRootFilter::U64, Contract => TypeRootFilter::Contract,
1528 ErrorRecovery(_) => TypeRootFilter::ErrorRecovery,
1529 Tuple(fields) => TypeRootFilter::Tuple(fields.len()),
1530 UntypedEnum(decl_id) => TypeRootFilter::Enum(*decl_id),
1531 UntypedStruct(decl_id) => TypeRootFilter::Struct(*decl_id),
1532 Enum(decl_id) => {
1533 TypeRootFilter::Enum(engines.de().get_parsed_decl_id(decl_id).unwrap())
1535 }
1536 Struct(decl_id) => {
1537 TypeRootFilter::Struct(engines.de().get_parsed_decl_id(decl_id).unwrap())
1539 }
1540 ContractCaller { abi_name, .. } => TypeRootFilter::ContractCaller(abi_name.to_string()),
1541 Array(_, _) => TypeRootFilter::Array,
1542 RawUntypedPtr => TypeRootFilter::RawUntypedPtr,
1543 RawUntypedSlice => TypeRootFilter::RawUntypedSlice,
1544 Ptr(_) => TypeRootFilter::Ptr,
1545 Slice(_) => TypeRootFilter::Slice,
1546 Alias { ty, .. } => Self::get_type_root_filter(engines, ty.type_id),
1547 TraitType { name, .. } => TypeRootFilter::TraitType(name.to_string()),
1548 Ref {
1549 referenced_type, ..
1550 } => Self::get_type_root_filter(engines, referenced_type.type_id),
1551 }
1552 }
1553}