1
- use std:: fmt;
1
+ use std:: { collections:: HashSet , fmt} ;
2
+
3
+ use sway_error:: handler:: { ErrorEmitted , Handler } ;
2
4
3
5
use crate :: {
6
+ engine_threading:: DebugWithEngines ,
4
7
language:: ty:: { TyTraitInterfaceItem , TyTraitItem } ,
5
8
Engines , TypeId , UnifyCheck ,
6
9
} ;
7
10
8
- use super :: { AssociatedItemDeclId , DeclEngineGet , InterfaceItemMap , ItemMap } ;
11
+ use super :: { AssociatedItemDeclId , InterfaceItemMap , ItemMap } ;
9
12
10
- type SourceDecl = AssociatedItemDeclId ;
13
+ type SourceDecl = ( AssociatedItemDeclId , TypeId ) ;
11
14
type DestinationDecl = AssociatedItemDeclId ;
12
15
13
16
/// The [DeclMapping] is used to create a mapping between a [SourceDecl] (LHS)
14
17
/// and a [DestinationDecl] (RHS).
18
+ #[ derive( Clone ) ]
15
19
pub struct DeclMapping {
16
20
mapping : Vec < ( SourceDecl , DestinationDecl ) > ,
17
21
}
@@ -26,7 +30,7 @@ impl fmt::Display for DeclMapping {
26
30
. map( |( source_type, dest_type) | {
27
31
format!(
28
32
"{} -> {}" ,
29
- source_type,
33
+ source_type. 0 ,
30
34
match dest_type {
31
35
AssociatedItemDeclId :: TraitFn ( decl_id) => decl_id. inner( ) ,
32
36
AssociatedItemDeclId :: Function ( decl_id) => decl_id. inner( ) ,
@@ -55,17 +59,27 @@ impl fmt::Debug for DeclMapping {
55
59
}
56
60
}
57
61
58
- impl DeclMapping {
59
- pub ( crate ) fn new ( ) -> Self {
60
- Self {
61
- mapping : Vec :: new ( ) ,
62
- }
63
- }
64
-
65
- pub ( crate ) fn insert ( & mut self , k : SourceDecl , v : DestinationDecl ) {
66
- self . mapping . push ( ( k, v) )
62
+ impl DebugWithEngines for DeclMapping {
63
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > , engines : & Engines ) -> fmt:: Result {
64
+ write ! (
65
+ f,
66
+ "DeclMapping {{ {} }}" ,
67
+ self . mapping
68
+ . iter( )
69
+ . map( |( source_type, dest_type) | {
70
+ format!(
71
+ "{} -> {}" ,
72
+ engines. help_out( source_type. 0 . clone( ) ) ,
73
+ engines. help_out( dest_type)
74
+ )
75
+ } )
76
+ . collect:: <Vec <_>>( )
77
+ . join( ", " )
78
+ )
67
79
}
80
+ }
68
81
82
+ impl DeclMapping {
69
83
pub ( crate ) fn is_empty ( & self ) -> bool {
70
84
self . mapping . is_empty ( )
71
85
}
@@ -79,9 +93,15 @@ impl DeclMapping {
79
93
for ( interface_decl_name, interface_item) in interface_decl_refs. into_iter ( ) {
80
94
if let Some ( new_item) = impld_decl_refs. get ( & interface_decl_name) {
81
95
let interface_decl_ref = match interface_item {
82
- TyTraitInterfaceItem :: TraitFn ( decl_ref) => decl_ref. id ( ) . into ( ) ,
83
- TyTraitInterfaceItem :: Constant ( decl_ref) => decl_ref. id ( ) . into ( ) ,
84
- TyTraitInterfaceItem :: Type ( decl_ref) => decl_ref. id ( ) . into ( ) ,
96
+ TyTraitInterfaceItem :: TraitFn ( decl_ref) => {
97
+ ( decl_ref. id ( ) . into ( ) , interface_decl_name. 1 )
98
+ }
99
+ TyTraitInterfaceItem :: Constant ( decl_ref) => {
100
+ ( decl_ref. id ( ) . into ( ) , interface_decl_name. 1 )
101
+ }
102
+ TyTraitInterfaceItem :: Type ( decl_ref) => {
103
+ ( decl_ref. id ( ) . into ( ) , interface_decl_name. 1 )
104
+ }
85
105
} ;
86
106
let new_decl_ref = match new_item {
87
107
TyTraitItem :: Fn ( decl_ref) => decl_ref. id ( ) . into ( ) ,
@@ -94,9 +114,9 @@ impl DeclMapping {
94
114
for ( decl_name, item) in item_decl_refs. into_iter ( ) {
95
115
if let Some ( new_item) = impld_decl_refs. get ( & decl_name) {
96
116
let interface_decl_ref = match item {
97
- TyTraitItem :: Fn ( decl_ref) => decl_ref. id ( ) . into ( ) ,
98
- TyTraitItem :: Constant ( decl_ref) => decl_ref. id ( ) . into ( ) ,
99
- TyTraitItem :: Type ( decl_ref) => decl_ref. id ( ) . into ( ) ,
117
+ TyTraitItem :: Fn ( decl_ref) => ( decl_ref. id ( ) . into ( ) , decl_name . 1 ) ,
118
+ TyTraitItem :: Constant ( decl_ref) => ( decl_ref. id ( ) . into ( ) , decl_name . 1 ) ,
119
+ TyTraitItem :: Type ( decl_ref) => ( decl_ref. id ( ) . into ( ) , decl_name . 1 ) ,
100
120
} ;
101
121
let new_decl_ref = match new_item {
102
122
TyTraitItem :: Fn ( decl_ref) => decl_ref. id ( ) . into ( ) ,
@@ -109,39 +129,41 @@ impl DeclMapping {
109
129
DeclMapping { mapping }
110
130
}
111
131
112
- pub ( crate ) fn find_match ( & self , decl_ref : SourceDecl ) -> Option < DestinationDecl > {
113
- for ( source_decl_ref, dest_decl_ref) in self . mapping . iter ( ) {
114
- if * source_decl_ref == decl_ref {
115
- return Some ( dest_decl_ref. clone ( ) ) ;
116
- }
117
- }
118
- None
119
- }
120
-
121
- /// This method returns only associated item functions that have as self type the given type.
122
- pub ( crate ) fn filter_functions_by_self_type (
132
+ pub ( crate ) fn find_match (
123
133
& self ,
124
- self_type : TypeId ,
134
+ _handler : & Handler ,
125
135
engines : & Engines ,
126
- ) -> DeclMapping {
127
- let mut mapping: Vec < ( SourceDecl , DestinationDecl ) > = vec ! [ ] ;
128
- for ( source_decl_ref, dest_decl_ref) in self . mapping . iter ( ) . cloned ( ) {
129
- match dest_decl_ref {
130
- AssociatedItemDeclId :: TraitFn ( _) => mapping. push ( ( source_decl_ref, dest_decl_ref) ) ,
131
- AssociatedItemDeclId :: Function ( func_id) => {
132
- let func = engines. de ( ) . get ( & func_id) ;
136
+ decl_ref : AssociatedItemDeclId ,
137
+ typeid : Option < TypeId > ,
138
+ self_typeid : Option < TypeId > ,
139
+ ) -> Result < Option < DestinationDecl > , ErrorEmitted > {
140
+ let mut dest_decl_refs = HashSet :: < DestinationDecl > :: new ( ) ;
133
141
134
- let unify_check = UnifyCheck :: non_dynamic_equality ( engines) ;
135
- if let ( left, Some ( right) ) = ( self_type, func. parameters . first ( ) ) {
136
- if unify_check. check ( left, right. type_argument . type_id ) {
137
- mapping. push ( ( source_decl_ref, dest_decl_ref) ) ;
138
- }
139
- }
142
+ if let Some ( mut typeid) = typeid {
143
+ if engines. te ( ) . get ( typeid) . is_self_type ( ) && self_typeid. is_some ( ) {
144
+ // If typeid is `Self`, then we use the self_typeid instead.
145
+ typeid = self_typeid. unwrap ( ) ;
146
+ }
147
+ for ( source_decl_ref, dest_decl_ref) in self . mapping . iter ( ) {
148
+ let unify_check = UnifyCheck :: non_dynamic_equality ( engines) ;
149
+ if source_decl_ref. 0 == decl_ref && unify_check. check ( source_decl_ref. 1 , typeid) {
150
+ dest_decl_refs. insert ( dest_decl_ref. clone ( ) ) ;
140
151
}
141
- AssociatedItemDeclId :: Constant ( _) => mapping. push ( ( source_decl_ref, dest_decl_ref) ) ,
142
- AssociatedItemDeclId :: Type ( _) => mapping. push ( ( source_decl_ref, dest_decl_ref) ) ,
143
152
}
144
153
}
145
- DeclMapping { mapping }
154
+
155
+ // At most one replacement should be found for decl_ref.
156
+ /* TODO uncomment this and close issue #5540
157
+ if dest_decl_refs.len() > 1 {
158
+ handler.emit_err(CompileError::InternalOwned(
159
+ format!(
160
+ "Multiple replacements for decl {} implemented in {}",
161
+ engines.help_out(decl_ref),
162
+ engines.help_out(typeid),
163
+ ),
164
+ dest_decl_refs.iter().last().unwrap().span(engines),
165
+ ));
166
+ }*/
167
+ Ok ( dest_decl_refs. iter ( ) . next ( ) . cloned ( ) )
146
168
}
147
169
}
0 commit comments