@@ -27,30 +27,37 @@ static int jl_is_any(jl_value_t *t1)
27
27
28
28
// the goal here is to compute if sig is more-specific
29
29
// than something we can put into the TypeName-based hash tables
30
- static int jl_args_morespecific_typename (jl_value_t * t1 )
30
+ // returns: 0 -> less specific, 1 -> more specific, 2 -> indeterminate (both)
31
+ static int jl_args_morespecific_typename (jl_value_t * t1 , int covariant )
31
32
{
32
33
if (jl_is_typector (t1 ))
33
34
t1 = (jl_value_t * )((jl_typector_t * )t1 )-> body ;
34
- if (jl_is_uniontype (t1 )) {
35
+ if (covariant && jl_is_uniontype (t1 )) {
35
36
jl_uniontype_t * ut = (jl_uniontype_t * )t1 ;
36
37
size_t i , l = jl_svec_len (ut -> types );
37
- for (i = 0 ; i < l ; i ++ ) {
38
- if (jl_args_morespecific_typename (jl_svecref (ut -> types , i )))
39
- return 1 ;
38
+ if (l == 0 )
39
+ return 0 ;
40
+ int morespec = jl_args_morespecific_typename (jl_svecref (ut -> types , 0 ), 0 );
41
+ for (i = 1 ; i < l ; i ++ ) {
42
+ if (morespec != jl_args_morespecific_typename (jl_svecref (ut -> types , i ), 0 ))
43
+ return 2 ;
40
44
}
41
- return 0 ;
45
+ return morespec ;
46
+ }
47
+ else if (jl_is_vararg_type (t1 )) {
48
+ return covariant ? jl_args_morespecific_typename (jl_tparam0 (t1 ), covariant ) : 0 ;
42
49
}
43
50
else if (jl_is_typevar (t1 )) {
44
- return jl_args_morespecific_typename (((jl_tvar_t * )t1 )-> ub );
51
+ return jl_args_morespecific_typename (((jl_tvar_t * )t1 )-> ub , 1 );
45
52
}
46
53
else if (jl_is_tuple (t1 )) {
47
- return 0 ;
54
+ return 0 ; // tuples aren't considered eligible for the TypeName level
48
55
}
49
56
else if (jl_is_type_type (t1 )) {
50
- return jl_args_morespecific_typename (jl_tparam0 (t1 ));
57
+ return jl_args_morespecific_typename (jl_tparam0 (t1 ), 0 );
51
58
}
52
59
else if (jl_is_datatype (t1 )) {
53
- return !((jl_datatype_t * )t1 )-> abstract && !is_kind (t1 );
60
+ return !((jl_datatype_t * )t1 )-> abstract && !is_kind (t1 ) ? 1 : 0 ;
54
61
}
55
62
return 0 ;
56
63
}
@@ -73,6 +80,69 @@ static jl_value_t* jl_type_extract_name(jl_value_t *t1)
73
80
return NULL ;
74
81
}
75
82
83
+ // note: this is carefully matched to jl_args_morespecific_typename
84
+ // to ensure that it won't be asked to split something any more
85
+ // complicated than it knows how to handle
86
+ static jl_value_t * jl_arg_split_spec (jl_value_t * t1 , int morespec , int covariant )
87
+ {
88
+ if (jl_is_typector (t1 ))
89
+ t1 = (jl_value_t * )((jl_typector_t * )t1 )-> body ;
90
+ if (covariant && jl_is_uniontype (t1 )) {
91
+ jl_uniontype_t * ut = (jl_uniontype_t * )t1 ;
92
+ size_t i , l = jl_svec_len (ut -> types );
93
+ size_t n = 0 ;
94
+ for (i = 0 ; i < l ; i ++ ) {
95
+ jl_value_t * elem = jl_svecref (ut -> types , i );
96
+ int elem_morespec = jl_args_morespecific_typename (elem , covariant );
97
+ if (elem_morespec == 2 || ((elem_morespec != 0 ) == (morespec != 0 )))
98
+ n ++ ;
99
+ }
100
+ jl_svec_t * u = jl_alloc_svec (n );
101
+ JL_GC_PUSH1 (& u );
102
+ n = 0 ;
103
+ for (i = 0 ; i < l ; i ++ ) {
104
+ jl_value_t * elem = jl_svecref (ut -> types , i );
105
+ int elem_morespec = jl_args_morespecific_typename (elem , covariant );
106
+ if (elem_morespec == 2 )
107
+ elem = jl_arg_split_spec (jl_svecref (ut -> types , i ), morespec , 0 );
108
+ else if ((elem_morespec != 0 ) != (morespec != 0 ))
109
+ continue ;
110
+ jl_svecset (u , n ++ , elem );
111
+ }
112
+ jl_value_t * uu = jl_type_union (u );
113
+ JL_GC_POP ();
114
+ return uu ;
115
+ }
116
+ else if (jl_is_vararg_type (t1 )) {
117
+ if (!covariant )
118
+ return t1 ;
119
+ jl_value_t * p = jl_arg_split_spec (jl_tparam0 (t1 ), morespec , covariant );
120
+ JL_GC_PUSH1 (& p );
121
+ assert (p != jl_tparam0 (t1 ));
122
+ p = (jl_value_t * )jl_wrap_vararg (p , jl_tparam1 (t1 ));
123
+ JL_GC_POP ();
124
+ return p ;
125
+ }
126
+ else if (jl_is_typevar (t1 )) {
127
+ jl_tvar_t * tv = (jl_tvar_t * )t1 ;
128
+ jl_value_t * tv2 = jl_arg_split_spec (tv -> ub , morespec , 1 );
129
+ JL_GC_PUSH1 (& tv2 );
130
+ assert (tv2 != tv -> ub );
131
+ tv = jl_new_typevar (tv -> name , tv -> lb , tv2 );
132
+ JL_GC_POP ();
133
+ return (jl_value_t * )tv ;
134
+ }
135
+ else if (jl_is_type_type (t1 )) {
136
+ jl_value_t * p = jl_arg_split_spec (jl_tparam0 (t1 ), morespec , 0 );
137
+ JL_GC_PUSH1 (& p );
138
+ assert (p != jl_tparam0 (t1 ));
139
+ t1 = (jl_value_t * )jl_wrap_Type (p );
140
+ JL_GC_POP ();
141
+ return t1 ;
142
+ }
143
+ return t1 ;
144
+ }
145
+
76
146
77
147
// ----- Type Signature Subtype Testing ----- //
78
148
@@ -963,7 +1033,8 @@ static unsigned jl_typemap_list_count(jl_typemap_entry_t *ml)
963
1033
return count ;
964
1034
}
965
1035
966
- static void jl_typemap_level_insert_ (jl_typemap_level_t * cache , jl_typemap_entry_t * newrec , int8_t offs , const struct jl_typemap_info * tparams );
1036
+ static void jl_typemap_level_insert_ (jl_typemap_level_t * cache , jl_typemap_entry_t * newrec , int8_t offs ,
1037
+ const struct jl_typemap_info * tparams );
967
1038
static void jl_typemap_list_insert_sorted (jl_typemap_entry_t * * pml , jl_value_t * parent ,
968
1039
jl_typemap_entry_t * newrec , const struct jl_typemap_info * tparams );
969
1040
@@ -982,7 +1053,8 @@ static jl_typemap_level_t *jl_new_typemap_level(void)
982
1053
return cache ;
983
1054
}
984
1055
985
- static jl_typemap_level_t * jl_method_convert_list_to_cache (jl_typemap_entry_t * ml , jl_value_t * key , int8_t offs )
1056
+ static jl_typemap_level_t * jl_method_convert_list_to_cache (jl_typemap_entry_t * ml , jl_value_t * key , int8_t offs ,
1057
+ const struct jl_typemap_info * tparams )
986
1058
{
987
1059
jl_typemap_level_t * cache = jl_new_typemap_level ();
988
1060
cache -> key = key ;
@@ -991,7 +1063,7 @@ static jl_typemap_level_t *jl_method_convert_list_to_cache(jl_typemap_entry_t *m
991
1063
while (ml != (void * )jl_nothing ) {
992
1064
next = ml -> next ;
993
1065
ml -> next = (jl_typemap_entry_t * )jl_nothing ;
994
- jl_typemap_level_insert_ (cache , ml , offs , 0 );
1066
+ jl_typemap_level_insert_ (cache , ml , offs , tparams );
995
1067
ml = next ;
996
1068
}
997
1069
JL_GC_POP ();
@@ -1024,7 +1096,7 @@ static void jl_typemap_insert_generic(union jl_typemap_t *pml, jl_value_t *paren
1024
1096
1025
1097
unsigned count = jl_typemap_list_count (pml -> leaf );
1026
1098
if (count > MAX_METHLIST_COUNT ) {
1027
- pml -> node = jl_method_convert_list_to_cache (pml -> leaf , key , offs );
1099
+ pml -> node = jl_method_convert_list_to_cache (pml -> leaf , key , offs , tparams );
1028
1100
jl_gc_wb (parent , pml -> node );
1029
1101
jl_typemap_level_insert_ (pml -> node , newrec , offs , tparams );
1030
1102
return ;
@@ -1091,9 +1163,34 @@ static void jl_typemap_level_insert_(jl_typemap_level_t *cache, jl_typemap_entry
1091
1163
if (a0 && jl_typemap_array_insert_ (& cache -> name1 , a0 , newrec , (jl_value_t * )cache , 2 , offs , tparams ))
1092
1164
return ;
1093
1165
}
1094
- if (!t1 || jl_args_morespecific_typename (t1 )) {
1095
- jl_typemap_list_insert_ (& cache -> linear_leaf , (jl_value_t * )cache , newrec , tparams );
1096
- return ;
1166
+ int morespec = t1 ? jl_args_morespecific_typename (t1 , 1 ) : 1 ;
1167
+ if (morespec ) {
1168
+ if (morespec == 2 ) {
1169
+ // need to split this union into components more-specific than TypeName, and those less-specific
1170
+ jl_value_t * morespec_sig = NULL ;
1171
+ JL_GC_PUSH1 (& morespec_sig );
1172
+ morespec_sig = (jl_value_t * )jl_svec_copy (newrec -> sig -> parameters );
1173
+ if (l <= offs ) offs = l - 1 ; // bound Vararg to the length of the signature
1174
+ jl_value_t * elem = jl_tparam (newrec -> sig , offs );
1175
+ jl_svecset (morespec_sig , offs , jl_arg_split_spec (elem , 1 , 1 ));
1176
+ morespec_sig = (jl_value_t * )jl_apply_tuple_type ((jl_svec_t * )morespec_sig );
1177
+
1178
+ jl_typemap_entry_t * newrec2 = (jl_typemap_entry_t * )jl_gc_allocobj (sizeof (jl_typemap_entry_t ));
1179
+ jl_set_typeof (newrec2 , jl_typemap_entry_type );
1180
+ * newrec2 = * newrec ; // copy newrec to newrec2
1181
+ // TODO: mark newrec2 as a non-primary entry (ignored for lookup operations)
1182
+ newrec2 -> sig = (jl_datatype_t * )morespec_sig ;
1183
+ morespec_sig = (jl_value_t * )newrec2 ;
1184
+ jl_typemap_list_insert_ (& cache -> linear_leaf , (jl_value_t * )cache , newrec2 , tparams );
1185
+ JL_GC_POP ();
1186
+ // fall-through. newrec is unmodified since lessspec_sig <: newrec->sig,
1187
+ // and the user might try to look up the original sig directly
1188
+ // (either through invoke or exact extraction)
1189
+ }
1190
+ else {
1191
+ jl_typemap_list_insert_ (& cache -> linear_leaf , (jl_value_t * )cache , newrec , tparams );
1192
+ return ;
1193
+ }
1097
1194
}
1098
1195
jl_typemap_list_insert_ (& cache -> linear , (jl_value_t * )cache , newrec , tparams );
1099
1196
}
0 commit comments