@@ -872,10 +872,20 @@ static jl_unionall_t *unalias_unionall(jl_unionall_t *u, jl_stenv_t *e)
872
872
// in the environment, rename to get a fresh var.
873
873
JL_GC_PUSH1 (& u );
874
874
while (btemp != NULL ) {
875
- if ( btemp -> var == u -> var ||
876
- // outer var can only refer to inner var if bounds changed
875
+ int aliased = btemp -> var == u -> var ||
876
+ // outer var can only refer to inner var if bounds changed (mainly for subtyping path)
877
877
(btemp -> lb != btemp -> var -> lb && jl_has_typevar (btemp -> lb , u -> var )) ||
878
- (btemp -> ub != btemp -> var -> ub && jl_has_typevar (btemp -> ub , u -> var ))) {
878
+ (btemp -> ub != btemp -> var -> ub && jl_has_typevar (btemp -> ub , u -> var ));
879
+ if (!aliased && btemp -> innervars != NULL ) {
880
+ for (size_t i = 0 ; i < jl_array_len (btemp -> innervars ); i ++ ) {
881
+ jl_tvar_t * ivar = (jl_tvar_t * )jl_array_ptr_ref (btemp -> innervars , i );
882
+ if (ivar == u -> var ) {
883
+ aliased = 1 ;
884
+ break ;
885
+ }
886
+ }
887
+ }
888
+ if (aliased ) {
879
889
u = jl_rename_unionall (u );
880
890
break ;
881
891
}
@@ -2833,7 +2843,7 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
2833
2843
2834
2844
// I. Handle indirect innervars (make them behave like direct innervars).
2835
2845
// 1) record if btemp->lb/ub has indirect innervars.
2836
- // 2) subtitute `vb->var` with `varval`/`varval `
2846
+ // 2) substitute `vb->var` with `varval`/`newvar `
2837
2847
// note: We only store the innervar in the outmost `varbinding`,
2838
2848
// thus we must check all inner env to ensure the recording/subtitution
2839
2849
// is complete
@@ -2897,6 +2907,7 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
2897
2907
}
2898
2908
envind ++ ;
2899
2909
}
2910
+ // FIXME: innervar that depend on `ivar` should also be updated.
2900
2911
}
2901
2912
}
2902
2913
}
@@ -3012,7 +3023,8 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
3012
3023
}
3013
3024
3014
3025
if (vb -> innervars != NULL ) {
3015
- for (size_t i = 0 ; i < jl_array_len (vb -> innervars ); i ++ ) {
3026
+ size_t len = jl_array_nrows (vb -> innervars ), count = 0 ;
3027
+ for (size_t i = 0 ; i < len ; i ++ ) {
3016
3028
jl_tvar_t * var = (jl_tvar_t * )jl_array_ptr_ref (vb -> innervars , i );
3017
3029
// the `btemp->prev` walk is only giving a sort of post-order guarantee (since we are
3018
3030
// iterating 2 trees at once), so once we set `wrap`, there might remain other branches
@@ -3026,11 +3038,45 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
3026
3038
if (wrap ) {
3027
3039
if (wrap -> innervars == NULL )
3028
3040
wrap -> innervars = jl_alloc_array_1d (jl_array_any_type , 0 );
3041
+ // FIXME: `var`'s dependence should also be pushed into `wrap->innervars`.
3029
3042
jl_array_ptr_1d_push (wrap -> innervars , (jl_value_t * )var );
3043
+ jl_array_ptr_set (vb -> innervars , i , (jl_value_t * )NULL );
3044
+ }
3045
+ }
3046
+ for (size_t i = 0 ; i < len ; i ++ ) {
3047
+ jl_tvar_t * var = (jl_tvar_t * )jl_array_ptr_ref (vb -> innervars , i );
3048
+ if (var ) {
3049
+ if (count < i )
3050
+ jl_array_ptr_set (vb -> innervars , count , (jl_value_t * )var );
3051
+ count ++ ;
3052
+ }
3053
+ }
3054
+ if (count != len )
3055
+ jl_array_del_end (vb -> innervars , len - count );
3056
+ if (res != jl_bottom_type ) {
3057
+ while (count > 1 ) {
3058
+ int changed = 0 ;
3059
+ // Now need to re-sort the vb->innervars using the partial-ordering predicate `jl_has_typevar`.
3060
+ // If this is slow, we could possibly switch to a simpler graph sort than this triple loop, such as Tarjan's SCC.
3061
+ // But for now we use a variant on selection sort for partial-orders.
3062
+ for (size_t i = 0 ; i < count - 1 ; i ++ ) {
3063
+ jl_tvar_t * vari = (jl_tvar_t * )jl_array_ptr_ref (vb -> innervars , i );
3064
+ for (size_t j = i + 1 ; j < count ; j ++ ) {
3065
+ jl_tvar_t * varj = (jl_tvar_t * )jl_array_ptr_ref (vb -> innervars , j );
3066
+ if (jl_has_typevar (varj -> lb , vari ) || jl_has_typevar (varj -> ub , vari )) {
3067
+ jl_array_ptr_set (vb -> innervars , j , (jl_value_t * )vari );
3068
+ jl_array_ptr_set (vb -> innervars , i , (jl_value_t * )varj );
3069
+ changed = 1 ;
3070
+ break ;
3071
+ }
3072
+ }
3073
+ if (changed ) break ;
3074
+ }
3075
+ if (!changed ) break ;
3030
3076
}
3031
- else if ( res != jl_bottom_type ) {
3032
- if ( jl_has_typevar ( res , var ))
3033
- res = jl_type_unionall (( jl_tvar_t * ) var , res );
3077
+ for ( size_t i = 0 ; i < count ; i ++ ) {
3078
+ jl_tvar_t * var = ( jl_tvar_t * ) jl_array_ptr_ref ( vb -> innervars , i );
3079
+ res = jl_type_unionall (var , res );
3034
3080
}
3035
3081
}
3036
3082
}
@@ -3050,23 +3096,16 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
3050
3096
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 )
3051
3097
{
3052
3098
jl_varbinding_t * btemp = e -> vars ;
3053
- // if the var for this unionall (based on identity) already appears somewhere
3054
- // in the environment, rename to get a fresh var.
3055
- // TODO: might need to look inside types in btemp->lb and btemp->ub
3056
3099
int envsize = 0 ;
3057
3100
while (btemp != NULL ) {
3058
3101
envsize ++ ;
3059
3102
if (envsize > 120 ) {
3060
3103
vb -> limited = 1 ;
3061
3104
return t ;
3062
3105
}
3063
- if (btemp -> var == u -> var || btemp -> lb == (jl_value_t * )u -> var ||
3064
- btemp -> ub == (jl_value_t * )u -> var ) {
3065
- u = jl_rename_unionall (u );
3066
- break ;
3067
- }
3068
3106
btemp = btemp -> prev ;
3069
3107
}
3108
+ u = unalias_unionall (u , e );
3070
3109
JL_GC_PUSH1 (& u );
3071
3110
vb -> var = u -> var ;
3072
3111
e -> vars = vb ;
0 commit comments