@@ -281,6 +281,78 @@ static jl_value_t *lookup_match(jl_value_t *a, jl_value_t *b, jl_svec_t **penv,
281
281
return ti ;
282
282
}
283
283
284
+ jl_value_t * jl_nth_slot_type (jl_tupletype_t * sig , size_t i )
285
+ {
286
+ size_t len = jl_datatype_nfields (sig );
287
+ if (len == 0 )
288
+ return NULL ;
289
+ if (i < len - 1 )
290
+ return jl_tparam (sig , i );
291
+ if (jl_is_vararg_type (jl_tparam (sig ,len - 1 )))
292
+ return jl_tparam0 (jl_tparam (sig ,len - 1 ));
293
+ if (i == len - 1 )
294
+ return jl_tparam (sig , i );
295
+ return NULL ;
296
+ }
297
+
298
+ // after intersection, the argument tuple type needs to be corrected to reflect the signature match
299
+ // that occurred, if the arguments contained a Type but the signature matched on the kind
300
+ static jl_tupletype_t * join_tsig (jl_tupletype_t * tt , jl_tupletype_t * sig )
301
+ {
302
+ jl_svec_t * newparams = NULL ;
303
+ JL_GC_PUSH1 (& newparams );
304
+ int changed = 0 ;
305
+ size_t i , np ;
306
+ for (i = 0 , np = jl_nparams (tt ); i < np ; i ++ ) {
307
+ jl_value_t * elt = jl_tparam (tt , i );
308
+ jl_value_t * newelt = NULL ;
309
+ jl_value_t * decl_i = jl_nth_slot_type (sig , i );
310
+ int isva = jl_is_vararg_type (elt );
311
+ if (isva ) elt = jl_tparam0 (elt );
312
+
313
+ if (jl_is_type_type (elt )) {
314
+ // unless the type signature matched T in `::Type{T}`
315
+ // the result of matching the type signature
316
+ // needs to be corrected to the leaf type 'kind'
317
+ // (for performance and/or correctness)
318
+ jl_value_t * kind = jl_typeof (jl_tparam0 (elt ));
319
+ if (jl_subtype (kind , decl_i , 0 )) {
320
+ if (jl_subtype ((jl_value_t * )jl_type_type , decl_i , 0 )) { // declared type was Any or Union{Type, ...}
321
+ // if there are bound typevars, the user indicated this exact specialization was required
322
+ // don't change it or it might mismatch the env
323
+ if (!jl_has_typevars (decl_i ))
324
+ newelt = (jl_value_t * )jl_type_type ;
325
+ }
326
+ else {
327
+ // TypeConstructors are problematic because they can be alternate
328
+ // representations of any type. If we matched this method because
329
+ // it matched the leaf type TypeConstructor, then don't
330
+ // cache something different since that doesn't necessarily actually apply
331
+ //
332
+ // similarly, if we matched Type{T<:Any}::DataType,
333
+ // then we don't want to cache it that way
334
+ // since lookup will think we matched ::Type{T}
335
+ // and that is quite a different thing
336
+ newelt = kind ;
337
+ }
338
+ }
339
+ }
340
+ // prepare to build a new type with the replacement above
341
+ if (newelt ) {
342
+ if (isva ) newelt = (jl_value_t * )jl_wrap_vararg (newelt );
343
+ if (!changed ) {
344
+ newparams = jl_svec_copy (tt -> parameters );
345
+ changed = 1 ;
346
+ }
347
+ jl_svecset (newparams , i , newelt );
348
+ }
349
+ }
350
+ if (changed )
351
+ tt = jl_apply_tuple_type (newparams );
352
+ JL_GC_POP ();
353
+ return tt ;
354
+ }
355
+
284
356
static int sigs_eq (jl_value_t * a , jl_value_t * b , int useenv )
285
357
{
286
358
if (jl_has_typevars (a ) || jl_has_typevars (b )) {
@@ -1056,27 +1128,6 @@ void jl_type_infer(jl_lambda_info_t *li, jl_value_t *toplevel)
1056
1128
#endif
1057
1129
}
1058
1130
1059
- jl_value_t * jl_nth_slot_type (jl_tupletype_t * sig , size_t i )
1060
- {
1061
- size_t len = jl_datatype_nfields (sig );
1062
- if (len == 0 )
1063
- return NULL ;
1064
- if (i < len - 1 )
1065
- return jl_tparam (sig , i );
1066
- if (jl_is_vararg_type (jl_tparam (sig ,len - 1 )))
1067
- return jl_tparam0 (jl_tparam (sig ,len - 1 ));
1068
- if (i == len - 1 )
1069
- return jl_tparam (sig , i );
1070
- return NULL ;
1071
- }
1072
-
1073
- static int very_general_type (jl_value_t * t )
1074
- {
1075
- return (t && (t == (jl_value_t * )jl_any_type || t == (jl_value_t * )jl_type_type ||
1076
- (jl_is_typevar (t ) &&
1077
- ((jl_tvar_t * )t )-> ub == (jl_value_t * )jl_any_type )));
1078
- }
1079
-
1080
1131
static int is_kind (jl_value_t * v )
1081
1132
{
1082
1133
return (v == (jl_value_t * )jl_uniontype_type ||
@@ -1110,27 +1161,6 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, union _jl_opaque_cache
1110
1161
for (i = 0 ; i < np ; i ++ ) {
1111
1162
jl_value_t * elt = jl_tparam (type ,i );
1112
1163
jl_value_t * decl_i = jl_nth_slot_type (decl ,i );
1113
- if (!isstaged && jl_is_type_type (elt ) && jl_is_tuple_type (jl_tparam0 (elt )) &&
1114
- !(jl_subtype (decl_i , (jl_value_t * )jl_type_type , 0 ) && !is_kind (decl_i ))) {
1115
- jl_methlist_t * curr = mt -> defs ;
1116
- int ok = 1 ;
1117
- while (curr != (void * )jl_nothing ) {
1118
- jl_value_t * slottype = jl_nth_slot_type (curr -> sig , i );
1119
- if (slottype && curr -> func != method ) {
1120
- if (jl_is_type_type (slottype ) &&
1121
- jl_type_intersection (slottype , decl_i ) != jl_bottom_type ) {
1122
- ok = 0 ;
1123
- break ;
1124
- }
1125
- }
1126
- curr = curr -> next ;
1127
- }
1128
- if (ok ) {
1129
- elt = jl_typeof (jl_tparam0 (elt ));
1130
- jl_svecset (newparams , i , elt );
1131
- }
1132
- }
1133
-
1134
1164
int set_to_any = 0 ;
1135
1165
int notcalled_func = (i > 0 && i <=8 && !(spec -> called & (1 <<(i - 1 ))) &&
1136
1166
jl_subtype (elt ,(jl_value_t * )jl_function_type ,0 ));
@@ -1179,24 +1209,9 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, union _jl_opaque_cache
1179
1209
}
1180
1210
}
1181
1211
}
1212
+
1182
1213
if (set_to_any || isstaged ) {
1183
1214
}
1184
- else if (jl_is_type_type (elt ) && jl_is_typector (jl_tparam0 (elt )) &&
1185
- decl_i == (jl_value_t * )jl_typector_type ) {
1186
- // TypeConstructors are problematic because they can be alternate
1187
- // representations of any type. If we matched this method because
1188
- // it matched the leaf type TypeConstructor, then don't
1189
- // cache something different since that doesn't necessarily actually apply
1190
- jl_svecset (newparams , i , jl_typector_type );
1191
- }
1192
- else if (jl_is_type_type (elt ) && decl_i == (jl_value_t * )jl_datatype_type ) {
1193
- // similarly, if we matched Type{T<:Any}::DataType,
1194
- // then we don't want to cache it that way
1195
- // since lookup will think we matched ::Type{T}
1196
- // and that is quite a different thing
1197
- jl_svecset (newparams , i , jl_datatype_type );
1198
- need_guard_entries = 1 ; // DataType has a UID so its precedence in the cache may be too high
1199
- }
1200
1215
else if (jl_is_type_type (elt ) && jl_is_type_type (jl_tparam0 (elt )) &&
1201
1216
// give up on specializing static parameters for Type{Type{Type{...}}}
1202
1217
(jl_is_type_type (jl_tparam0 (jl_tparam0 (elt ))) ||
@@ -1228,90 +1243,8 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, union _jl_opaque_cache
1228
1243
need_guard_entries = 1 ;
1229
1244
assert (jl_svecref (newparams ,i ) != (jl_value_t * )jl_bottom_type );
1230
1245
}
1231
- else if (jl_is_type_type (elt ) && very_general_type (decl_i ) &&
1232
- !jl_has_typevars (decl_i )) {
1233
- /*
1234
- here's a fairly complex heuristic: if this argument slot's
1235
- declared type is Any, and no definition overlaps with Type
1236
- for this slot, then don't specialize for every Type that
1237
- might be passed.
1238
- Since every type x has its own type Type{x}, this would be
1239
- excessive specialization for an Any slot.
1240
-
1241
- TypeConstructors are problematic because they can be alternate
1242
- representations of any type. Extensionally, TC == TC.body, but
1243
- typeof(TC) != typeof(TC.body). This creates an ambiguity:
1244
- Type{TC} is type-equal to Type{TC.body}, yet a slot
1245
- x::TypeConstructor matches the first but not the second, while
1246
- also matching all other TypeConstructors. This means neither
1247
- Type{TC} nor TypeConstructor is more specific.
1248
-
1249
- To solve this, we identify "kind slots", which are slots
1250
- for which some definition specifies a kind (e.g. DataType).
1251
- Those tend to be in reflective functions that look at types
1252
- themselves. For these slots we specialize on jl_typeof(T) instead
1253
- of Type{T}, i.e. the kind of the type rather than the specific
1254
- type.
1255
- */
1256
- int ok = 1 , kindslot = 0 ;
1257
- jl_methlist_t * curr = mt -> defs ;
1258
- jl_value_t * kind = (jl_value_t * )jl_typeof (jl_tparam0 (elt ));
1259
- while (curr != (void * )jl_nothing ) {
1260
- jl_value_t * slottype = jl_nth_slot_type (curr -> sig , i );
1261
- if (slottype && curr -> func != method ) {
1262
- if (slottype == kind ) {
1263
- ok = 0 ;
1264
- break ;
1265
- }
1266
- if (is_kind (slottype ))
1267
- kindslot = 1 ;
1268
- }
1269
- curr = curr -> next ;
1270
- }
1271
- if (ok ) {
1272
- if (kindslot ) {
1273
- jl_svecset (newparams , i , kind );
1274
- }
1275
- else {
1276
- curr = mt -> defs ;
1277
- while (curr != (void * )jl_nothing ) {
1278
- jl_value_t * slottype = jl_nth_slot_type (curr -> sig , i );
1279
- if (slottype && curr -> func != method ) {
1280
- if (!very_general_type (slottype ) &&
1281
- jl_type_intersection (slottype , (jl_value_t * )jl_type_type ) !=
1282
- (jl_value_t * )jl_bottom_type ) {
1283
- ok = 0 ;
1284
- break ;
1285
- }
1286
- }
1287
- curr = curr -> next ;
1288
- }
1289
- if (ok ) {
1290
- jl_svecset (newparams , i , jl_typetype_type );
1291
- need_guard_entries = 1 ;
1292
- }
1293
- }
1294
- }
1295
- }
1296
- else if (is_kind (decl_i )) {
1297
- // if a slot is specialized for a particular kind, it can be
1298
- // considered a reflective method and so only needs to be
1299
- // specialized for type representation, not type extent.
1300
- jl_methlist_t * curr = mt -> defs ;
1301
- int ok = 1 ;
1302
- while (curr != (void * )jl_nothing ) {
1303
- jl_value_t * slottype = jl_nth_slot_type (curr -> sig , i );
1304
- if (slottype && curr -> func != method ) {
1305
- if (jl_is_type_type (slottype ) &&
1306
- jl_type_intersection (slottype , decl_i ) != jl_bottom_type ) {
1307
- ok = 0 ;
1308
- break ;
1309
- }
1310
- }
1311
- curr = curr -> next ;
1312
- }
1313
- if (ok )
1314
- jl_svecset (newparams , i , decl_i );
1246
+ else if (is_kind (elt )) {
1247
+ need_guard_entries = 1 ;
1315
1248
}
1316
1249
}
1317
1250
@@ -1394,6 +1327,7 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, union _jl_opaque_cache
1394
1327
}
1395
1328
}
1396
1329
if (unmatched_tvars ) {
1330
+ // FIXME: this is invalid (c.f. intersection of #11355 and #11840)
1397
1331
// if distinguishing a guard entry from the generalized signature
1398
1332
// would require matching type vars then bail out, since the
1399
1333
// method cache matching algorithm cannot do that.
@@ -1558,15 +1492,15 @@ static jl_lambda_info_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype_t *
1558
1492
jl_methlist_t * m = NULL ;
1559
1493
jl_svec_t * env = jl_emptysvec ;
1560
1494
jl_lambda_info_t * func = NULL ;
1561
- JL_GC_PUSH3 (& env , & m , & func );
1495
+ JL_GC_PUSH4 (& env , & m , & func , & tt );
1562
1496
1563
1497
m = jl_method_cache_assoc_by_type_ (mt -> defs , tt , inexact , & env );
1564
1498
if (m == NULL ) {
1565
1499
JL_GC_POP ();
1566
1500
return NULL ;
1567
1501
}
1568
1502
1569
- assert ( jl_is_svec ( env ) );
1503
+ tt = join_tsig ( tt , m -> sig );
1570
1504
func = m -> func ;
1571
1505
if (func -> isstaged )
1572
1506
func = jl_instantiate_staged (func , tt , env );
@@ -2234,6 +2168,7 @@ jl_value_t *jl_gf_invoke(jl_tupletype_t *types0, jl_value_t **args, size_t nargs
2234
2168
assert (ti != (jl_value_t * )jl_bottom_type );
2235
2169
(void )ti ;
2236
2170
}
2171
+ tt = join_tsig (tt , m -> sig );
2237
2172
jl_lambda_info_t * func = m -> func ;
2238
2173
2239
2174
if (func -> invokes .nothing == NULL )
0 commit comments