@@ -857,10 +857,13 @@ struct subtype_tuple_env {
857
857
jl_vararg_kind_t vvx , vvy ;
858
858
} JL_ROOTED_VALUE_COLLECTION ;
859
859
860
- static int subtype_tuple_varargs (struct subtype_tuple_env * env , jl_stenv_t * e , int param )
860
+ static int subtype_tuple_varargs (
861
+ jl_vararg_t * vtx , jl_vararg_t * vty ,
862
+ size_t vx , size_t vy ,
863
+ jl_stenv_t * e , int param )
861
864
{
862
- jl_value_t * xp0 = jl_unwrap_vararg (env -> vtx ); jl_value_t * xp1 = jl_unwrap_vararg_num (env -> vtx );
863
- jl_value_t * yp0 = jl_unwrap_vararg (env -> vty ); jl_value_t * yp1 = jl_unwrap_vararg_num (env -> vty );
865
+ jl_value_t * xp0 = jl_unwrap_vararg (vtx ); jl_value_t * xp1 = jl_unwrap_vararg_num (vtx );
866
+ jl_value_t * yp0 = jl_unwrap_vararg (vty ); jl_value_t * yp1 = jl_unwrap_vararg_num (vty );
864
867
865
868
if (!xp1 ) {
866
869
jl_value_t * yl = yp1 ;
@@ -877,31 +880,28 @@ static int subtype_tuple_varargs(struct subtype_tuple_env *env, jl_stenv_t *e, i
877
880
}
878
881
}
879
882
else {
880
- jl_value_t * xl = jl_unwrap_vararg_num (env -> vtx );
883
+ jl_value_t * xl = jl_unwrap_vararg_num (vtx );
881
884
if (jl_is_typevar (xl )) {
882
885
jl_varbinding_t * xlv = lookup (e , (jl_tvar_t * )xl );
883
886
if (xlv )
884
887
xl = xlv -> lb ;
885
888
}
886
889
if (jl_is_long (xl )) {
887
- if (jl_unbox_long (xl ) + 1 == env -> vx ) {
890
+ if (jl_unbox_long (xl ) + 1 == vx ) {
888
891
// LHS is exhausted. We're a subtype if the RHS is either
889
892
// exhausted as well or unbounded (in which case we need to
890
893
// set it to 0).
891
- if (jl_is_vararg (env -> vty )) {
892
- jl_value_t * yl = jl_unwrap_vararg_num (env -> vty );
893
- if (yl ) {
894
- if (jl_is_typevar (yl )) {
895
- jl_varbinding_t * ylv = lookup (e , (jl_tvar_t * )yl );
896
- if (ylv )
897
- yl = ylv -> lb ;
898
- }
899
- if (jl_is_long (yl )) {
900
- return jl_unbox_long (yl ) + 1 == env -> vy ;
901
- }
894
+ jl_value_t * yl = jl_unwrap_vararg_num (vty );
895
+ if (yl ) {
896
+ if (jl_is_typevar (yl )) {
897
+ jl_varbinding_t * ylv = lookup (e , (jl_tvar_t * )yl );
898
+ if (ylv )
899
+ yl = ylv -> lb ;
902
900
}
903
- }
904
- else {
901
+ if (jl_is_long (yl )) {
902
+ return jl_unbox_long (yl ) + 1 == vy ;
903
+ }
904
+ } else {
905
905
// We can skip the subtype check, but we still
906
906
// need to make sure to constrain the length of y
907
907
// to 0.
@@ -955,76 +955,74 @@ static int subtype_tuple_varargs(struct subtype_tuple_env *env, jl_stenv_t *e, i
955
955
e -> invdepth ++ ;
956
956
e -> Rinvdepth ++ ;
957
957
JL_GC_PUSH2 (& xp1 , & yp1 );
958
- if (xp1 && jl_is_long (xp1 ) && env -> vx != 1 )
959
- xp1 = jl_box_long (jl_unbox_long (xp1 ) - env -> vx + 1 );
960
- if (jl_is_long (yp1 ) && env -> vy != 1 )
961
- yp1 = jl_box_long (jl_unbox_long (yp1 ) - env -> vy + 1 );
958
+ if (xp1 && jl_is_long (xp1 ) && vx != 1 )
959
+ xp1 = jl_box_long (jl_unbox_long (xp1 ) - vx + 1 );
960
+ if (jl_is_long (yp1 ) && vy != 1 )
961
+ yp1 = jl_box_long (jl_unbox_long (yp1 ) - vy + 1 );
962
962
int ans = forall_exists_equal (xp1 , yp1 , e );
963
963
JL_GC_POP ();
964
964
e -> invdepth -- ;
965
965
e -> Rinvdepth -- ;
966
966
return ans ;
967
967
}
968
968
969
- static int subtype_tuple_tail (struct subtype_tuple_env * env , int8_t R , jl_stenv_t * e , int param )
969
+ static int subtype_tuple_tail (jl_datatype_t * xd , jl_datatype_t * yd , int8_t R , jl_stenv_t * e , int param )
970
970
{
971
- int x_reps = 1 ;
972
- loop : // while (i <= lx) {
973
- if (env -> i >= env -> lx )
974
- goto done ;
971
+ size_t lx = jl_nparams (xd );
972
+ size_t ly = jl_nparams (yd );
973
+ size_t i = 0 , j = 0 , vx = 0 , vy = 0 , x_reps = 1 ;
974
+ jl_value_t * lastx = NULL , * lasty = NULL ;
975
+ jl_value_t * xi = NULL , * yi = NULL ;
975
976
976
- /* Get the type in the current index. If necessary introduce tvars for
977
- varargs */
978
- jl_value_t * xi = NULL ;
979
- if (env -> i == env -> lx - 1 && env -> vvx ) {
980
- if (!env -> vtx ) {
981
- xi = jl_tparam (env -> xd , env -> i );
982
- assert (jl_is_vararg (xi ));
983
- env -> vtx = xi ;
977
+ for (;;) {
978
+ if (i < lx ) {
979
+ xi = jl_tparam (xd , i );
980
+ if (i == lx - 1 && (vx || jl_is_vararg (xi ))) {
981
+ vx += 1 ;
984
982
}
985
- xi = env -> vtx ;
986
- }
987
- else {
988
- xi = jl_tparam (env -> xd , env -> i );
989
983
}
990
984
991
- jl_value_t * yi = NULL ;
992
- if (env -> j < env -> ly ) {
993
- if (env -> j == env -> ly - 1 && env -> vvy ) {
994
- if (!env -> vty ) {
995
- yi = jl_tparam (env -> yd , env -> j );
996
- assert (jl_is_vararg (yi ));
997
- env -> vty = yi ;
998
- }
999
- yi = env -> vty ;
1000
- }
1001
- else {
1002
- yi = jl_tparam (env -> yd , env -> j );
985
+ if (j < ly ) {
986
+ yi = jl_tparam (yd , j );
987
+ if (j == ly - 1 && (vy || jl_is_vararg (yi ))) {
988
+ vy += 1 ;
1003
989
}
1004
990
}
1005
991
1006
- if (env -> vtx )
1007
- env -> vx += 1 ;
1008
- if (env -> vty )
1009
- env -> vy += 1 ;
992
+ if (i >= lx )
993
+ break ;
1010
994
1011
- if (env -> vx && env -> vy ) {
1012
- return subtype_tuple_varargs (env , e , param );
995
+ int all_varargs = vx && vy ;
996
+ if (!all_varargs && vy == 1 ) {
997
+ if (jl_unwrap_vararg (yi ) == (jl_value_t * )jl_any_type ) {
998
+ // Tuple{...} <: Tuple{..., Vararg{Any, _}}
999
+ // fast path all the type checks away
1000
+ xi = jl_tparam (xd , lx - 1 );
1001
+ if (jl_is_vararg (xi )) {
1002
+ all_varargs = 1 ;
1003
+ vy += lx - i ;
1004
+ vx = 1 ;
1005
+ } else {
1006
+ break ;
1007
+ }
1008
+ }
1013
1009
}
1014
1010
1015
- if (env -> vx ) {
1016
- xi = jl_unwrap_vararg (env -> vtx );
1017
- if (env -> j >= env -> ly )
1018
- return 1 ;
1019
- }
1020
- else if (env -> j >= env -> ly ) {
1021
- return 0 ;
1011
+ if (all_varargs ) {
1012
+ // Tuple{..., Vararg{xi, _}} <: Tuple{..., Vararg{yi, _}}
1013
+ return subtype_tuple_varargs (
1014
+ (jl_vararg_t * )xi ,
1015
+ (jl_vararg_t * )yi ,
1016
+ vx , vy , e , param );
1022
1017
}
1023
- int x_same = env -> lastx && jl_egal (xi , env -> lastx );
1024
- if (env -> vy ) {
1025
- yi = jl_unwrap_vararg (env -> vty );
1026
- if (!env -> vvx && yi == (jl_value_t * )jl_any_type )
1027
- goto done ; // if y ends in `Vararg{Any}` skip checking everything
1018
+
1019
+ if (j >= ly )
1020
+ return !!vx ;
1021
+
1022
+ xi = vx ? jl_unwrap_vararg (xi ) : xi ;
1023
+ int x_same = lastx && jl_egal (xi , lastx );
1024
+ if (vy ) {
1025
+ yi = jl_unwrap_vararg (yi );
1028
1026
// keep track of number of consecutive identical types compared to Vararg
1029
1027
if (x_same )
1030
1028
x_reps ++ ;
@@ -1036,8 +1034,8 @@ static int subtype_tuple_tail(struct subtype_tuple_env *env, int8_t R, jl_stenv_
1036
1034
// element type on the right more than twice.
1037
1035
}
1038
1036
else if (x_same &&
1039
- ((yi == env -> lasty && !jl_has_free_typevars (xi ) && !jl_has_free_typevars (yi )) ||
1040
- (yi == env -> lasty && !env -> vx && env -> vy && jl_is_concrete_type (xi )))) {
1037
+ ((yi == lasty && !jl_has_free_typevars (xi ) && !jl_has_free_typevars (yi )) ||
1038
+ (yi == lastx && !vx && vy && jl_is_concrete_type (xi )))) {
1041
1039
// fast path for repeated elements
1042
1040
}
1043
1041
else if (e -> Runions .depth == 0 && e -> Lunions .depth == 0 && !jl_has_free_typevars (xi ) && !jl_has_free_typevars (yi )) {
@@ -1048,73 +1046,71 @@ static int subtype_tuple_tail(struct subtype_tuple_env *env, int8_t R, jl_stenv_
1048
1046
else if (!subtype (xi , yi , e , param )) {
1049
1047
return 0 ;
1050
1048
}
1051
- env -> lastx = xi ; env -> lasty = yi ;
1052
- if (env -> i < env -> lx - 1 || !env -> vx )
1053
- env -> i ++ ;
1054
- if (env -> j < env -> ly - 1 || !env -> vy )
1055
- env -> j ++ ;
1056
-
1057
- goto loop ;
1058
- // } (from loop:)
1049
+ lastx = xi ; lasty = yi ;
1050
+ if (i < lx - 1 || !vx )
1051
+ i ++ ;
1052
+ if (j < ly - 1 || !vy )
1053
+ j ++ ;
1054
+ }
1059
1055
1060
- done :
1061
- if (!env -> vy && env -> j < env -> ly && jl_is_vararg (jl_tparam (env -> yd , env -> j )))
1062
- env -> vy += 1 ;
1063
- if (env -> vy && !env -> vx && env -> lx + 1 >= env -> ly ) {
1056
+ if (vy && !vx && lx + 1 >= ly ) {
1064
1057
// in Tuple{...,tn} <: Tuple{...,Vararg{T,N}}, check (lx+1-ly) <: N
1065
- if (!check_vararg_length (jl_tparam ( env -> yd , env -> ly - 1 ), env -> lx + 1 - env -> ly , e ))
1058
+ if (!check_vararg_length (yi , lx + 1 - ly , e ))
1066
1059
return 0 ;
1067
1060
}
1068
- return (env -> lx + env -> vx == env -> ly + env -> vy ) || (env -> vy && (env -> lx >= (env -> vx ? env -> ly : (env -> ly - 1 ))));
1061
+ return (lx + vx == ly + vy ) || (vy && (lx >= (vx ? ly : (ly - 1 ))));
1069
1062
}
1070
1063
1071
1064
static int subtype_tuple (jl_datatype_t * xd , jl_datatype_t * yd , jl_stenv_t * e , int param )
1072
1065
{
1073
- struct subtype_tuple_env env ;
1074
- env .xd = xd ;
1075
- env .yd = yd ;
1076
- env .lx = jl_nparams (xd );
1077
- env .ly = jl_nparams (yd );
1078
- if (env .lx == 0 && env .ly == 0 )
1066
+ // Check tuple compatibility based on tuple length only (fastpath)
1067
+ size_t lx = jl_nparams (xd );
1068
+ size_t ly = jl_nparams (yd );
1069
+
1070
+ if (lx == 0 && ly == 0 )
1079
1071
return 1 ;
1080
- env . i = env . j = 0 ;
1081
- env . vx = env . vy = 0 ;
1082
- env . vvx = env . vvy = JL_VARARG_NONE ;
1072
+
1073
+ jl_vararg_kind_t vvx = JL_VARARG_NONE ;
1074
+ jl_vararg_kind_t vvy = JL_VARARG_NONE ;
1083
1075
jl_varbinding_t * xbb = NULL ;
1084
- if (env .lx > 0 ) {
1085
- env .vvx = jl_vararg_kind (jl_tparam (env .xd , env .lx - 1 ));
1086
- if (env .vvx == JL_VARARG_BOUND )
1087
- xbb = lookup (e , (jl_tvar_t * )jl_unwrap_vararg_num (jl_tparam (env .xd , env .lx - 1 )));
1088
- }
1089
- if (env .ly > 0 )
1090
- env .vvy = jl_vararg_kind (jl_tparam (env .yd , env .ly - 1 ));
1091
- if (env .vvx != JL_VARARG_NONE && env .vvx != JL_VARARG_INT &&
1076
+ jl_value_t * xva = NULL , * yva = NULL ;
1077
+ if (lx > 0 ) {
1078
+ xva = jl_tparam (xd , lx - 1 );
1079
+ vvx = jl_vararg_kind (xva );
1080
+ if (vvx == JL_VARARG_BOUND )
1081
+ xbb = lookup (e , (jl_tvar_t * )jl_unwrap_vararg_num (xva ));
1082
+ }
1083
+ if (ly > 0 ) {
1084
+ yva = jl_tparam (yd , ly - 1 );
1085
+ vvy = jl_vararg_kind (yva );
1086
+ }
1087
+ if (vvx != JL_VARARG_NONE && vvx != JL_VARARG_INT &&
1092
1088
(!xbb || !jl_is_long (xbb -> lb ))) {
1093
- if (env . vvx == JL_VARARG_UNBOUND || (xbb && !xbb -> right )) {
1089
+ if (vvx == JL_VARARG_UNBOUND || (xbb && !xbb -> right )) {
1094
1090
// Unbounded on the LHS, bounded on the RHS
1095
- if (env . vvy == JL_VARARG_NONE || env . vvy == JL_VARARG_INT )
1091
+ if (vvy == JL_VARARG_NONE || vvy == JL_VARARG_INT )
1096
1092
return 0 ;
1097
- else if (env . lx < env . ly ) // Unbounded includes N == 0
1093
+ else if (lx < ly ) // Unbounded includes N == 0
1098
1094
return 0 ;
1099
1095
}
1100
- else if (env . vvy == JL_VARARG_NONE && !check_vararg_length (jl_tparam ( env . xd , env . lx - 1 ), env . ly + 1 - env . lx , e )) {
1096
+ else if (vvy == JL_VARARG_NONE && !check_vararg_length (xva , ly + 1 - lx , e )) {
1101
1097
return 0 ;
1102
1098
}
1103
1099
}
1104
1100
else {
1105
- size_t nx = env . lx ;
1106
- if (env . vvx == JL_VARARG_INT )
1107
- nx += jl_vararg_length (jl_tparam ( env . xd , env . lx - 1 ) ) - 1 ;
1101
+ size_t nx = lx ;
1102
+ if (vvx == JL_VARARG_INT )
1103
+ nx += jl_vararg_length (xva ) - 1 ;
1108
1104
else if (xbb && jl_is_long (xbb -> lb ))
1109
1105
nx += jl_unbox_long (xbb -> lb ) - 1 ;
1110
1106
else
1111
- assert (env . vvx == JL_VARARG_NONE );
1112
- size_t ny = env . ly ;
1113
- if (env . vvy == JL_VARARG_INT )
1114
- ny += jl_vararg_length (jl_tparam ( env . yd , env . ly - 1 ) ) - 1 ;
1115
- else if (env . vvy != JL_VARARG_NONE )
1107
+ assert (vvx == JL_VARARG_NONE );
1108
+ size_t ny = ly ;
1109
+ if (vvy == JL_VARARG_INT )
1110
+ ny += jl_vararg_length (yva ) - 1 ;
1111
+ else if (vvy != JL_VARARG_NONE )
1116
1112
ny -= 1 ;
1117
- if (env . vvy == JL_VARARG_NONE || env . vvy == JL_VARARG_INT ) {
1113
+ if (vvy == JL_VARARG_NONE || vvy == JL_VARARG_INT ) {
1118
1114
if (nx != ny )
1119
1115
return 0 ;
1120
1116
}
@@ -1125,11 +1121,7 @@ static int subtype_tuple(jl_datatype_t *xd, jl_datatype_t *yd, jl_stenv_t *e, in
1125
1121
}
1126
1122
1127
1123
param = (param == 0 ? 1 : param );
1128
- env .lastx = env .lasty = NULL ;
1129
- env .vtx = env .vty = NULL ;
1130
- JL_GC_PUSH2 (& env .vtx , & env .vty );
1131
- int ans = subtype_tuple_tail (& env , 0 , e , param );
1132
- JL_GC_POP ();
1124
+ int ans = subtype_tuple_tail (xd , yd , 0 , e , param );
1133
1125
return ans ;
1134
1126
}
1135
1127
0 commit comments