From dc58703f7601e374af459ef4fcf9d310fa4cd2f5 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Wed, 13 Sep 2023 10:38:46 +0200 Subject: [PATCH] Special-case Vararg handling when contained in an NTuple. --- src/jltypes.c | 18 +++++++++++++++++- test/core.jl | 10 ++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/jltypes.c b/src/jltypes.c index 7985174cf90c4..c049a8aa90d30 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -2248,7 +2248,23 @@ static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_ int i; for (i = 0; i < ntp; i++) { jl_value_t *elt = jl_svecref(tp, i); - jl_value_t *pi = inst_type_w_(elt, env, stack, check); + jl_value_t *pi; + if (jl_is_vararg(elt)) { + // special-case Vararg when contained in Tuple: normally we disallow non-type T, + // but NTuple{2,N} should work for StaticArrays.jl (see JuliaLang/julia#51244). + jl_vararg_t *va = (jl_vararg_t*)elt; + jl_value_t *T = NULL; + if (va->T && !jl_is_type(va->T) && !jl_is_typevar(va->T)) { + // temporarily swap out Vararg{T} for Vararg{Any} + T = va->T; + va->T = (jl_value_t*) jl_any_type; + } + pi = inst_type_w_(elt, env, stack, check); + if (T) + ((jl_vararg_t*)pi)->T = T; + } else { + pi = inst_type_w_(elt, env, stack, check); + } iparams[i] = pi; if (ip_heap) jl_gc_wb(ip_heap, pi); diff --git a/test/core.jl b/test/core.jl index 658cbd63da181..e7ce3b442f387 100644 --- a/test/core.jl +++ b/test/core.jl @@ -8097,3 +8097,13 @@ end let lin = Core.LineInfoNode(Base, first(methods(convert)), :foo, Int32(5), Int32(0)) @test convert(LineNumberNode, lin) == LineNumberNode(5, :foo) end + +# JuliaLang/julia#51228: bad Varargs should be disallowed +let + @test_throws TypeError Vararg{2,2} + # ... but should still be allowed inside of a Tuple + @test_broken Tuple{Vararg{2,2}} === Tuple{2,2} + # ... because it's used for the NTuple definition + @test NTuple{2,2} === Tuple{2,2} + # ... which is used by e.g. StaticArrays.jl +end