@@ -708,16 +708,37 @@ static int var_occurs_invariant(jl_value_t *v, jl_tvar_t *var, int inv) JL_NOTSA
708708 return var_occurs_inside (v , var , 0 , 1 );
709709}
710710
711- static int with_tvar ( tvar_callback callback , void * context , jl_unionall_t * u , int8_t R , jl_stenv_t * e , int param )
711+ static jl_unionall_t * unalias_unionall ( jl_unionall_t * u , jl_stenv_t * e )
712712{
713+ jl_varbinding_t * btemp = e -> vars ;
714+ // if the var for this unionall (based on identity) already appears somewhere
715+ // in the environment, rename to get a fresh var.
716+ JL_GC_PUSH1 (& u );
717+ while (btemp != NULL ) {
718+ if (btemp -> var == u -> var ||
719+ // outer var can only refer to inner var if bounds changed
720+ (btemp -> lb != btemp -> var -> lb && jl_has_typevar (btemp -> lb , u -> var )) ||
721+ (btemp -> ub != btemp -> var -> ub && jl_has_typevar (btemp -> ub , u -> var ))) {
722+ u = rename_unionall (u );
723+ break ;
724+ }
725+ btemp = btemp -> prev ;
726+ }
727+ JL_GC_POP ();
728+ return u ;
729+ }
730+
731+ static int subtype_unionall (jl_value_t * t , jl_unionall_t * u , jl_stenv_t * e , int8_t R , int param )
732+ {
733+ u = unalias_unionall (u , e );
713734 jl_varbinding_t vb = { u -> var , u -> var -> lb , u -> var -> ub , R , 0 , 0 , 0 , 0 ,
714735 R ? e -> Rinvdepth : e -> invdepth , 0 , NULL , 0 , e -> vars };
715736 JL_GC_PUSH4 (& u , & vb .lb , & vb .ub , & vb .innervars );
716737 e -> vars = & vb ;
717738 int ans ;
718739 if (R ) {
719740 e -> envidx ++ ;
720- ans = callback ( context , R , e , param );
741+ ans = subtype ( t , u -> body , e , param );
721742 e -> envidx -- ;
722743 // widen Type{x} to typeof(x) in argument position
723744 if (!vb .occurs_inv )
@@ -750,7 +771,8 @@ static int with_tvar(tvar_callback callback, void *context, jl_unionall_t *u, in
750771 }
751772 }
752773 else {
753- ans = callback (context , R , e , param );
774+ ans = R ? subtype (t , u -> body , e , param ) :
775+ subtype (u -> body , t , e , param );
754776 }
755777
756778 // handle the "diagonal dispatch" rule, which says that a type var occurring more
@@ -802,53 +824,6 @@ static int with_tvar(tvar_callback callback, void *context, jl_unionall_t *u, in
802824 return ans ;
803825}
804826
805- static jl_unionall_t * unalias_unionall (jl_unionall_t * u , jl_stenv_t * e )
806- {
807- jl_varbinding_t * btemp = e -> vars ;
808- // if the var for this unionall (based on identity) already appears somewhere
809- // in the environment, rename to get a fresh var.
810- JL_GC_PUSH1 (& u );
811- while (btemp != NULL ) {
812- if (btemp -> var == u -> var ||
813- // outer var can only refer to inner var if bounds changed
814- (btemp -> lb != btemp -> var -> lb && jl_has_typevar (btemp -> lb , u -> var )) ||
815- (btemp -> ub != btemp -> var -> ub && jl_has_typevar (btemp -> ub , u -> var ))) {
816- u = rename_unionall (u );
817- break ;
818- }
819- btemp = btemp -> prev ;
820- }
821- JL_GC_POP ();
822- return u ;
823- }
824-
825- struct subtype_unionall_env {
826- jl_value_t * t ;
827- jl_value_t * ubody ;
828- };
829-
830- static int subtype_unionall_callback (struct subtype_unionall_env * env , int8_t R , jl_stenv_t * s , int param ) {
831- JL_GC_PROMISE_ROOTED (env -> t );
832- JL_GC_PROMISE_ROOTED (env -> ubody );
833- if (R ) {
834- return subtype (env -> t , env -> ubody , s , param );
835- }
836- else {
837- return subtype (env -> ubody , env -> t , s , param );
838- }
839- }
840-
841- // compare UnionAll type `u` to `t`. `R==1` if `u` came from the right side of A <: B.
842- static int subtype_unionall (jl_value_t * t , jl_unionall_t * u , jl_stenv_t * e , int8_t R , int param )
843- {
844- u = unalias_unionall (u , e );
845- struct subtype_unionall_env env = {t , u -> body };
846- JL_GC_PUSH1 (& u );
847- int res = with_tvar ((tvar_callback )subtype_unionall_callback , (void * )& env , u , R , e , param );
848- JL_GC_POP ();
849- return res ;
850- }
851-
852827// check n <: (length of vararg type v)
853828static int check_vararg_length (jl_value_t * v , ssize_t n , jl_stenv_t * e )
854829{
@@ -1004,21 +979,7 @@ static int subtype_tuple_tail(struct subtype_tuple_env *env, int8_t R, jl_stenv_
1004979 if (env -> i == env -> lx - 1 && env -> vvx ) {
1005980 if (!env -> vtx ) {
1006981 xi = jl_tparam (env -> xd , env -> i );
1007- // Unbounded vararg on the LHS without vararg on the RHS should
1008- // have been caught earlier.
1009- assert (env -> vvy || !jl_is_unionall (xi ));
1010- if (jl_is_unionall (xi )) {
1011- // TODO: If !var_occurs_inside(jl_tparam0(xid), p1, 0, 1),
1012- // we could avoid introducing the tvar into the environment
1013- jl_unionall_t * u = (jl_unionall_t * )xi ;
1014- u = unalias_unionall (u , e );
1015- env -> vtx = (jl_value_t * )u ;
1016- // goto loop, but with the tvar introduced
1017- JL_GC_PUSH1 (& u );
1018- int res = with_tvar ((tvar_callback )subtype_tuple_tail , env , u , 0 , e , param );
1019- JL_GC_POP ();
1020- return res ;
1021- }
982+ assert (jl_is_vararg (xi ));
1022983 env -> vtx = xi ;
1023984 }
1024985 xi = env -> vtx ;
@@ -1032,16 +993,7 @@ static int subtype_tuple_tail(struct subtype_tuple_env *env, int8_t R, jl_stenv_
1032993 if (env -> j == env -> ly - 1 && env -> vvy ) {
1033994 if (!env -> vty ) {
1034995 yi = jl_tparam (env -> yd , env -> j );
1035- if (jl_is_unionall (yi )) {
1036- jl_unionall_t * u = (jl_unionall_t * )yi ;
1037- u = unalias_unionall (u , e );
1038- env -> vty = (jl_value_t * )u ;
1039- // goto loop, but with the tvar introduced
1040- JL_GC_PUSH1 (& u );
1041- int res = with_tvar ((tvar_callback )subtype_tuple_tail , env , u , 1 , e , param );
1042- JL_GC_POP ();
1043- return res ;
1044- }
996+ assert (jl_is_vararg (yi ));
1045997 env -> vty = yi ;
1046998 }
1047999 yi = env -> vty ;
0 commit comments