@@ -2721,32 +2721,33 @@ static jl_value_t *omit_bad_union(jl_value_t *u, jl_tvar_t *t)
2721
2721
jl_tvar_t * var = ((jl_unionall_t * )u )-> var ;
2722
2722
jl_value_t * ub = var -> ub , * body = ((jl_unionall_t * )u )-> body ;
2723
2723
assert (var != t );
2724
- if (!jl_has_typevar (var -> lb , t )) {
2725
- JL_GC_PUSH3 (& ub , & body , & var );
2726
- body = omit_bad_union (body , t );
2727
- if (!jl_has_typevar (body , var )) {
2728
- res = body ;
2724
+ JL_GC_PUSH3 (& ub , & body , & var );
2725
+ body = omit_bad_union (body , t );
2726
+ if (!jl_has_typevar (body , var )) {
2727
+ res = body ;
2728
+ }
2729
+ else if (jl_has_typevar (var -> lb , t )) {
2730
+ res = jl_bottom_type ;
2731
+ }
2732
+ else {
2733
+ ub = omit_bad_union (ub , t );
2734
+ if (ub == jl_bottom_type && var -> lb != ub ) {
2735
+ res = jl_bottom_type ;
2729
2736
}
2730
- else {
2731
- ub = omit_bad_union (ub , t );
2732
- if (ub == jl_bottom_type && var -> lb != ub ) {
2733
- res = jl_bottom_type ;
2737
+ else if (obviously_egal (var -> lb , ub )) {
2738
+ JL_TRY {
2739
+ res = jl_substitute_var (body , var , ub );
2734
2740
}
2735
- else if (obviously_egal (var -> lb , ub )) {
2736
- JL_TRY {
2737
- res = jl_substitute_var (body , var , ub );
2738
- }
2739
- JL_CATCH {
2740
- res = jl_bottom_type ;
2741
- }
2741
+ JL_CATCH {
2742
+ res = jl_bottom_type ;
2742
2743
}
2743
- else {
2744
- if (ub != var -> ub ) {
2745
- var = jl_new_typevar (var -> name , var -> lb , ub );
2746
- body = jl_substitute_var (body , ((jl_unionall_t * )u )-> var , (jl_value_t * )var );
2747
- }
2748
- res = jl_new_struct (jl_unionall_type , var , body );
2744
+ }
2745
+ else {
2746
+ if (ub != var -> ub ) {
2747
+ var = jl_new_typevar (var -> name , var -> lb , ub );
2748
+ body = jl_substitute_var (body , ((jl_unionall_t * )u )-> var , (jl_value_t * )var );
2749
2749
}
2750
+ res = jl_new_struct (jl_unionall_type , var , body );
2750
2751
}
2751
2752
}
2752
2753
JL_GC_POP ();
@@ -2770,9 +2771,9 @@ static jl_value_t *omit_bad_union(jl_value_t *u, jl_tvar_t *t)
2770
2771
// Caller might not have rooted `res`
2771
2772
static jl_value_t * finish_unionall (jl_value_t * res JL_MAYBE_UNROOTED , jl_varbinding_t * vb , jl_unionall_t * u , jl_stenv_t * e )
2772
2773
{
2773
- jl_value_t * varval = NULL ;
2774
+ jl_value_t * varval = NULL , * ilb = NULL , * iub = NULL , * nivar = NULL ;
2774
2775
jl_tvar_t * newvar = vb -> var ;
2775
- JL_GC_PUSH2 (& res , & newvar );
2776
+ JL_GC_PUSH5 (& res , & newvar , & ilb , & iub , & nivar );
2776
2777
// try to reduce var to a single value
2777
2778
if (jl_is_long (vb -> ub ) && jl_is_typevar (vb -> lb )) {
2778
2779
varval = vb -> ub ;
@@ -2806,19 +2807,99 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
2806
2807
newvar = jl_new_typevar (vb -> var -> name , vb -> lb , vb -> ub );
2807
2808
2808
2809
// remove/replace/rewrap free occurrences of this var in the environment
2810
+
2811
+ // I. Handle indirect innervars (make them behave like direct innervars).
2812
+ // 1) record if btemp->lb/ub has indirect innervars.
2813
+ // 2) subtitute `vb->var` with `varval`/`varval`
2814
+ // note: We only store the innervar in the outmost `varbinding`,
2815
+ // thus we must check all inner env to ensure the recording/subtitution
2816
+ // is complete
2817
+ int len = current_env_length (e );
2818
+ int8_t * blinding_has_innerdep = (int8_t * )alloca (len );
2819
+ memset (blinding_has_innerdep , 0 , len );
2820
+ for (jl_varbinding_t * btemp = e -> vars ; btemp != NULL ; btemp = btemp -> prev ) {
2821
+ if (btemp -> innervars != NULL ) {
2822
+ for (size_t i = 0 ; i < jl_array_len (btemp -> innervars ); i ++ ) {
2823
+ jl_tvar_t * ivar = (jl_tvar_t * )jl_array_ptr_ref (btemp -> innervars , i );
2824
+ ilb = ivar -> lb ; iub = ivar -> ub ;
2825
+ int has_innerdep = 0 ;
2826
+ if (jl_has_typevar (ilb , vb -> var )) {
2827
+ has_innerdep = 1 ;
2828
+ if (varval ) {
2829
+ JL_TRY {
2830
+ ilb = jl_substitute_var (ilb , vb -> var , varval );
2831
+ }
2832
+ JL_CATCH {
2833
+ res = jl_bottom_type ;
2834
+ }
2835
+ }
2836
+ else if (newvar != vb -> var ) {
2837
+ ilb = jl_substitute_var (ilb , vb -> var , (jl_value_t * )newvar );
2838
+ }
2839
+ }
2840
+ if (jl_has_typevar (iub , vb -> var )) {
2841
+ has_innerdep = 1 ;
2842
+ if (varval ) {
2843
+ JL_TRY {
2844
+ iub = jl_substitute_var (iub , vb -> var , varval );
2845
+ }
2846
+ JL_CATCH {
2847
+ res = jl_bottom_type ;
2848
+ }
2849
+ }
2850
+ else if (newvar != vb -> var ) {
2851
+ iub = jl_substitute_var (iub , vb -> var , (jl_value_t * )newvar );
2852
+ }
2853
+ }
2854
+ if (!has_innerdep ) continue ;
2855
+ int need_subtitution = 0 ;
2856
+ if (ilb != ivar -> lb || iub != ivar -> ub ) {
2857
+ need_subtitution = 1 ;
2858
+ nivar = (jl_value_t * )jl_new_typevar (ivar -> name , ilb , iub );
2859
+ jl_array_ptr_set (btemp -> innervars , i , nivar );
2860
+ if (jl_has_typevar (res , ivar ))
2861
+ res = jl_substitute_var (res , ivar , nivar );
2862
+ }
2863
+ int envind = 0 ;
2864
+ for (jl_varbinding_t * btemp2 = e -> vars ; btemp2 != btemp -> prev ; btemp2 = btemp2 -> prev ) {
2865
+ if (jl_has_typevar (btemp2 -> lb , ivar )) {
2866
+ if (need_subtitution )
2867
+ btemp2 -> lb = jl_substitute_var (btemp2 -> lb , ivar , nivar );
2868
+ blinding_has_innerdep [envind ] |= 1 ;
2869
+ }
2870
+ if (jl_has_typevar (btemp2 -> ub , ivar )) {
2871
+ if (need_subtitution )
2872
+ btemp2 -> ub = jl_substitute_var (btemp2 -> ub , ivar , nivar );
2873
+ blinding_has_innerdep [envind ] |= 2 ;
2874
+ }
2875
+ envind ++ ;
2876
+ }
2877
+ }
2878
+ }
2879
+ }
2880
+ // II. Handle direct innervars.
2809
2881
jl_varbinding_t * wrap = NULL ;
2882
+ int envind = 0 ;
2810
2883
for (jl_varbinding_t * btemp = e -> vars ; btemp != NULL ; btemp = btemp -> prev ) {
2811
- if (jl_has_typevar (btemp -> lb , vb -> var )) {
2884
+ int has_innerdep = blinding_has_innerdep [envind ++ ];
2885
+ int lb_has_innerdep = has_innerdep & 1 ;
2886
+ int ub_has_innerdep = has_innerdep & 2 ;
2887
+ assert (!has_innerdep || btemp -> depth0 == vb -> depth0 );
2888
+ int lb_has_dep = jl_has_typevar (btemp -> lb , vb -> var );
2889
+ int ub_has_dep = jl_has_typevar (btemp -> ub , vb -> var );
2890
+ if (lb_has_innerdep || lb_has_dep ) {
2812
2891
if (vb -> lb == (jl_value_t * )btemp -> var ) {
2813
2892
JL_GC_POP ();
2814
2893
return jl_bottom_type ;
2815
2894
}
2816
2895
if (varval ) {
2817
- JL_TRY {
2818
- btemp -> lb = jl_substitute_var (btemp -> lb , vb -> var , varval );
2819
- }
2820
- JL_CATCH {
2821
- res = jl_bottom_type ;
2896
+ if (lb_has_dep ) { // inner substitution has been handled
2897
+ JL_TRY {
2898
+ btemp -> lb = jl_substitute_var (btemp -> lb , vb -> var , varval );
2899
+ }
2900
+ JL_CATCH {
2901
+ res = jl_bottom_type ;
2902
+ }
2822
2903
}
2823
2904
}
2824
2905
else if (btemp -> lb == (jl_value_t * )vb -> var ) {
@@ -2827,7 +2908,7 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
2827
2908
else if (btemp -> depth0 == vb -> depth0 && !jl_has_typevar (vb -> lb , btemp -> var ) && !jl_has_typevar (vb -> ub , btemp -> var )) {
2828
2909
// if our variable is T, and some outer variable has constraint S = Ref{T},
2829
2910
// move the `where T` outside `where S` instead of putting it here. issue #21243.
2830
- if (newvar != vb -> var )
2911
+ if (newvar != vb -> var && lb_has_dep ) // inner substitution has been handled
2831
2912
btemp -> lb = jl_substitute_var (btemp -> lb , vb -> var , (jl_value_t * )newvar );
2832
2913
wrap = btemp ;
2833
2914
}
@@ -2836,20 +2917,23 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
2836
2917
}
2837
2918
assert ((jl_value_t * )btemp -> var != btemp -> lb );
2838
2919
}
2839
- if (jl_has_typevar ( btemp -> ub , vb -> var ) ) {
2920
+ if (ub_has_innerdep || ub_has_dep ) {
2840
2921
if (vb -> ub == (jl_value_t * )btemp -> var ) {
2922
+ // TODO: handle `omit_bad_union` correctly if `ub_has_innerdep`
2841
2923
btemp -> ub = omit_bad_union (btemp -> ub , vb -> var );
2842
2924
if (btemp -> ub == jl_bottom_type && btemp -> ub != btemp -> lb ) {
2843
2925
JL_GC_POP ();
2844
2926
return jl_bottom_type ;
2845
2927
}
2846
2928
}
2847
2929
if (varval ) {
2848
- JL_TRY {
2849
- btemp -> ub = jl_substitute_var (btemp -> ub , vb -> var , varval );
2850
- }
2851
- JL_CATCH {
2852
- res = jl_bottom_type ;
2930
+ if (ub_has_dep ) { // inner substitution has been handled
2931
+ JL_TRY {
2932
+ btemp -> ub = jl_substitute_var (btemp -> ub , vb -> var , varval );
2933
+ }
2934
+ JL_CATCH {
2935
+ res = jl_bottom_type ;
2936
+ }
2853
2937
}
2854
2938
}
2855
2939
else if (btemp -> ub == (jl_value_t * )vb -> var ) {
@@ -2860,7 +2944,7 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind
2860
2944
btemp -> ub = vb -> ub ;
2861
2945
}
2862
2946
else if (btemp -> depth0 == vb -> depth0 && !jl_has_typevar (vb -> lb , btemp -> var ) && !jl_has_typevar (vb -> ub , btemp -> var )) {
2863
- if (newvar != vb -> var )
2947
+ if (newvar != vb -> var && ub_has_dep ) // inner substitution has been handled
2864
2948
btemp -> ub = jl_substitute_var (btemp -> ub , vb -> var , (jl_value_t * )newvar );
2865
2949
wrap = btemp ;
2866
2950
}
0 commit comments