Skip to content

Commit adf8989

Browse files
committed
fixup! implement validation of Vararg type parameter on construction
1 parent 62c9f64 commit adf8989

File tree

7 files changed

+57
-39
lines changed

7 files changed

+57
-39
lines changed

src/codegen.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6738,7 +6738,7 @@ static jl_cgval_t emit_cfunction(jl_codectx_t &ctx, jl_value_t *output_type, con
67386738
sigt = NULL;
67396739
}
67406740
else {
6741-
sigt = jl_apply_tuple_type((jl_svec_t*)sigt);
6741+
sigt = jl_apply_tuple_type((jl_svec_t*)sigt, 1);
67426742
}
67436743
if (sigt && !(unionall_env && jl_has_typevar_from_unionall(rt, unionall_env))) {
67446744
unionall_env = NULL;
@@ -7242,7 +7242,7 @@ static jl_datatype_t *compute_va_type(jl_method_instance_t *lam, size_t nreq)
72427242
}
72437243
jl_svecset(tupargs, i-nreq, argType);
72447244
}
7245-
jl_value_t *typ = jl_apply_tuple_type(tupargs);
7245+
jl_value_t *typ = jl_apply_tuple_type(tupargs, 1);
72467246
JL_GC_POP();
72477247
return (jl_datatype_t*)typ;
72487248
}

src/gf.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,7 +1266,7 @@ static jl_method_instance_t *cache_method(
12661266
intptr_t max_varargs = get_max_varargs(definition, kwmt, mt, NULL);
12671267
jl_compilation_sig(tt, sparams, definition, max_varargs, &newparams);
12681268
if (newparams) {
1269-
temp2 = jl_apply_tuple_type(newparams);
1269+
temp2 = jl_apply_tuple_type(newparams, 1);
12701270
// Now there may be a problem: the widened signature is more general
12711271
// than just the given arguments, so it might conflict with another
12721272
// definition that does not have cache instances yet. To fix this, we
@@ -1389,7 +1389,7 @@ static jl_method_instance_t *cache_method(
13891389
}
13901390
}
13911391
if (newparams) {
1392-
simplett = (jl_datatype_t*)jl_apply_tuple_type(newparams);
1392+
simplett = (jl_datatype_t*)jl_apply_tuple_type(newparams, 1);
13931393
temp2 = (jl_value_t*)simplett;
13941394
}
13951395

@@ -2579,7 +2579,7 @@ JL_DLLEXPORT jl_value_t *jl_normalize_to_compilable_sig(jl_methtable_t *mt, jl_t
25792579
jl_compilation_sig(ti, env, m, max_varargs, &newparams);
25802580
int is_compileable = ((jl_datatype_t*)ti)->isdispatchtuple;
25812581
if (newparams) {
2582-
tt = (jl_datatype_t*)jl_apply_tuple_type(newparams);
2582+
tt = (jl_datatype_t*)jl_apply_tuple_type(newparams, 1);
25832583
if (!is_compileable) {
25842584
// compute new env, if used below
25852585
jl_value_t *ti = jl_type_intersection_env((jl_value_t*)tt, (jl_value_t*)m->sig, &newparams);
@@ -2834,7 +2834,7 @@ jl_value_t *jl_argtype_with_function_type(jl_value_t *ft JL_MAYBE_UNROOTED, jl_v
28342834
jl_svecset(tt, 0, ft);
28352835
for (size_t i = 0; i < l; i++)
28362836
jl_svecset(tt, i+1, jl_tparam(types,i));
2837-
tt = (jl_value_t*)jl_apply_tuple_type((jl_svec_t*)tt);
2837+
tt = (jl_value_t*)jl_apply_tuple_type((jl_svec_t*)tt, 1);
28382838
tt = jl_rewrap_unionall_(tt, types0);
28392839
JL_GC_POP();
28402840
return tt;

src/jltypes.c

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ JL_DLLEXPORT int jl_get_size(jl_value_t *val, size_t *pnt)
333333
if (jl_is_long(val)) {
334334
ssize_t slen = jl_unbox_long(val);
335335
if (slen < 0)
336-
jl_errorf("size or dimension is negative: %d", slen);
336+
jl_errorf("size or dimension is negative: %zd", slen);
337337
*pnt = slen;
338338
return 1;
339339
}
@@ -1435,17 +1435,6 @@ jl_datatype_t *jl_apply_cmpswap_type(jl_value_t *ty)
14351435
return rettyp;
14361436
}
14371437

1438-
// used to expand an NTuple to a flat representation
1439-
static jl_value_t *jl_tupletype_fill(size_t n, jl_value_t *v)
1440-
{
1441-
jl_value_t *p = NULL;
1442-
JL_GC_PUSH1(&p);
1443-
p = (jl_value_t*)jl_svec_fill(n, v);
1444-
p = jl_apply_tuple_type((jl_svec_t*)p);
1445-
JL_GC_POP();
1446-
return p;
1447-
}
1448-
14491438
JL_EXTENSION struct _jl_typestack_t {
14501439
jl_datatype_t *tt;
14511440
struct _jl_typestack_t *prev;
@@ -1796,13 +1785,13 @@ int _may_substitute_ub(jl_value_t *v, jl_tvar_t *var, int inside_inv, int *cov_c
17961785
// * `var` does not appear in invariant position
17971786
// * `var` appears at most once (in covariant position) and not in a `Vararg`
17981787
// unless the upper bound is concrete (diagonal rule)
1799-
int may_substitute_ub(jl_value_t *v, jl_tvar_t *var) JL_NOTSAFEPOINT
1788+
static int may_substitute_ub(jl_value_t *v, jl_tvar_t *var) JL_NOTSAFEPOINT
18001789
{
18011790
int cov_count = 0;
18021791
return _may_substitute_ub(v, var, 0, &cov_count);
18031792
}
18041793

1805-
jl_value_t *normalize_unionalls(jl_value_t *t)
1794+
static jl_value_t *normalize_unionalls(jl_value_t *t)
18061795
{
18071796
if (jl_is_uniontype(t)) {
18081797
jl_uniontype_t *u = (jl_uniontype_t*)t;
@@ -1840,6 +1829,29 @@ jl_value_t *normalize_unionalls(jl_value_t *t)
18401829
return t;
18411830
}
18421831

1832+
// used to expand an NTuple to a flat representation
1833+
static jl_value_t *jl_tupletype_fill(size_t n, jl_value_t *t, int check)
1834+
{
1835+
if (check) {
1836+
// Since we are skipping making the Vararg, we inline the checks from jl_wrap_vararg here
1837+
if (!jl_is_type(t) && !jl_is_typevar(t)) {
1838+
jl_type_error_rt("Vararg", "type", (jl_value_t*)jl_type_type, t);
1839+
}
1840+
// jl_wrap_vararg sometimes simplifies the type, so we only do this 1 time, instead of for each n later
1841+
t = normalize_unionalls(t);
1842+
jl_value_t *tw = extract_wrapper(t);
1843+
if (tw && t != tw && jl_types_equal(t, tw))
1844+
t = tw;
1845+
check = 0; // remember that checks are already done now
1846+
}
1847+
jl_value_t *p = NULL;
1848+
JL_GC_PUSH1(&p);
1849+
p = (jl_value_t*)jl_svec_fill(n, t);
1850+
p = jl_apply_tuple_type((jl_svec_t*)p, check);
1851+
JL_GC_POP();
1852+
return p;
1853+
}
1854+
18431855
static jl_value_t *_jl_instantiate_type_in_env(jl_value_t *ty, jl_unionall_t *env, jl_value_t **vals, jl_typeenv_t *prev, jl_typestack_t *stack);
18441856

18451857
static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **iparams, size_t ntp,
@@ -1962,7 +1974,7 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value
19621974
if (nt == 0 || !jl_has_free_typevars(va0)) {
19631975
if (ntp == 1) {
19641976
JL_GC_POP();
1965-
return jl_tupletype_fill(nt, va0);
1977+
return jl_tupletype_fill(nt, va0, 0);
19661978
}
19671979
size_t i, l;
19681980
p = jl_alloc_svec(ntp - 1 + nt);
@@ -1971,7 +1983,7 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value
19711983
l = ntp - 1 + nt;
19721984
for (; i < l; i++)
19731985
jl_svecset(p, i, va0);
1974-
jl_value_t *ndt = jl_apply_tuple_type(p);
1986+
jl_value_t *ndt = jl_apply_tuple_type(p, check);
19751987
JL_GC_POP();
19761988
return ndt;
19771989
}
@@ -2136,19 +2148,19 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value
21362148
return (jl_value_t*)ndt;
21372149
}
21382150

2139-
static jl_value_t *jl_apply_tuple_type_v_(jl_value_t **p, size_t np, jl_svec_t *params)
2151+
static jl_value_t *jl_apply_tuple_type_v_(jl_value_t **p, size_t np, jl_svec_t *params, int check)
21402152
{
2141-
return inst_datatype_inner(jl_anytuple_type, params, p, np, NULL, NULL, 1);
2153+
return inst_datatype_inner(jl_anytuple_type, params, p, np, NULL, NULL, check);
21422154
}
21432155

2144-
JL_DLLEXPORT jl_value_t *jl_apply_tuple_type(jl_svec_t *params)
2156+
JL_DLLEXPORT jl_value_t *jl_apply_tuple_type(jl_svec_t *params, int check)
21452157
{
2146-
return jl_apply_tuple_type_v_(jl_svec_data(params), jl_svec_len(params), params);
2158+
return jl_apply_tuple_type_v_(jl_svec_data(params), jl_svec_len(params), params, check);
21472159
}
21482160

21492161
JL_DLLEXPORT jl_value_t *jl_apply_tuple_type_v(jl_value_t **p, size_t np)
21502162
{
2151-
return jl_apply_tuple_type_v_(p, np, NULL);
2163+
return jl_apply_tuple_type_v_(p, np, NULL, 1);
21522164
}
21532165

21542166
jl_tupletype_t *jl_lookup_arg_tuple_type(jl_value_t *arg1, jl_value_t **args, size_t nargs, int leaf)
@@ -2211,13 +2223,16 @@ static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_
22112223
jl_datatype_t *tt = (jl_datatype_t*)t;
22122224
jl_svec_t *tp = tt->parameters;
22132225
size_t ntp = jl_svec_len(tp);
2214-
// Instantiate NTuple{3,Int}
2226+
// Instantiate Tuple{Vararg{T,N}} where T is fixed and N is known, such as Dims{3}
2227+
// And avoiding allocating the intermediate steps
22152228
// Note this does not instantiate Tuple{Vararg{Int,3}}; that's done in inst_datatype_inner
2229+
// Note this does not instantiate NTuple{N,T}, since it is unnecessary and inefficient to expand that now
2230+
// and it may skip the constructor checks for jl_wrap_vararg
22162231
if (jl_is_va_tuple(tt) && ntp == 1) {
2217-
// If this is a Tuple{Vararg{T,N}} with known N, expand it to
2232+
// If this is a Tuple{Vararg{T,N}} with known N and T, expand it to
22182233
// a fixed-length tuple
22192234
jl_value_t *T=NULL, *N=NULL;
2220-
jl_value_t *va = jl_unwrap_unionall(jl_tparam0(tt));
2235+
jl_value_t *va = jl_tparam0(tt);
22212236
jl_value_t *ttT = jl_unwrap_vararg(va);
22222237
jl_value_t *ttN = jl_unwrap_vararg_num(va);
22232238
jl_typeenv_t *e = env;
@@ -2228,11 +2243,12 @@ static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_
22282243
N = e->val;
22292244
e = e->prev;
22302245
}
2231-
if (T != NULL && N != NULL && jl_is_long(N)) {
2246+
if (T != NULL && N != NULL && jl_is_long(N) && !jl_has_free_typevars(T)) {
2247+
// Since this is skipping jl_wrap_vararg, we inline the checks from it here
22322248
ssize_t nt = jl_unbox_long(N);
22332249
if (nt < 0)
2234-
jl_errorf("size or dimension is negative: %zd", nt);
2235-
return jl_tupletype_fill(nt, T);
2250+
jl_errorf("Vararg length is negative: %zd", nt);
2251+
return jl_tupletype_fill(nt, T, check);
22362252
}
22372253
}
22382254
jl_value_t **iparams;
@@ -2429,6 +2445,8 @@ jl_vararg_t *jl_wrap_vararg(jl_value_t *t, jl_value_t *n, int check)
24292445
}
24302446
if (t) {
24312447
if (!jl_is_type(t) && !jl_is_typevar(t)) {
2448+
// Vararg{T} validation is slightly more strict than DataType parameters,
2449+
// since it only allows Types and not other things like isbits
24322450
jl_type_error_rt("Vararg", "type", (jl_value_t*)jl_type_type, t);
24332451
}
24342452
t = normalize_unionalls(t);
@@ -2729,7 +2747,7 @@ void jl_init_types(void) JL_GC_DISABLED
27292747
jl_anytuple_type->layout = NULL;
27302748

27312749
jl_typeofbottom_type->super = jl_wrap_Type(jl_bottom_type);
2732-
jl_emptytuple_type = (jl_datatype_t*)jl_apply_tuple_type(jl_emptysvec);
2750+
jl_emptytuple_type = (jl_datatype_t*)jl_apply_tuple_type(jl_emptysvec, 0);
27332751
jl_emptytuple = jl_gc_permobj(0, jl_emptytuple_type);
27342752
jl_emptytuple_type->instance = jl_emptytuple;
27352753

src/julia.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1563,7 +1563,7 @@ JL_DLLEXPORT jl_value_t *jl_apply_type1(jl_value_t *tc, jl_value_t *p1);
15631563
JL_DLLEXPORT jl_value_t *jl_apply_type2(jl_value_t *tc, jl_value_t *p1, jl_value_t *p2);
15641564
JL_DLLEXPORT jl_datatype_t *jl_apply_modify_type(jl_value_t *dt);
15651565
JL_DLLEXPORT jl_datatype_t *jl_apply_cmpswap_type(jl_value_t *dt);
1566-
JL_DLLEXPORT jl_value_t *jl_apply_tuple_type(jl_svec_t *params);
1566+
JL_DLLEXPORT jl_value_t *jl_apply_tuple_type(jl_svec_t *params, int check); // if uncertain, set check=1
15671567
JL_DLLEXPORT jl_value_t *jl_apply_tuple_type_v(jl_value_t **p, size_t np);
15681568
JL_DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name,
15691569
jl_module_t *module,

src/method.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -998,7 +998,7 @@ JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata,
998998
JL_GC_PUSH3(&f, &m, &argtype);
999999
size_t i, na = jl_svec_len(atypes);
10001000

1001-
argtype = jl_apply_tuple_type(atypes);
1001+
argtype = jl_apply_tuple_type(atypes, 1);
10021002
if (!jl_is_datatype(argtype))
10031003
jl_error("invalid type in method definition (Union{})");
10041004

src/precompile_utils.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ static void _compile_all_union(jl_value_t *sig)
120120
jl_svecset(p, i, ty);
121121
}
122122
}
123-
methsig = jl_apply_tuple_type(p);
123+
methsig = jl_apply_tuple_type(p, 1);
124124
methsig = jl_rewrap_unionall(methsig, sig);
125125
_compile_all_tvar_union(methsig);
126126
}

src/subtype.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3393,7 +3393,7 @@ static jl_value_t *intersect_tuple(jl_datatype_t *xd, jl_datatype_t *yd, jl_sten
33933393
else if (isy)
33943394
res = (jl_value_t*)yd;
33953395
else if (p)
3396-
res = jl_apply_tuple_type(p);
3396+
res = jl_apply_tuple_type(p, 1);
33973397
else
33983398
res = jl_apply_tuple_type_v(params, np);
33993399
}
@@ -4130,7 +4130,7 @@ static jl_value_t *switch_union_tuple(jl_value_t *a, jl_value_t *b)
41304130
ts[1] = jl_tparam(b, i);
41314131
jl_svecset(vec, i, jl_type_union(ts, 2));
41324132
}
4133-
jl_value_t *ans = jl_apply_tuple_type(vec);
4133+
jl_value_t *ans = jl_apply_tuple_type(vec, 1);
41344134
JL_GC_POP();
41354135
return ans;
41364136
}

0 commit comments

Comments
 (0)