@@ -1153,6 +1153,92 @@ static jl_value_t *extract_wrapper(jl_value_t *t JL_PROPAGATES_ROOT) JL_GLOBALLY
1153
1153
return NULL ;
1154
1154
}
1155
1155
1156
+ int _may_substitute_ub (jl_value_t * v , jl_tvar_t * var , int inside_inv , int * cov_count ) JL_NOTSAFEPOINT
1157
+ {
1158
+ if (v == (jl_value_t * )var ) {
1159
+ if (inside_inv ) {
1160
+ return 0 ;
1161
+ }
1162
+ else {
1163
+ (* cov_count )++ ;
1164
+ return * cov_count <= 1 || jl_is_concrete_type (var -> ub );
1165
+ }
1166
+ }
1167
+ else if (jl_is_uniontype (v )) {
1168
+ return _may_substitute_ub (((jl_uniontype_t * )v )-> a , var , inside_inv , cov_count ) &&
1169
+ _may_substitute_ub (((jl_uniontype_t * )v )-> b , var , inside_inv , cov_count );
1170
+ }
1171
+ else if (jl_is_unionall (v )) {
1172
+ jl_unionall_t * ua = (jl_unionall_t * )v ;
1173
+ if (ua -> var == var )
1174
+ return 1 ;
1175
+ return _may_substitute_ub (ua -> var -> lb , var , inside_inv , cov_count ) &&
1176
+ _may_substitute_ub (ua -> var -> ub , var , inside_inv , cov_count ) &&
1177
+ _may_substitute_ub (ua -> body , var , inside_inv , cov_count );
1178
+ }
1179
+ else if (jl_is_datatype (v )) {
1180
+ int invar = inside_inv || !jl_is_tuple_type (v );
1181
+ for (size_t i = 0 ; i < jl_nparams (v ); i ++ ) {
1182
+ if (!_may_substitute_ub (jl_tparam (v ,i ), var , invar , cov_count ))
1183
+ return 0 ;
1184
+ }
1185
+ }
1186
+ else if (jl_is_vararg (v )) {
1187
+ jl_vararg_t * va = (jl_vararg_t * )v ;
1188
+ int old_count = * cov_count ;
1189
+ if (va -> T && !_may_substitute_ub (va -> T , var , inside_inv , cov_count ))
1190
+ return 0 ;
1191
+ if (* cov_count > old_count && !jl_is_concrete_type (var -> ub ))
1192
+ return 0 ;
1193
+ if (va -> N && !_may_substitute_ub (va -> N , var , 1 , cov_count ))
1194
+ return 0 ;
1195
+ }
1196
+ return 1 ;
1197
+ }
1198
+
1199
+ // Check whether `var` may be replaced with its upper bound `ub` in `v where var<:ub`
1200
+ // Conditions:
1201
+ // * `var` does not appear in invariant position
1202
+ // * `var` appears at most once (in covariant position) and not in a `Vararg`
1203
+ // unless the upper bound is concrete (diagonal rule)
1204
+ int may_substitute_ub (jl_value_t * v , jl_tvar_t * var ) JL_NOTSAFEPOINT
1205
+ {
1206
+ int cov_count = 0 ;
1207
+ return _may_substitute_ub (v , var , 0 , & cov_count );
1208
+ }
1209
+
1210
+ jl_value_t * normalize_unionalls (jl_value_t * t )
1211
+ {
1212
+ JL_GC_PUSH1 (& t );
1213
+ if (jl_is_uniontype (t )) {
1214
+ jl_uniontype_t * u = (jl_uniontype_t * )t ;
1215
+ jl_value_t * a = NULL ;
1216
+ jl_value_t * b = NULL ;
1217
+ JL_GC_PUSH2 (& a , & b );
1218
+ a = normalize_unionalls (u -> a );
1219
+ b = normalize_unionalls (u -> b );
1220
+ if (a != u -> a || b != u -> b ) {
1221
+ t = jl_new_struct (jl_uniontype_type , a , b );
1222
+ }
1223
+ JL_GC_POP ();
1224
+ }
1225
+ else if (jl_is_unionall (t )) {
1226
+ jl_unionall_t * u = (jl_unionall_t * )t ;
1227
+ jl_value_t * body = normalize_unionalls (u -> body );
1228
+ if (body != u -> body ) {
1229
+ JL_GC_PUSH1 (& body );
1230
+ t = jl_new_struct (jl_unionall_type , u -> var , body );
1231
+ JL_GC_POP ();
1232
+ u = (jl_unionall_t * )t ;
1233
+ }
1234
+
1235
+ if (u -> var -> lb == u -> var -> ub || may_substitute_ub (body , u -> var ))
1236
+ t = jl_instantiate_unionall (u , u -> var -> ub );
1237
+ }
1238
+ JL_GC_POP ();
1239
+ return t ;
1240
+ }
1241
+
1156
1242
static jl_value_t * _jl_instantiate_type_in_env (jl_value_t * ty , jl_unionall_t * env , jl_value_t * * vals , jl_typeenv_t * prev , jl_typestack_t * stack );
1157
1243
1158
1244
static jl_value_t * inst_datatype_inner (jl_datatype_t * dt , jl_svec_t * p , jl_value_t * * iparams , size_t ntp ,
@@ -1162,6 +1248,11 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value
1162
1248
jl_typename_t * tn = dt -> name ;
1163
1249
int istuple = (tn == jl_tuple_typename );
1164
1250
int isnamedtuple = (tn == jl_namedtuple_typename );
1251
+ if (dt -> name != jl_type_typename ) {
1252
+ for (size_t i = 0 ; i < ntp ; i ++ )
1253
+ iparams [i ] = normalize_unionalls (iparams [i ]);
1254
+ }
1255
+
1165
1256
// check type cache
1166
1257
if (cacheable ) {
1167
1258
size_t i ;
0 commit comments