@@ -7,11 +7,12 @@ use indexmap::{IndexMap, IndexSet};
7
7
use std:: collections:: { HashMap , HashSet , VecDeque } ;
8
8
use std:: mem:: swap;
9
9
use types:: check:: TypeChecker ;
10
+ use types:: format:: format_type;
10
11
use types:: specialize:: { ordered_shapes_from_map, TypeSpecializer } ;
11
12
use types:: {
12
13
Block as _, Database , InternedTypeArguments , MethodId , Shape ,
13
- TypeArguments , TypeId , TypeInstance , TypeParameterId , TypeRef , CALL_METHOD ,
14
- DECREMENT_METHOD , DROPPER_METHOD , INCREMENT_METHOD ,
14
+ TypeArguments , TypeEnum , TypeId , TypeInstance , TypeParameterId , TypeRef ,
15
+ CALL_METHOD , DECREMENT_METHOD , DROPPER_METHOD , INCREMENT_METHOD ,
15
16
} ;
16
17
17
18
fn argument_shape (
@@ -34,7 +35,7 @@ fn specialize_constants(
34
35
35
36
// Constants never need access to the self type, so we just use a dummy
36
37
// value here.
37
- let stype = TypeInstance :: new ( TypeId :: nil ( ) ) ;
38
+ let stype = TypeEnum :: TypeInstance ( TypeInstance :: new ( TypeId :: nil ( ) ) ) ;
38
39
39
40
for & id in mir. constants . keys ( ) {
40
41
let old_typ = id. value_type ( db) ;
@@ -97,7 +98,7 @@ fn shapes_compatible_with_bounds(
97
98
98
99
struct Job {
99
100
/// The type of `self` within the method.
100
- self_type : TypeInstance ,
101
+ self_type : TypeEnum ,
101
102
102
103
/// The ID of the method that's being specialized.
103
104
method : MethodId ,
@@ -124,7 +125,7 @@ impl Work {
124
125
125
126
fn push (
126
127
& mut self ,
127
- self_type : TypeInstance ,
128
+ self_type : TypeEnum ,
128
129
method : MethodId ,
129
130
shapes : HashMap < TypeParameterId , Shape > ,
130
131
) -> bool {
@@ -228,7 +229,7 @@ impl DynamicCalls {
228
229
229
230
/// A compiler pass that specializes generic types.
230
231
pub ( crate ) struct Specialize < ' a , ' b > {
231
- self_type : TypeInstance ,
232
+ self_type : TypeEnum ,
232
233
method : MethodId ,
233
234
state : & ' a mut State ,
234
235
work : & ' b mut Work ,
@@ -276,7 +277,11 @@ impl<'a, 'b> Specialize<'a, 'b> {
276
277
let main_method = state. db . main_method ( ) . unwrap ( ) ;
277
278
let main_mod = main_type. module ( & state. db ) ;
278
279
279
- work. push ( TypeInstance :: new ( main_type) , main_method, HashMap :: new ( ) ) ;
280
+ work. push (
281
+ TypeEnum :: TypeInstance ( TypeInstance :: new ( main_type) ) ,
282
+ main_method,
283
+ HashMap :: new ( ) ,
284
+ ) ;
280
285
281
286
// The main() method isn't called explicitly, so we have to manually
282
287
// record it in the main type.
@@ -852,11 +857,20 @@ impl<'a, 'b> Specialize<'a, 'b> {
852
857
type_arguments : Option < & TypeArguments > ,
853
858
) -> Instruction {
854
859
let typ = receiver. instance_of ( ) ;
855
- let method_impl = typ
860
+
861
+ let Some ( method_impl) = typ
856
862
. specialization_source ( & self . state . db )
857
863
. unwrap_or ( typ)
858
864
. method ( & self . state . db , call. method . name ( & self . state . db ) )
859
- . unwrap ( ) ;
865
+ else {
866
+ panic ! (
867
+ "can't devirtualize call to {}.{} in {}.{}" ,
868
+ receiver. instance_of( ) . name( & self . state. db) ,
869
+ call. method. name( & self . state. db) ,
870
+ format_type( & self . state. db, self . self_type) ,
871
+ self . method. name( & self . state. db) ,
872
+ ) ;
873
+ } ;
860
874
861
875
let mut shapes = type_arguments
862
876
. map ( |args| self . type_argument_shapes ( call. method , args) )
@@ -899,18 +913,18 @@ impl<'a, 'b> Specialize<'a, 'b> {
899
913
type_id : TypeId ,
900
914
method : MethodId ,
901
915
shapes : & HashMap < TypeParameterId , Shape > ,
902
- custom_self_type : Option < TypeInstance > ,
916
+ custom_self_type : Option < TypeEnum > ,
903
917
) -> MethodId {
904
918
let ins = TypeInstance :: new ( type_id) ;
905
- let stype = custom_self_type. unwrap_or ( ins) ;
919
+ let stype = custom_self_type. unwrap_or ( TypeEnum :: TypeInstance ( ins) ) ;
906
920
907
921
// Regular methods on regular types don't need to be specialized.
908
922
if !type_id. is_generic ( & self . state . db )
909
923
&& !type_id. is_closure ( & self . state . db )
910
924
&& !method. is_generic ( & self . state . db )
911
925
{
912
926
if self . work . push ( stype, method, shapes. clone ( ) ) {
913
- self . update_method_type ( method, shapes) ;
927
+ self . update_method_type ( stype , method, shapes) ;
914
928
self . regular_methods . push ( method) ;
915
929
}
916
930
@@ -959,7 +973,7 @@ impl<'a, 'b> Specialize<'a, 'b> {
959
973
960
974
for name in methods {
961
975
let method = type_id. method ( & self . state . db , name) . unwrap ( ) ;
962
- let stype = TypeInstance :: new ( type_id) ;
976
+ let stype = TypeEnum :: TypeInstance ( TypeInstance :: new ( type_id) ) ;
963
977
964
978
if self . work . push ( stype, method, HashMap :: new ( ) ) {
965
979
self . regular_methods . push ( method) ;
@@ -980,7 +994,7 @@ impl<'a, 'b> Specialize<'a, 'b> {
980
994
let stype = if type_id. is_closure ( & self . state . db ) {
981
995
self . self_type
982
996
} else {
983
- TypeInstance :: new ( type_id)
997
+ TypeEnum :: TypeInstance ( TypeInstance :: new ( type_id) )
984
998
} ;
985
999
986
1000
if original == type_id {
@@ -1021,7 +1035,7 @@ impl<'a, 'b> Specialize<'a, 'b> {
1021
1035
let method = original. method ( & self . state . db , name) . unwrap ( ) ;
1022
1036
1023
1037
if original == type_id {
1024
- let stype = TypeInstance :: new ( type_id) ;
1038
+ let stype = TypeEnum :: TypeInstance ( TypeInstance :: new ( type_id) ) ;
1025
1039
1026
1040
if self . work . push ( stype, method, HashMap :: new ( ) ) {
1027
1041
self . regular_methods . push ( method) ;
@@ -1089,14 +1103,15 @@ impl<'a, 'b> Specialize<'a, 'b> {
1089
1103
1090
1104
let new = method. clone_for_specialization ( & mut self . state . db ) ;
1091
1105
let old_ret = method. return_type ( & self . state . db ) ;
1106
+ let stype = receiver. as_type_enum ( & self . state . db ) . unwrap ( ) ;
1092
1107
1093
1108
for arg in method. arguments ( & self . state . db ) {
1094
1109
let arg_type = TypeSpecializer :: new (
1095
1110
& mut self . state . db ,
1096
1111
self . interned ,
1097
1112
shapes,
1098
1113
& mut self . types ,
1099
- self . self_type ,
1114
+ stype ,
1100
1115
)
1101
1116
. specialize ( arg. value_type ) ;
1102
1117
@@ -1107,7 +1122,7 @@ impl<'a, 'b> Specialize<'a, 'b> {
1107
1122
self . interned ,
1108
1123
shapes,
1109
1124
& mut self . types ,
1110
- self . self_type ,
1125
+ stype ,
1111
1126
)
1112
1127
. specialize ( raw_var_type) ;
1113
1128
@@ -1125,7 +1140,7 @@ impl<'a, 'b> Specialize<'a, 'b> {
1125
1140
self . interned ,
1126
1141
shapes,
1127
1142
& mut self . types ,
1128
- self . self_type ,
1143
+ stype ,
1129
1144
)
1130
1145
. specialize ( old_ret) ;
1131
1146
@@ -1150,6 +1165,7 @@ impl<'a, 'b> Specialize<'a, 'b> {
1150
1165
/// return types are specialized (if needed).
1151
1166
fn update_method_type (
1152
1167
& mut self ,
1168
+ self_type : TypeEnum ,
1153
1169
method : MethodId ,
1154
1170
shapes : & HashMap < TypeParameterId , Shape > ,
1155
1171
) {
@@ -1161,7 +1177,7 @@ impl<'a, 'b> Specialize<'a, 'b> {
1161
1177
self . interned ,
1162
1178
shapes,
1163
1179
& mut self . types ,
1164
- self . self_type ,
1180
+ self_type,
1165
1181
)
1166
1182
. specialize ( arg. value_type ) ;
1167
1183
@@ -1171,7 +1187,7 @@ impl<'a, 'b> Specialize<'a, 'b> {
1171
1187
self . interned ,
1172
1188
shapes,
1173
1189
& mut self . types ,
1174
- self . self_type ,
1190
+ self_type,
1175
1191
)
1176
1192
. specialize ( raw_var_type) ;
1177
1193
@@ -1189,7 +1205,7 @@ impl<'a, 'b> Specialize<'a, 'b> {
1189
1205
self . interned ,
1190
1206
shapes,
1191
1207
& mut self . types ,
1192
- self . self_type ,
1208
+ self_type,
1193
1209
)
1194
1210
. specialize ( old_ret) ;
1195
1211
0 commit comments