@@ -2849,7 +2849,7 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
2849
2849
2850
2850
// I. Handle indirect innervars (make them behave like direct innervars).
2851
2851
// 1) record if btemp->lb/ub has indirect innervars.
2852
- // 2) substitute `vb->var` with `varval`/`varval `
2852
+ // 2) substitute `vb->var` with `varval`/`newvar `
2853
2853
// note: We only store the innervar in the outmost `varbinding`,
2854
2854
// thus we must check all inner env to ensure the recording/substitution
2855
2855
// is complete
@@ -2913,6 +2913,7 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
2913
2913
}
2914
2914
envind ++ ;
2915
2915
}
2916
+ // FIXME: innervar that depend on `ivar` should also be updated.
2916
2917
}
2917
2918
}
2918
2919
}
@@ -3028,7 +3029,8 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
3028
3029
}
3029
3030
3030
3031
if (vb -> innervars != NULL ) {
3031
- for (size_t i = 0 ; i < jl_array_nrows (vb -> innervars ); i ++ ) {
3032
+ size_t len = jl_array_nrows (vb -> innervars ), count = 0 ;
3033
+ for (size_t i = 0 ; i < len ; i ++ ) {
3032
3034
jl_tvar_t * var = (jl_tvar_t * )jl_array_ptr_ref (vb -> innervars , i );
3033
3035
// the `btemp->prev` walk is only giving a sort of post-order guarantee (since we are
3034
3036
// iterating 2 trees at once), so once we set `wrap`, there might remain other branches
@@ -3042,11 +3044,45 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
3042
3044
if (wrap ) {
3043
3045
if (wrap -> innervars == NULL )
3044
3046
wrap -> innervars = jl_alloc_array_1d (jl_array_any_type , 0 );
3047
+ // FIXME: `var`'s dependence should also be pushed into `wrap->innervars`.
3045
3048
jl_array_ptr_1d_push (wrap -> innervars , (jl_value_t * )var );
3049
+ jl_array_ptr_set (vb -> innervars , i , (jl_value_t * )NULL );
3046
3050
}
3047
- else if (res != jl_bottom_type ) {
3048
- if (jl_has_typevar (res , var ))
3049
- res = jl_type_unionall ((jl_tvar_t * )var , res );
3051
+ }
3052
+ for (size_t i = 0 ; i < len ; i ++ ) {
3053
+ jl_tvar_t * var = (jl_tvar_t * )jl_array_ptr_ref (vb -> innervars , i );
3054
+ if (var ) {
3055
+ if (count < i )
3056
+ jl_array_ptr_set (vb -> innervars , count , (jl_value_t * )var );
3057
+ count ++ ;
3058
+ }
3059
+ }
3060
+ if (count != len )
3061
+ jl_array_del_end (vb -> innervars , len - count );
3062
+ if (res != jl_bottom_type ) {
3063
+ while (count > 1 ) {
3064
+ int changed = 0 ;
3065
+ // Now need to re-sort the vb->innervars using the partial-ordering predicate `jl_has_typevar`.
3066
+ // If this is slow, we could possibly switch to a simpler graph sort than this triple loop, such as Tarjan's SCC.
3067
+ // But for now we use a variant on selection sort for partial-orders.
3068
+ for (size_t i = 0 ; i < count - 1 ; i ++ ) {
3069
+ jl_tvar_t * vari = (jl_tvar_t * )jl_array_ptr_ref (vb -> innervars , i );
3070
+ for (size_t j = i + 1 ; j < count ; j ++ ) {
3071
+ jl_tvar_t * varj = (jl_tvar_t * )jl_array_ptr_ref (vb -> innervars , j );
3072
+ if (jl_has_typevar (varj -> lb , vari ) || jl_has_typevar (varj -> ub , vari )) {
3073
+ jl_array_ptr_set (vb -> innervars , j , (jl_value_t * )vari );
3074
+ jl_array_ptr_set (vb -> innervars , i , (jl_value_t * )varj );
3075
+ changed = 1 ;
3076
+ break ;
3077
+ }
3078
+ }
3079
+ if (changed ) break ;
3080
+ }
3081
+ if (!changed ) break ;
3082
+ }
3083
+ for (size_t i = 0 ; i < count ; i ++ ) {
3084
+ jl_tvar_t * var = (jl_tvar_t * )jl_array_ptr_ref (vb -> innervars , i );
3085
+ res = jl_type_unionall (var , res );
3050
3086
}
3051
3087
}
3052
3088
}
0 commit comments