@@ -64,6 +64,7 @@ typedef struct jl_varbinding_t {
64
64
int8_t occurs_inv ; // occurs in invariant position
65
65
int8_t occurs_cov ; // # of occurrences in covariant position
66
66
int8_t concrete ; // 1 if another variable has a constraint forcing this one to be concrete
67
+ int8_t upper_bounded ; // var upper bound has been constrained
67
68
// in covariant position, we need to try constraining a variable in different ways:
68
69
// 0 - unconstrained
69
70
// 1 - less than
@@ -145,7 +146,7 @@ static void save_env(jl_stenv_t *e, jl_value_t **root, jl_savedenv_t *se)
145
146
v = v -> prev ;
146
147
}
147
148
* root = (jl_value_t * )jl_alloc_svec (len * 3 );
148
- se -> buf = (int8_t * )(len ? malloc (len * 2 ) : NULL );
149
+ se -> buf = (int8_t * )(len ? malloc (len * 3 ) : NULL );
149
150
#ifdef __clang_analyzer__
150
151
if (len )
151
152
memset (se -> buf , 0 , len * 2 );
@@ -157,6 +158,7 @@ static void save_env(jl_stenv_t *e, jl_value_t **root, jl_savedenv_t *se)
157
158
jl_svecset (* root , i ++ , (jl_value_t * )v -> innervars );
158
159
se -> buf [j ++ ] = v -> occurs_inv ;
159
160
se -> buf [j ++ ] = v -> occurs_cov ;
161
+ se -> buf [j ++ ] = v -> upper_bounded ;
160
162
v = v -> prev ;
161
163
}
162
164
se -> rdepth = e -> Runions .depth ;
@@ -176,13 +178,46 @@ static void restore_env(jl_stenv_t *e, jl_value_t *root, jl_savedenv_t *se) JL_N
176
178
assert (se -> buf );
177
179
v -> occurs_inv = se -> buf [j ++ ];
178
180
v -> occurs_cov = se -> buf [j ++ ];
181
+ v -> upper_bounded = se -> buf [j ++ ];
179
182
v = v -> prev ;
180
183
}
181
184
e -> Runions .depth = se -> rdepth ;
182
185
if (e -> envout && e -> envidx < e -> envsz )
183
186
memset (& e -> envout [e -> envidx ], 0 , (e -> envsz - e -> envidx )* sizeof (void * ));
184
187
}
185
188
189
+ // restore just occurs_inv and occurs_cov from `se` back to `e`
190
+ static void restore_var_counts (jl_stenv_t * e , jl_savedenv_t * se ) JL_NOTSAFEPOINT
191
+ {
192
+ jl_varbinding_t * v = e -> vars ;
193
+ int j = 0 ;
194
+ while (v != NULL ) {
195
+ assert (se -> buf );
196
+ v -> occurs_inv = se -> buf [j ++ ];
197
+ v -> occurs_cov = se -> buf [j ++ ];
198
+ j ++ ;
199
+ v = v -> prev ;
200
+ }
201
+ }
202
+
203
+ // compute the maximum of the occurence counts in `e` and `se`, storing them in `se`
204
+ static void max_var_counts (jl_stenv_t * e , jl_savedenv_t * se ) JL_NOTSAFEPOINT
205
+ {
206
+ jl_varbinding_t * v = e -> vars ;
207
+ int j = 0 ;
208
+ while (v != NULL ) {
209
+ assert (se -> buf );
210
+ if (v -> occurs_inv > se -> buf [j ])
211
+ se -> buf [j ] = v -> occurs_inv ;
212
+ j ++ ;
213
+ if (v -> occurs_cov > se -> buf [j ])
214
+ se -> buf [j ] = v -> occurs_cov ;
215
+ j ++ ;
216
+ j ++ ;
217
+ v = v -> prev ;
218
+ }
219
+ }
220
+
186
221
// type utilities
187
222
188
223
// quickly test that two types are identical
@@ -528,8 +563,10 @@ static int var_lt(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int param)
528
563
record_var_occurrence (bb , e , param );
529
564
if (!bb -> right ) // check ∀b . b<:a
530
565
return subtype_left_var (bb -> ub , a , e );
531
- if (bb -> ub == a )
566
+ if (bb -> ub == a ) {
567
+ bb -> upper_bounded = 1 ;
532
568
return 1 ;
569
+ }
533
570
if (!((bb -> lb == jl_bottom_type && !jl_is_type (a ) && !jl_is_typevar (a )) || subtype_ccheck (bb -> lb , a , e )))
534
571
return 0 ;
535
572
// for this to work we need to compute issub(left,right) before issub(right,left),
@@ -542,6 +579,7 @@ static int var_lt(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int param)
542
579
else {
543
580
bb -> ub = simple_meet (bb -> ub , a );
544
581
}
582
+ bb -> upper_bounded = 1 ;
545
583
assert (bb -> ub != (jl_value_t * )b );
546
584
if (jl_is_typevar (a )) {
547
585
jl_varbinding_t * aa = lookup (e , (jl_tvar_t * )a );
@@ -657,7 +695,7 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8
657
695
}
658
696
btemp = btemp -> prev ;
659
697
}
660
- jl_varbinding_t vb = { u -> var , u -> var -> lb , u -> var -> ub , R , NULL , 0 , 0 , 0 , 0 , e -> invdepth , 0 , NULL , e -> vars };
698
+ jl_varbinding_t vb = { u -> var , u -> var -> lb , u -> var -> ub , R , NULL , 0 , 0 , 0 , 0 , 0 , e -> invdepth , 0 , NULL , e -> vars };
661
699
JL_GC_PUSH4 (& u , & vb .lb , & vb .ub , & vb .innervars );
662
700
e -> vars = & vb ;
663
701
int ans ;
@@ -671,7 +709,9 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8
671
709
// fill variable values into `envout` up to `envsz`
672
710
if (e -> envidx < e -> envsz ) {
673
711
jl_value_t * val ;
674
- if (!vb .occurs_inv && vb .lb != jl_bottom_type )
712
+ if (vb .lb == vb .ub && vb .upper_bounded )
713
+ val = vb .lb ;
714
+ else if (!vb .occurs_inv && vb .lb != jl_bottom_type )
675
715
val = is_leaf_bound (vb .lb ) ? vb .lb : (jl_value_t * )jl_new_typevar (u -> var -> name , jl_bottom_type , vb .lb );
676
716
else if (vb .lb == vb .ub )
677
717
val = vb .lb ;
@@ -720,7 +760,7 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8
720
760
else if (!is_leaf_bound (vb .lb )) {
721
761
ans = 0 ;
722
762
}
723
- if (ans ) {
763
+ if (ans && vb . lb != vb . ub ) {
724
764
// if we occur as another var's lower bound, record the fact that we
725
765
// were concrete so that subtype can return true for that var.
726
766
/*
@@ -731,6 +771,17 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8
731
771
btemp = btemp->prev;
732
772
}
733
773
*/
774
+ // a diagonal var cannot be >: another diagonal var at a different invariant depth, e.g.
775
+ // Ref{Tuple{T,T} where T} !<: Ref{Tuple{T,T}} where T
776
+ btemp = vb .prev ;
777
+ while (btemp != NULL ) {
778
+ if (btemp -> lb == (jl_value_t * )u -> var && btemp -> depth0 != vb .depth0 &&
779
+ (btemp -> concrete || (btemp -> occurs_cov > 1 && btemp -> occurs_inv == 0 ))) {
780
+ ans = 0 ;
781
+ break ;
782
+ }
783
+ btemp = btemp -> prev ;
784
+ }
734
785
}
735
786
}
736
787
@@ -811,7 +862,7 @@ static int subtype_tuple(jl_datatype_t *xd, jl_datatype_t *yd, jl_stenv_t *e, in
811
862
else if ((vvy && ly > lx + 1 ) || (!vvy && lx != ly )) {
812
863
return 0 ;
813
864
}
814
- param = ( param == 0 ? 1 : param ) ;
865
+ param = 1 ;
815
866
jl_value_t * lastx = NULL , * lasty = NULL ;
816
867
while (i < lx ) {
817
868
jl_value_t * xi = jl_tparam (xd , i );
@@ -1067,6 +1118,12 @@ static int forall_exists_equal(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
1067
1118
{
1068
1119
if (obviously_egal (x , y )) return 1 ;
1069
1120
1121
+ jl_savedenv_t se ; // original env
1122
+ jl_savedenv_t me ; // for accumulating maximum var counts
1123
+ jl_value_t * saved = NULL ;
1124
+ save_env (e , & saved , & se );
1125
+ save_env (e , & saved , & me );
1126
+
1070
1127
jl_unionstate_t oldLunions = e -> Lunions ;
1071
1128
memset (e -> Lunions .stack , 0 , sizeof (e -> Lunions .stack ));
1072
1129
int sub ;
@@ -1096,11 +1153,27 @@ static int forall_exists_equal(jl_value_t *x, jl_value_t *y, jl_stenv_t *e)
1096
1153
statestack_set (& e -> Lunions , i , 0 );
1097
1154
lastset = set - 1 ;
1098
1155
statestack_set (& e -> Lunions , lastset , 1 );
1156
+ // take the maximum of var counts over all choices, to identify
1157
+ // diagonal variables better.
1158
+ max_var_counts (e , & me );
1159
+ restore_var_counts (e , & se );
1099
1160
}
1100
1161
}
1101
1162
1102
1163
e -> Lunions = oldLunions ;
1103
- return sub && subtype (y , x , e , 0 );
1164
+ if (sub ) {
1165
+ // avoid double-counting variables when we check subtype in both directions.
1166
+ // e.g. in `Ref{Tuple{T}}` the `T` occurs once even though we recursively
1167
+ // call `subtype` on it twice.
1168
+ max_var_counts (e , & me );
1169
+ restore_var_counts (e , & se );
1170
+ sub = subtype (y , x , e , 2 );
1171
+ max_var_counts (e , & me );
1172
+ restore_var_counts (e , & me );
1173
+ }
1174
+ free (se .buf );
1175
+ free (me .buf );
1176
+ return sub ;
1104
1177
}
1105
1178
1106
1179
static int exists_subtype (jl_value_t * x , jl_value_t * y , jl_stenv_t * e , jl_value_t * saved , jl_savedenv_t * se , int param )
@@ -1961,7 +2034,7 @@ static jl_value_t *intersect_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_
1961
2034
{
1962
2035
jl_value_t * res = NULL , * res2 = NULL , * save = NULL , * save2 = NULL ;
1963
2036
jl_savedenv_t se , se2 ;
1964
- jl_varbinding_t vb = { u -> var , u -> var -> lb , u -> var -> ub , R , NULL , 0 , 0 , 0 , 0 , e -> invdepth , 0 , NULL , e -> vars };
2037
+ jl_varbinding_t vb = { u -> var , u -> var -> lb , u -> var -> ub , R , NULL , 0 , 0 , 0 , 0 , 0 , e -> invdepth , 0 , NULL , e -> vars };
1965
2038
JL_GC_PUSH6 (& res , & save2 , & vb .lb , & vb .ub , & save , & vb .innervars );
1966
2039
save_env (e , & save , & se );
1967
2040
res = intersect_unionall_ (t , u , e , R , param , & vb );
0 commit comments