@@ -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