@@ -139,7 +139,7 @@ static jl_varbinding_t *lookup(jl_stenv_t *e, jl_tvar_t *v) JL_GLOBALLY_ROOTED J
139139
140140static int statestack_get (jl_unionstate_t * st , int i ) JL_NOTSAFEPOINT
141141{
142- assert (i >= 0 && i <= 32767 ); // limited by the depth bit.
142+ assert (i >= 0 && i < 32767 ); // limited by the depth bit.
143143 // get the `i`th bit in an array of 32-bit words
144144 jl_bits_stack_t * stack = & st -> stack ;
145145 while (i >= sizeof (stack -> data ) * 8 ) {
@@ -153,7 +153,7 @@ static int statestack_get(jl_unionstate_t *st, int i) JL_NOTSAFEPOINT
153153
154154static void statestack_set (jl_unionstate_t * st , int i , int val ) JL_NOTSAFEPOINT
155155{
156- assert (i >= 0 && i <= 32767 ); // limited by the depth bit.
156+ assert (i >= 0 && i < 32767 ); // limited by the depth bit.
157157 jl_bits_stack_t * stack = & st -> stack ;
158158 while (i >= sizeof (stack -> data ) * 8 ) {
159159 if (__unlikely (stack -> next == NULL )) {
@@ -1448,11 +1448,14 @@ static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param)
14481448 }
14491449 if (jl_is_unionall (y )) {
14501450 jl_varbinding_t * xb = lookup (e , (jl_tvar_t * )x );
1451- if (xb == NULL ? !e -> ignore_free : !xb -> right ) {
1451+ jl_value_t * xub = xb == NULL ? ((jl_tvar_t * )x )-> ub : xb -> ub ;
1452+ if ((xb == NULL ? !e -> ignore_free : !xb -> right ) && xub != y ) {
14521453 // We'd better unwrap `y::UnionAll` eagerly if `x` isa ∀-var.
14531454 // This makes sure the following cases work correct:
14541455 // 1) `∀T <: Union{∃S, SomeType{P}} where {P}`: `S == Any` ==> `S >: T`
14551456 // 2) `∀T <: Union{∀T, SomeType{P}} where {P}`:
1457+ // note: if xub == y we'd better try `subtype_var` as `subtype_left_var`
1458+ // hit `==` based fast path.
14561459 return subtype_unionall (x , (jl_unionall_t * )y , e , 1 , param );
14571460 }
14581461 }
@@ -1590,6 +1593,8 @@ static int has_exists_typevar(jl_value_t *x, jl_stenv_t *e) JL_NOTSAFEPOINT
15901593 return env != NULL && jl_has_bound_typevars (x , env );
15911594}
15921595
1596+ static int forall_exists_subtype (jl_value_t * x , jl_value_t * y , jl_stenv_t * e , int param );
1597+
15931598static int local_forall_exists_subtype (jl_value_t * x , jl_value_t * y , jl_stenv_t * e , int param , int limit_slow )
15941599{
15951600 int16_t oldRmore = e -> Runions .more ;
@@ -1603,7 +1608,19 @@ static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t
16031608 return jl_subtype (x , y );
16041609 int has_exists = (!kindx && has_exists_typevar (x , e )) ||
16051610 (!kindy && has_exists_typevar (y , e ));
1606- if (has_exists && (is_exists_typevar (x , e ) != is_exists_typevar (y , e ))) {
1611+ if (!has_exists ) {
1612+ // We can use ∀_∃_subtype safely for ∃ free inputs.
1613+ // This helps to save some bits in union stack.
1614+ jl_saved_unionstate_t oldRunions ; push_unionstate (& oldRunions , & e -> Runions );
1615+ e -> Lunions .used = e -> Runions .used = 0 ;
1616+ e -> Lunions .depth = e -> Runions .depth = 0 ;
1617+ e -> Lunions .more = e -> Runions .more = 0 ;
1618+ int count = 0 , noRmore = 0 ;
1619+ sub = forall_exists_subtype (x , y , e , param );
1620+ pop_unionstate (& e -> Runions , & oldRunions );
1621+ return sub ;
1622+ }
1623+ if (is_exists_typevar (x , e ) != is_exists_typevar (y , e )) {
16071624 e -> Lunions .used = 0 ;
16081625 while (1 ) {
16091626 e -> Lunions .more = 0 ;
@@ -1617,7 +1634,7 @@ static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t
16171634 if (limit_slow == -1 )
16181635 limit_slow = kindx || kindy ;
16191636 jl_savedenv_t se ;
1620- save_env (e , & se , has_exists );
1637+ save_env (e , & se , 1 );
16211638 int count , limited = 0 , ini_count = 0 ;
16221639 jl_saved_unionstate_t latestLunions = {0 , 0 , 0 , NULL };
16231640 while (1 ) {
@@ -1635,26 +1652,26 @@ static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t
16351652 limited = 1 ;
16361653 if (!sub || !next_union_state (e , 0 ))
16371654 break ;
1638- if (limited || ! has_exists || e -> Runions .more == oldRmore ) {
1655+ if (limited || e -> Runions .more == oldRmore ) {
16391656 // re-save env and freeze the ∃decision for previous ∀Union
16401657 // Note: We could ignore the rest `∃Union` decisions if `x` and `y`
16411658 // contain no ∃ typevar, as they have no effect on env.
16421659 ini_count = count ;
16431660 push_unionstate (& latestLunions , & e -> Lunions );
1644- re_save_env (e , & se , has_exists );
1661+ re_save_env (e , & se , 1 );
16451662 e -> Runions .more = oldRmore ;
16461663 }
16471664 }
16481665 if (sub || e -> Runions .more == oldRmore )
16491666 break ;
16501667 assert (e -> Runions .more > oldRmore );
16511668 next_union_state (e , 1 );
1652- restore_env (e , & se , has_exists ); // also restore Rdepth here
1669+ restore_env (e , & se , 1 ); // also restore Rdepth here
16531670 e -> Runions .more = oldRmore ;
16541671 }
16551672 if (!sub )
16561673 assert (e -> Runions .more == oldRmore );
1657- else if (limited || ! has_exists )
1674+ else if (limited )
16581675 e -> Runions .more = oldRmore ;
16591676 free_env (& se );
16601677 return sub ;
0 commit comments