@@ -881,10 +881,20 @@ static jl_unionall_t *unalias_unionall(jl_unionall_t *u, jl_stenv_t *e)
881
881
// in the environment, rename to get a fresh var.
882
882
JL_GC_PUSH1 (& u );
883
883
while (btemp != NULL ) {
884
- if ( btemp -> var == u -> var ||
885
- // outer var can only refer to inner var if bounds changed
884
+ int aliased = btemp -> var == u -> var ||
885
+ // outer var can only refer to inner var if bounds changed (mainly for subtyping path)
886
886
(btemp -> lb != btemp -> var -> lb && jl_has_typevar (btemp -> lb , u -> var )) ||
887
- (btemp -> ub != btemp -> var -> ub && jl_has_typevar (btemp -> ub , u -> var ))) {
887
+ (btemp -> ub != btemp -> var -> ub && jl_has_typevar (btemp -> ub , u -> var ));
888
+ if (!aliased && btemp -> innervars != NULL ) {
889
+ for (size_t i = 0 ; i < jl_array_len (btemp -> innervars ); i ++ ) {
890
+ jl_tvar_t * ivar = (jl_tvar_t * )jl_array_ptr_ref (btemp -> innervars , i );
891
+ if (ivar == u -> var ) {
892
+ aliased = 1 ;
893
+ break ;
894
+ }
895
+ }
896
+ }
897
+ if (aliased ) {
888
898
u = jl_rename_unionall (u );
889
899
break ;
890
900
}
@@ -2839,7 +2849,7 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
2839
2849
2840
2850
// I. Handle indirect innervars (make them behave like direct innervars).
2841
2851
// 1) record if btemp->lb/ub has indirect innervars.
2842
- // 2) substitute `vb->var` with `varval`/`varval `
2852
+ // 2) substitute `vb->var` with `varval`/`newvar `
2843
2853
// note: We only store the innervar in the outmost `varbinding`,
2844
2854
// thus we must check all inner env to ensure the recording/substitution
2845
2855
// is complete
@@ -2903,6 +2913,7 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
2903
2913
}
2904
2914
envind ++ ;
2905
2915
}
2916
+ // FIXME: innervar that depend on `ivar` should also be updated.
2906
2917
}
2907
2918
}
2908
2919
}
@@ -3018,7 +3029,8 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
3018
3029
}
3019
3030
3020
3031
if (vb -> innervars != NULL ) {
3021
- 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 ++ ) {
3022
3034
jl_tvar_t * var = (jl_tvar_t * )jl_array_ptr_ref (vb -> innervars , i );
3023
3035
// the `btemp->prev` walk is only giving a sort of post-order guarantee (since we are
3024
3036
// iterating 2 trees at once), so once we set `wrap`, there might remain other branches
@@ -3032,11 +3044,45 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
3032
3044
if (wrap ) {
3033
3045
if (wrap -> innervars == NULL )
3034
3046
wrap -> innervars = jl_alloc_array_1d (jl_array_any_type , 0 );
3047
+ // FIXME: `var`'s dependence should also be pushed into `wrap->innervars`.
3035
3048
jl_array_ptr_1d_push (wrap -> innervars , (jl_value_t * )var );
3049
+ jl_array_ptr_set (vb -> innervars , i , (jl_value_t * )NULL );
3050
+ }
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 ;
3036
3082
}
3037
- else if ( res != jl_bottom_type ) {
3038
- if ( jl_has_typevar ( res , var ))
3039
- res = jl_type_unionall (( jl_tvar_t * ) var , res );
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 );
3040
3086
}
3041
3087
}
3042
3088
}
@@ -3056,23 +3102,16 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
3056
3102
static jl_value_t * intersect_unionall_ (jl_value_t * t , jl_unionall_t * u , jl_stenv_t * e , int8_t R , int param , jl_varbinding_t * vb )
3057
3103
{
3058
3104
jl_varbinding_t * btemp = e -> vars ;
3059
- // if the var for this unionall (based on identity) already appears somewhere
3060
- // in the environment, rename to get a fresh var.
3061
- // TODO: might need to look inside types in btemp->lb and btemp->ub
3062
3105
int envsize = 0 ;
3063
3106
while (btemp != NULL ) {
3064
3107
envsize ++ ;
3065
3108
if (envsize > 120 ) {
3066
3109
vb -> limited = 1 ;
3067
3110
return t ;
3068
3111
}
3069
- if (btemp -> var == u -> var || btemp -> lb == (jl_value_t * )u -> var ||
3070
- btemp -> ub == (jl_value_t * )u -> var ) {
3071
- u = jl_rename_unionall (u );
3072
- break ;
3073
- }
3074
3112
btemp = btemp -> prev ;
3075
3113
}
3114
+ u = unalias_unionall (u , e );
3076
3115
JL_GC_PUSH1 (& u );
3077
3116
vb -> var = u -> var ;
3078
3117
e -> vars = vb ;
0 commit comments