@@ -128,7 +128,7 @@ static jl_varbinding_t *lookup(jl_stenv_t *e, jl_tvar_t *v) JL_GLOBALLY_ROOTED J
128128
129129static int statestack_get (jl_unionstate_t * st , int i ) JL_NOTSAFEPOINT
130130{
131- assert (i >= 0 && i <= 32767 ); // limited by the depth bit.
131+ assert (i >= 0 && i < 32767 ); // limited by the depth bit.
132132 // get the `i`th bit in an array of 32-bit words
133133 jl_bits_stack_t * stack = & st -> stack ;
134134 while (i >= sizeof (stack -> data ) * 8 ) {
@@ -142,7 +142,7 @@ static int statestack_get(jl_unionstate_t *st, int i) JL_NOTSAFEPOINT
142142
143143static void statestack_set (jl_unionstate_t * st , int i , int val ) JL_NOTSAFEPOINT
144144{
145- assert (i >= 0 && i <= 32767 ); // limited by the depth bit.
145+ assert (i >= 0 && i < 32767 ); // limited by the depth bit.
146146 jl_bits_stack_t * stack = & st -> stack ;
147147 while (i >= sizeof (stack -> data ) * 8 ) {
148148 if (__unlikely (stack -> next == NULL )) {
@@ -1409,11 +1409,14 @@ static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param)
14091409 }
14101410 if (jl_is_unionall (y )) {
14111411 jl_varbinding_t * xb = lookup (e , (jl_tvar_t * )x );
1412- if (xb == NULL ? !e -> ignore_free : !xb -> right ) {
1412+ jl_value_t * xub = xb == NULL ? ((jl_tvar_t * )x )-> ub : xb -> ub ;
1413+ if ((xb == NULL ? !e -> ignore_free : !xb -> right ) && xub != y ) {
14131414 // We'd better unwrap `y::UnionAll` eagerly if `x` isa ∀-var.
14141415 // This makes sure the following cases work correct:
14151416 // 1) `∀T <: Union{∃S, SomeType{P}} where {P}`: `S == Any` ==> `S >: T`
14161417 // 2) `∀T <: Union{∀T, SomeType{P}} where {P}`:
1418+ // note: if xub == y we'd better try `subtype_var` as `subtype_left_var`
1419+ // hit `==` based fast path.
14171420 return subtype_unionall (x , (jl_unionall_t * )y , e , 1 , param );
14181421 }
14191422 }
@@ -1551,6 +1554,8 @@ static int has_exists_typevar(jl_value_t *x, jl_stenv_t *e) JL_NOTSAFEPOINT
15511554 return env != NULL && jl_has_bound_typevars (x , env );
15521555}
15531556
1557+ static int forall_exists_subtype (jl_value_t * x , jl_value_t * y , jl_stenv_t * e , int param );
1558+
15541559static int local_forall_exists_subtype (jl_value_t * x , jl_value_t * y , jl_stenv_t * e , int param , int limit_slow )
15551560{
15561561 int16_t oldRmore = e -> Runions .more ;
@@ -1564,7 +1569,18 @@ static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t
15641569 return jl_subtype (x , y );
15651570 int has_exists = (!kindx && has_exists_typevar (x , e )) ||
15661571 (!kindy && has_exists_typevar (y , e ));
1567- if (has_exists && (is_exists_typevar (x , e ) != is_exists_typevar (y , e ))) {
1572+ if (!has_exists ) {
1573+ // We can use ∀_∃_subtype safely for ∃ free inputs.
1574+ // This helps to save some bits in union stack.
1575+ jl_saved_unionstate_t oldRunions ; push_unionstate (& oldRunions , & e -> Runions );
1576+ e -> Lunions .used = e -> Runions .used = 0 ;
1577+ e -> Lunions .depth = e -> Runions .depth = 0 ;
1578+ e -> Lunions .more = e -> Runions .more = 0 ;
1579+ sub = forall_exists_subtype (x , y , e , param );
1580+ pop_unionstate (& e -> Runions , & oldRunions );
1581+ return sub ;
1582+ }
1583+ if (is_exists_typevar (x , e ) != is_exists_typevar (y , e )) {
15681584 e -> Lunions .used = 0 ;
15691585 while (1 ) {
15701586 e -> Lunions .more = 0 ;
@@ -1578,7 +1594,7 @@ static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t
15781594 if (limit_slow == -1 )
15791595 limit_slow = kindx || kindy ;
15801596 jl_savedenv_t se ;
1581- save_env (e , & se , has_exists );
1597+ save_env (e , & se , 1 );
15821598 int count , limited = 0 , ini_count = 0 ;
15831599 jl_saved_unionstate_t latestLunions = {0 , 0 , 0 , NULL };
15841600 while (1 ) {
@@ -1596,26 +1612,26 @@ static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t
15961612 limited = 1 ;
15971613 if (!sub || !next_union_state (e , 0 ))
15981614 break ;
1599- if (limited || ! has_exists || e -> Runions .more == oldRmore ) {
1615+ if (limited || e -> Runions .more == oldRmore ) {
16001616 // re-save env and freeze the ∃decision for previous ∀Union
16011617 // Note: We could ignore the rest `∃Union` decisions if `x` and `y`
16021618 // contain no ∃ typevar, as they have no effect on env.
16031619 ini_count = count ;
16041620 push_unionstate (& latestLunions , & e -> Lunions );
1605- re_save_env (e , & se , has_exists );
1621+ re_save_env (e , & se , 1 );
16061622 e -> Runions .more = oldRmore ;
16071623 }
16081624 }
16091625 if (sub || e -> Runions .more == oldRmore )
16101626 break ;
16111627 assert (e -> Runions .more > oldRmore );
16121628 next_union_state (e , 1 );
1613- restore_env (e , & se , has_exists ); // also restore Rdepth here
1629+ restore_env (e , & se , 1 ); // also restore Rdepth here
16141630 e -> Runions .more = oldRmore ;
16151631 }
16161632 if (!sub )
16171633 assert (e -> Runions .more == oldRmore );
1618- else if (limited || ! has_exists )
1634+ else if (limited )
16191635 e -> Runions .more = oldRmore ;
16201636 free_env (& se );
16211637 return sub ;
0 commit comments