@@ -1153,6 +1153,92 @@ static jl_value_t *extract_wrapper(jl_value_t *t JL_PROPAGATES_ROOT) JL_GLOBALLY
11531153 return NULL ;
11541154}
11551155
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+
11561242static 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 );
11571243
11581244static 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
11621248 jl_typename_t * tn = dt -> name ;
11631249 int istuple = (tn == jl_tuple_typename );
11641250 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+
11651256 // check type cache
11661257 if (cacheable ) {
11671258 size_t i ;
0 commit comments