Skip to content

Commit fb8fd07

Browse files
committed
Disallow Vararg in UnionAll
1 parent 43c2871 commit fb8fd07

25 files changed

+258
-196
lines changed

base/boot.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ TypeVar(n::Symbol, @nospecialize(lb), @nospecialize(ub)) = _typevar(n, lb, ub)
253253

254254
UnionAll(v::TypeVar, @nospecialize(t)) = ccall(:jl_type_unionall, Any, (Any, Any), v, t)
255255

256-
const Vararg{T, N} = VarargMarker{T, N}
256+
const Vararg = ccall(:jl_toplevel_eval_in, Any, (Any, Any), Core, _expr(:new, VarargMarker))
257257

258258
# let the compiler assume that calling Union{} as a constructor does not need
259259
# to be considered ever (which comes up often as Type{<:T})

base/combinatorics.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ julia> 2^2 * 3^3
307307
!!! compat "Julia 1.6"
308308
The method that accepts a tuple requires Julia 1.6 or later.
309309
"""
310-
function nextprod(a::Union{Tuple{Vararg{<:Integer}},AbstractVector{<:Integer}}, x::Real)
310+
function nextprod(a::Union{Tuple{Vararg{Integer}},AbstractVector{<:Integer}}, x::Real)
311311
if x > typemax(Int)
312312
throw(ArgumentError("unsafe for x > typemax(Int), got $x"))
313313
end

base/compiler/tfuncs.jl

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -489,9 +489,8 @@ function typeof_concrete_vararg(t::DataType)
489489
for i = 1:np
490490
p = t.parameters[i]
491491
if i == np && isvarargtype(p)
492-
pp = unwrap_unionall(p)
493-
if isconcretetype(pp.T) && pp.N isa TypeVar
494-
return rewrap_unionall(Type{Tuple{t.parameters[1:np-1]..., pp}}, p)
492+
if isdefined(p, :T) && !isdefined(p, :N) && isconcretetype(p.T)
493+
return Type{Tuple{t.parameters[1:np-1]..., Vararg{p.T, N}}} where N
495494
end
496495
elseif !isconcretetype(p)
497496
break
@@ -555,18 +554,32 @@ function typeassert_type_instance(@nospecialize(v), @nospecialize(t))
555554
widev = widenconst(v)
556555
if widev <: t
557556
return v
558-
elseif typeintersect(widev, t) === Bottom
557+
end
558+
ti = typeintersect(widev, t)
559+
if ti === Bottom
559560
return Bottom
560561
end
561562
@assert widev <: Tuple
562563
new_fields = Vector{Any}(undef, length(v.fields))
563564
for i = 1:length(new_fields)
564-
new_fields[i] = typeassert_type_instance(v.fields[i], getfield_tfunc(t, Const(i)))
565-
if new_fields[i] === Bottom
566-
return Bottom
565+
if isa(v.fields[i], Core.VarargMarker)
566+
new_fields[i] = v.fields[i]
567+
else
568+
new_fields[i] = typeassert_type_instance(v.fields[i], getfield_tfunc(t, Const(i)))
569+
if new_fields[i] === Bottom
570+
return Bottom
571+
end
567572
end
568573
end
569-
return tuple_tfunc(new_fields)
574+
tt = tuple_tfunc(new_fields)
575+
if isa(tt, PartialStruct)
576+
if !(widenconst(tt) <: ti)
577+
return PartialStruct(ti, tt.fields)
578+
end
579+
elseif !(tt <: ti)
580+
return ti
581+
end
582+
return tt
570583
elseif isa(v, Conditional)
571584
if !(Bool <: t)
572585
return Bottom
@@ -1133,7 +1146,7 @@ function apply_type_tfunc(@nospecialize(headtypetype), @nospecialize args...)
11331146
return Any
11341147
end
11351148
if !isempty(args) && isvarargtype(args[end])
1136-
return isvarargtype(headtype) ? Any : Type
1149+
return isvarargtype(headtype) ? Core.VarargMarker : Type
11371150
end
11381151
largs = length(args)
11391152
if headtype === Union
@@ -1175,7 +1188,7 @@ function apply_type_tfunc(@nospecialize(headtypetype), @nospecialize args...)
11751188
end
11761189
return allconst ? Const(ty) : Type{ty}
11771190
end
1178-
istuple = (headtype == Tuple)
1191+
istuple = isa(headtype, Type) && (headtype == Tuple)
11791192
if !istuple && !isa(headtype, UnionAll) && !isvarargtype(headtype)
11801193
return Union{}
11811194
end
@@ -1260,11 +1273,11 @@ function apply_type_tfunc(@nospecialize(headtypetype), @nospecialize args...)
12601273
catch ex
12611274
# type instantiation might fail if one of the type parameters
12621275
# doesn't match, which could happen if a type estimate is too coarse
1263-
return isvarargtype(headtype) ? Any : Type{<:headtype}
1276+
return isvarargtype(headtype) ? Core.VarargMarker : Type{<:headtype}
12641277
end
12651278
!uncertain && canconst && return Const(appl)
12661279
if isvarargtype(appl)
1267-
return Any
1280+
return Core.VarargMarker
12681281
end
12691282
if istuple
12701283
return Type{<:appl}
@@ -1316,7 +1329,7 @@ function tuple_tfunc(atypes::Vector{Any})
13161329
x = atypes[i]
13171330
# TODO ignore singleton Const (don't forget to update cache logic if you implement this)
13181331
if !anyinfo
1319-
anyinfo = !isa(x, Type) || isType(x)
1332+
anyinfo = (!isa(x, Type) && !isvarargtype(x)) || isType(x)
13201333
end
13211334
if isa(x, Const)
13221335
params[i] = typeof(x.val)

base/compiler/typelimits.jl

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ function is_derived_type(@nospecialize(t), @nospecialize(c), mindepth::Int)
4747
# also handle the var here, since this construct bounds the mindepth to the smallest possible value
4848
return is_derived_type(t, c.var.ub, mindepth) || is_derived_type(t, c.body, mindepth)
4949
elseif isa(c, Core.VarargMarker)
50-
return is_derived_type(t, c.T, mindepth)
50+
return is_derived_type(t, unwrapva(c), mindepth)
5151
elseif isa(c, DataType)
5252
if mindepth > 0
5353
mindepth -= 1
@@ -122,10 +122,9 @@ function _limit_type_size(@nospecialize(t), @nospecialize(c), sources::SimpleVec
122122
end
123123
elseif isa(t, Core.VarargMarker)
124124
isa(c, Core.VarargMarker) || return Vararg
125-
VaT = _limit_type_size(t.T, c.T, sources, depth + 1, 0)
126-
N = t.N
127-
if isa(N, TypeVar) || N === c.N
128-
return Vararg{VaT, N}
125+
VaT = _limit_type_size(unwrapva(t), unwrapva(c), sources, depth + 1, 0)
126+
if isdefined(t, :N) && (isa(t.N, TypeVar) || (isdefined(c, :N) && t.N === c.N))
127+
return Vararg{VaT, t.N}
129128
end
130129
return Vararg{VaT}
131130
elseif isa(t, DataType)

base/compiler/typeutils.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ function unioncomplexity(t::DataType)
196196
return c
197197
end
198198
unioncomplexity(u::UnionAll) = max(unioncomplexity(u.body), unioncomplexity(u.var.ub))
199-
unioncomplexity(t::Core.VarargMarker) = unioncomplexity(t.T)
199+
unioncomplexity(t::Core.VarargMarker) = isdefined(t, :T) ? unioncomplexity(t.T) : 0
200200
unioncomplexity(@nospecialize(x)) = 0
201201

202202
function improvable_via_constant_propagation(@nospecialize(t))

base/essentials.jl

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,14 @@ function rewrap_unionall(@nospecialize(t), @nospecialize(u))
255255
return UnionAll(u.var, rewrap_unionall(t, u.body))
256256
end
257257

258+
function rewrap_unionall(t::Core.VarargMarker, u)
259+
isdefined(t, :T) || return t
260+
if !isdefined(t, :N) || (isdefined(t, :N) && t.N == u.var)
261+
return Vararg{rewrap_unionall(t.T, u)}
262+
end
263+
Vararg{rewrap_unionall(t.T, u), t.N}
264+
end
265+
258266
# replace TypeVars in all enclosing UnionAlls with fresh TypeVars
259267
function rename_unionall(@nospecialize(u))
260268
if !isa(u, UnionAll)
@@ -272,7 +280,6 @@ function rename_unionall(@nospecialize(u))
272280
end
273281

274282
function isvarargtype(@nospecialize(t))
275-
t = unwrap_unionall(t)
276283
return isa(t, Core.VarargMarker)
277284
end
278285

@@ -285,18 +292,14 @@ function isvatuple(@nospecialize(t))
285292
return false
286293
end
287294

288-
function unwrapva(@nospecialize(t))
289-
# NOTE: this returns a related type, but it's NOT a subtype of the original tuple
290-
t2 = unwrap_unionall(t)
291-
return isvarargtype(t2) ? rewrap_unionall(t2.T, t) : t
292-
end
295+
unwrapva(t::Core.VarargMarker) = isdefined(t, :T) ? t.T : Any
296+
unwrapva(@nospecialize(t)) = t
293297

294-
function unconstrain_vararg_length(@nospecialize(va))
298+
function unconstrain_vararg_length(va::Core.VarargMarker)
295299
# construct a new Vararg type where its length is unconstrained,
296300
# but its element type still captures any dependencies the input
297301
# element type may have had on the input length
298-
T = unwrap_unionall(va).T
299-
return rewrap_unionall(Vararg{T}, va)
302+
return Vararg{unwrapva(va)}
300303
end
301304

302305
typename(a) = error("typename does not apply to this type")

base/methodshow.jl

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,14 @@ function argtype_decl(env, n, @nospecialize(sig::DataType), i::Int, nargs, isva:
2727
t === Any && return s, ""
2828
end
2929
if isvarargtype(t)
30-
v1, v2 = nothing, nothing
31-
if isa(t, UnionAll)
32-
v1 = t.var
33-
t = t.body
34-
if isa(t, UnionAll)
35-
v2 = t.var
36-
t = t.body
37-
end
38-
end
39-
ut = unwrap_unionall(t)::Core.VarargMarker
40-
tt, tn = ut.T, ut.N
41-
if isa(tn, TypeVar) && (tn === v1 || tn === v2)
42-
if tt === Any || (isa(tt, TypeVar) && (tt === v1 || tt === v2))
30+
if !isdefined(t, :N)
31+
if unwrapva(t) === Any
4332
return string(s, "..."), ""
4433
else
4534
return s, string_with_env(env, tt) * "..."
4635
end
4736
end
48-
return s, string_with_env(env, "Vararg{", tt, ", ", tn, "}")
37+
return s, string_with_env(env, "Vararg{", t.T, ", ", t.N, "}")
4938
end
5039
return s, string_with_env(env, t)
5140
end

base/promotion.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,8 @@ function full_va_len(p)
157157
isempty(p) && return 0, true
158158
last = p[end]
159159
if isvarargtype(last)
160-
N = unwrap_unionall(last).N
161-
if isa(N, Int)
162-
return length(p)::Int + N - 1, true
160+
if isdefined(last, :N) && isa(last.N, Int)
161+
return length(p)::Int + last.N - 1, true
163162
end
164163
return length(p)::Int, false
165164
end

base/reflection.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,9 @@ function to_tuple_type(@nospecialize(t))
733733
end
734734
if isa(t, Type) && t <: Tuple
735735
for p in unwrap_unionall(t).parameters
736+
if isa(p, Core.VarargMarker)
737+
p = p.T
738+
end
736739
if !(isa(p, Type) || isa(p, TypeVar))
737740
error("argument tuple type must contain only types")
738741
end

base/show.jl

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2213,11 +2213,16 @@ function show(io::IO, tv::TypeVar)
22132213
end
22142214

22152215
function show(io::IO, vm::Core.VarargMarker)
2216-
print(io, "Vararg{")
2217-
show(io, vm.T)
2218-
print(io, ", ")
2219-
show(io, vm.N)
2220-
print(io, "}")
2216+
print(io, "Vararg")
2217+
if isdefined(vm, :T)
2218+
print(io, "{")
2219+
show(io, vm.T)
2220+
if isdefined(vm, :N)
2221+
print(io, ", ")
2222+
show(io, vm.N)
2223+
end
2224+
print(io, "}")
2225+
end
22212226
end
22222227

22232228
module IRShow

0 commit comments

Comments
 (0)