Skip to content

Commit 1add963

Browse files
committed
Disallow raw vararg in subtype/typeintersect
1 parent fb8fd07 commit 1add963

File tree

2 files changed

+66
-80
lines changed

2 files changed

+66
-80
lines changed

src/subtype.c

+62-79
Original file line numberDiff line numberDiff line change
@@ -1190,24 +1190,6 @@ static int subtype_tuple(jl_datatype_t *xd, jl_datatype_t *yd, jl_stenv_t *e, in
11901190
return ans;
11911191
}
11921192

1193-
static int subtype_naked_vararg(jl_datatype_t *xd, jl_datatype_t *yd, jl_stenv_t *e, int param)
1194-
{
1195-
// Vararg: covariant in first parameter, invariant in second
1196-
jl_value_t *xp1=jl_unwrap_vararg(xd), *xp2=jl_unwrap_vararg_num(xd), *yp1=jl_unwrap_vararg(yd), *yp2=jl_unwrap_vararg_num(yd);
1197-
// in Vararg{T1} <: Vararg{T2}, need to check subtype twice to
1198-
// simulate the possibility of multiple arguments, which is needed
1199-
// to implement the diagonal rule correctly.
1200-
if (!subtype(xp1, yp1, e, param)) return 0;
1201-
if (!subtype(xp1, yp1, e, 1)) return 0;
1202-
e->invdepth++;
1203-
e->Rinvdepth++;
1204-
// Vararg{T,N} <: Vararg{T2,N2}; equate N and N2
1205-
int ans = forall_exists_equal(xp2, yp2, e);
1206-
e->invdepth--;
1207-
e->Rinvdepth--;
1208-
return ans;
1209-
}
1210-
12111193
// `param` means we are currently looking at a parameter of a type constructor
12121194
// (as opposed to being outside any type constructor, or comparing variable bounds).
12131195
// this is used to record the positions where type variables occur for the
@@ -1303,8 +1285,8 @@ static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param)
13031285
}
13041286
if (jl_is_unionall(y))
13051287
return subtype_unionall(x, (jl_unionall_t*)y, e, 1, param);
1306-
if ((jl_is_datatype(x) || jl_is_vararg_type(x)) &&
1307-
(jl_is_datatype(y) || jl_is_vararg_type(y))) {
1288+
assert(!jl_is_vararg_marker(x) && !jl_is_vararg_marker(y));
1289+
if (jl_is_datatype(x) && jl_is_datatype(y)) {
13081290
if (x == y) return 1;
13091291
if (y == (jl_value_t*)jl_any_type) return 1;
13101292
jl_datatype_t *xd = (jl_datatype_t*)x, *yd = (jl_datatype_t*)y;
@@ -1334,15 +1316,6 @@ static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param)
13341316
e->invdepth = saved;
13351317
return issub;
13361318
}
1337-
if (jl_is_vararg_marker(xd)) {
1338-
if (!jl_is_vararg_marker(yd))
1339-
return 0;
1340-
// N.B.: This case is only used for raw varargs that are not part
1341-
// of a tuple (those that are have special handling in subtype_tuple).
1342-
// Vararg isn't really a proper type, but it does sometimes show up
1343-
// as e.g. Type{Vararg}, so we'd like to handle that correctly.
1344-
return subtype_naked_vararg(xd, yd, e, param);
1345-
}
13461319
while (xd != jl_any_type && xd->name != yd->name) {
13471320
if (xd->super == NULL)
13481321
jl_errorf("circular type parameter constraint in definition of %s", jl_symbol_name(xd->name->name));
@@ -2723,6 +2696,51 @@ static int intersect_vararg_length(jl_value_t *v, ssize_t n, jl_stenv_t *e, int8
27232696
return 1;
27242697
}
27252698

2699+
static jl_value_t *intersect_invariant(jl_value_t *x, jl_value_t *y, jl_stenv_t *e);
2700+
static jl_value_t *intersect_varargs(jl_vararg_marker_t *vmx, jl_vararg_marker_t *vmy, jl_stenv_t *e, int param)
2701+
{
2702+
// Vararg: covariant in first parameter, invariant in second
2703+
jl_value_t *xp1=jl_unwrap_vararg(vmx), *xp2=jl_unwrap_vararg_num(vmx),
2704+
*yp1=jl_unwrap_vararg(vmy), *yp2=jl_unwrap_vararg_num(vmy);
2705+
// in Vararg{T1} <: Vararg{T2}, need to check subtype twice to
2706+
// simulate the possibility of multiple arguments, which is needed
2707+
// to implement the diagonal rule correctly.
2708+
if (intersect(xp1, yp1, e, param==0 ? 1 : param) == jl_bottom_type)
2709+
return jl_bottom_type;
2710+
jl_value_t *i2=NULL, *ii = intersect(xp1, yp1, e, 1);
2711+
if (ii == jl_bottom_type) return jl_bottom_type;
2712+
if (!xp2 && !yp2)
2713+
return jl_wrap_vararg(ii, NULL);
2714+
JL_GC_PUSH2(&ii, &i2);
2715+
if (xp2 && jl_is_typevar(xp2)) {
2716+
jl_varbinding_t *xb = lookup(e, (jl_tvar_t*)xp2);
2717+
if (xb) xb->intvalued = 1;
2718+
if (!yp2) {
2719+
i2 = bound_var_below((jl_tvar_t*)xp2, xb, e);
2720+
}
2721+
}
2722+
if (yp2 && jl_is_typevar(yp2)) {
2723+
jl_varbinding_t *yb = lookup(e, (jl_tvar_t*)yp2);
2724+
if (yb) yb->intvalued = 1;
2725+
if (!xp2) {
2726+
i2 = bound_var_below((jl_tvar_t*)yp2, yb, e);
2727+
}
2728+
}
2729+
if (xp2 && yp2) {
2730+
// Vararg{T,N} <: Vararg{T2,N2}; equate N and N2
2731+
i2 = intersect_invariant(xp2, yp2, e);
2732+
if (i2 == NULL || i2 == jl_bottom_type || (jl_is_long(i2) && jl_unbox_long(i2) < 0) ||
2733+
!((jl_is_typevar(i2) && ((jl_tvar_t*)i2)->lb == jl_bottom_type &&
2734+
((jl_tvar_t*)i2)->ub == (jl_value_t*)jl_any_type) || jl_is_long(i2))) {
2735+
i2 = jl_bottom_type;
2736+
}
2737+
}
2738+
ii = i2 == jl_bottom_type ? jl_bottom_type : jl_wrap_vararg(ii, i2);
2739+
JL_GC_POP();
2740+
return ii;
2741+
}
2742+
2743+
27262744
static jl_value_t *intersect_tuple(jl_datatype_t *xd, jl_datatype_t *yd, jl_stenv_t *e, int param)
27272745
{
27282746
size_t lx = jl_nparams(xd), ly = jl_nparams(yd);
@@ -2754,29 +2772,34 @@ static jl_value_t *intersect_tuple(jl_datatype_t *xd, jl_datatype_t *yd, jl_sten
27542772
res = (jl_value_t*)jl_apply_tuple_type_v(jl_svec_data(params), i);
27552773
break;
27562774
}
2757-
if (vx && !vy)
2758-
xi = jl_unwrap_vararg(xi);
2759-
if (vy && !vx)
2760-
yi = jl_unwrap_vararg(yi);
27612775
jl_varbinding_t *xb=NULL, *yb=NULL;
2776+
jl_value_t *ii = NULL;
27622777
if (vx && vy) {
27632778
// {A^n...,Vararg{T,N}} ∩ {Vararg{S,M}} = {(A∩S)^n...,Vararg{T∩S,N}} plus N = M-n
2764-
jl_value_t *xlen = jl_unwrap_vararg_num(jl_unwrap_unionall(xi));
2779+
jl_value_t *xlen = jl_unwrap_vararg_num(xi);
27652780
if (xlen && jl_is_typevar(xlen)) {
27662781
xb = lookup(e, (jl_tvar_t*)xlen);
27672782
if (xb)
27682783
xb->offset = ly-lx;
27692784
}
2770-
jl_value_t *ylen = jl_unwrap_vararg_num(jl_unwrap_unionall(yi));
2785+
jl_value_t *ylen = jl_unwrap_vararg_num(yi);
27712786
if (ylen && jl_is_typevar(ylen)) {
27722787
yb = lookup(e, (jl_tvar_t*)ylen);
27732788
if (yb)
27742789
yb->offset = lx-ly;
27752790
}
2791+
ii = intersect_varargs((jl_vararg_marker_t*)xi,
2792+
(jl_vararg_marker_t*)yi,
2793+
e, param);
2794+
if (xb) xb->offset = 0;
2795+
if (yb) yb->offset = 0;
2796+
} else {
2797+
if (vx)
2798+
xi = jl_unwrap_vararg(xi);
2799+
if (vy)
2800+
yi = jl_unwrap_vararg(yi);
2801+
ii = intersect(xi, yi, e, param == 0 ? 1 : param);
27762802
}
2777-
jl_value_t *ii = intersect(xi, yi, e, param == 0 ? 1 : param);
2778-
if (xb) xb->offset = 0;
2779-
if (yb) yb->offset = 0;
27802803
if (ii == jl_bottom_type) {
27812804
if (vx && vy) {
27822805
int len = i > j ? i : j;
@@ -3080,47 +3103,7 @@ static jl_value_t *intersect(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int pa
30803103
}
30813104
if (jl_is_unionall(y))
30823105
return intersect_unionall(x, (jl_unionall_t*)y, e, 1, param);
3083-
if (jl_is_vararg_marker(x) && jl_is_vararg_marker(y)) {
3084-
// Vararg: covariant in first parameter, invariant in second
3085-
jl_value_t *xp1=jl_unwrap_vararg(x), *xp2=jl_unwrap_vararg_num(x),
3086-
*yp1=jl_unwrap_vararg(y), *yp2=jl_unwrap_vararg_num(y);
3087-
// in Vararg{T1} <: Vararg{T2}, need to check subtype twice to
3088-
// simulate the possibility of multiple arguments, which is needed
3089-
// to implement the diagonal rule correctly.
3090-
if (intersect(xp1, yp1, e, param==0 ? 1 : param) == jl_bottom_type)
3091-
return jl_bottom_type;
3092-
jl_value_t *i2=NULL, *ii = intersect(xp1, yp1, e, 1);
3093-
if (ii == jl_bottom_type) return jl_bottom_type;
3094-
if (!xp2 && !yp2)
3095-
return jl_wrap_vararg(ii, NULL);
3096-
JL_GC_PUSH2(&ii, &i2);
3097-
if (xp2 && jl_is_typevar(xp2)) {
3098-
jl_varbinding_t *xb = lookup(e, (jl_tvar_t*)xp2);
3099-
if (xb) xb->intvalued = 1;
3100-
if (!yp2) {
3101-
i2 = bound_var_below((jl_tvar_t*)xp2, xb, e);
3102-
}
3103-
}
3104-
if (yp2 && jl_is_typevar(yp2)) {
3105-
jl_varbinding_t *yb = lookup(e, (jl_tvar_t*)yp2);
3106-
if (yb) yb->intvalued = 1;
3107-
if (!xp2) {
3108-
i2 = bound_var_below((jl_tvar_t*)yp2, yb, e);
3109-
}
3110-
}
3111-
if (xp2 && yp2) {
3112-
// Vararg{T,N} <: Vararg{T2,N2}; equate N and N2
3113-
i2 = intersect_invariant(xp2, yp2, e);
3114-
if (i2 == NULL || i2 == jl_bottom_type || (jl_is_long(i2) && jl_unbox_long(i2) < 0) ||
3115-
!((jl_is_typevar(i2) && ((jl_tvar_t*)i2)->lb == jl_bottom_type &&
3116-
((jl_tvar_t*)i2)->ub == (jl_value_t*)jl_any_type) || jl_is_long(i2))) {
3117-
i2 = jl_bottom_type;
3118-
}
3119-
}
3120-
ii = i2 == jl_bottom_type ? jl_bottom_type : jl_wrap_vararg(ii, i2);
3121-
JL_GC_POP();
3122-
return ii;
3123-
}
3106+
assert(!jl_is_vararg_marker(x) && !jl_is_vararg_marker(y));
31243107
if (jl_is_datatype(x) && jl_is_datatype(y)) {
31253108
jl_datatype_t *xd = (jl_datatype_t*)x, *yd = (jl_datatype_t*)y;
31263109
if (param < 2) {

src/typemap.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,10 @@ static int sig_match_by_type_simple(jl_value_t **types, size_t n, jl_tupletype_t
148148
if (jl_is_typevar(t))
149149
t = ((jl_tvar_t*)t)->ub;
150150
for (; i < n; i++) {
151-
if (!jl_subtype(types[i], t))
151+
jl_value_t *ti = types[i];
152+
if (i == n - 1 && jl_is_vararg_marker(ti))
153+
ti = jl_unwrap_vararg(ti);
154+
if (!jl_subtype(ti, t))
152155
return 0;
153156
}
154157
return 1;

0 commit comments

Comments
 (0)