Skip to content

Commit e8caa27

Browse files
vtjnashKristofferC
authored andcommitted
inference: relax type_more_complex for Type
If the object is not a potential Type{...}, we can allow greater flexibility in recursion. (cherry picked from commit 1daaf47)
1 parent 643fef7 commit e8caa27

File tree

2 files changed

+72
-24
lines changed

2 files changed

+72
-24
lines changed

base/compiler/typelimits.jl

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ function is_derived_type(@nospecialize(t), @nospecialize(c), mindepth::Int)
3939
if t === c
4040
return mindepth <= 1
4141
end
42+
isvarargtype(t) && (t = unwrapva(t))
43+
isvarargtype(c) && (c = unwrapva(c))
4244
if isa(c, Union)
4345
# see if it is one of the elements of the union
4446
return is_derived_type(t, c.a, mindepth) || is_derived_type(t, c.b, mindepth)
4547
elseif isa(c, UnionAll)
4648
# see if it is derived from the body
4749
# also handle the var here, since this construct bounds the mindepth to the smallest possible value
4850
return is_derived_type(t, c.var.ub, mindepth) || is_derived_type(t, c.body, mindepth)
49-
elseif isvarargtype(c)
50-
return is_derived_type(t, unwrapva(c), mindepth)
5151
elseif isa(c, DataType)
5252
if mindepth > 0
5353
mindepth -= 1
@@ -114,10 +114,14 @@ function _limit_type_size(@nospecialize(t), @nospecialize(c), sources::SimpleVec
114114
return Union{a, b}
115115
end
116116
elseif isa(t, DataType)
117-
if isType(t) # allow taking typeof as Type{...}, but ensure it doesn't start nesting
117+
if isType(t) # see equivalent case in type_more_complex
118118
tt = unwrap_unionall(t.parameters[1])
119-
(!isa(tt, DataType) || isType(tt)) && (depth += 1)
120-
is_derived_type_from_any(tt, sources, depth) && return t
119+
if isa(tt, Union) || isa(tt, TypeVar) || isType(tt)
120+
is_derived_type_from_any(tt, sources, depth + 1) && return t
121+
else
122+
isType(c) && (c = unwrap_unionall(c.parameters[1]))
123+
type_more_complex(tt, c, sources, depth, 0, 0) || return t
124+
end
121125
return Type
122126
elseif isa(c, DataType)
123127
tP = t.parameters
@@ -167,6 +171,11 @@ end
167171

168172
# helper function of `_limit_type_size`, which has the right to take and return `TypeVar` / `Vararg`
169173
function __limit_type_size(@nospecialize(t), @nospecialize(c), sources::SimpleVector, depth::Int, allowed_tuplelen::Int)
174+
cN = 0
175+
if isvarargtype(c) # Tuple{Vararg{T}} --> Tuple{T} is OK
176+
isdefined(c, :N) && (cN = c.N)
177+
c = unwrapva(c)
178+
end
170179
if isa(c, TypeVar)
171180
if isa(t, TypeVar) && t.ub === c.ub && (t.lb === Union{} || t.lb === c.lb)
172181
return t # it's ok to change the name, or widen `lb` to Union{}, so we can handle this immediately here
@@ -176,15 +185,17 @@ function __limit_type_size(@nospecialize(t), @nospecialize(c), sources::SimpleVe
176185
# don't have a matching TypeVar in comparison, so we keep just the upper bound
177186
return __limit_type_size(t.ub, c, sources, depth, allowed_tuplelen)
178187
elseif isvarargtype(t)
179-
isvarargtype(c) || return Vararg
180-
VaT = __limit_type_size(unwrapva(t), unwrapva(c), sources, depth + 1, 0)
181-
if isdefined(t, :N) && (isa(t.N, TypeVar) || (isdefined(c, :N) && t.N === c.N))
182-
return Vararg{VaT, t.N}
188+
# Tuple{Vararg{T,N}} --> Tuple{Vararg{S,M}} is OK
189+
# Tuple{T} --> Tuple{Vararg{T}} is OK
190+
# but S must be more limited than T, and must not introduce a new number for M
191+
VaT = __limit_type_size(unwrapva(t), c, sources, depth + 1, 0)
192+
if isdefined(t, :N)
193+
tN = t.N
194+
if isa(tN, TypeVar) || tN === cN
195+
return Vararg{VaT, tN}
196+
end
183197
end
184198
return Vararg{VaT}
185-
elseif isvarargtype(c)
186-
# Tuple{Vararg{T}} --> Tuple{T} is OK
187-
return __limit_type_size(t, unwrapva(c), sources, depth, 0)
188199
else
189200
return _limit_type_size(t, c, sources, depth, allowed_tuplelen)
190201
end
@@ -205,6 +216,8 @@ function type_more_complex(@nospecialize(t), @nospecialize(c), sources::SimpleVe
205216
return false # t isn't something new
206217
end
207218
# peel off wrappers
219+
isvarargtype(t) && (t = unwrapva(t))
220+
isvarargtype(c) && (c = unwrapva(c))
208221
if isa(c, UnionAll)
209222
# allow wrapping type with fewer UnionAlls than comparison if in a covariant context
210223
if !isa(t, UnionAll) && tupledepth == 0
@@ -233,18 +246,19 @@ function type_more_complex(@nospecialize(t), @nospecialize(c), sources::SimpleVe
233246
return t !== 1 && !(0 <= t < c) # alternatively, could use !(abs(t) <= abs(c) || abs(t) < n) for some n
234247
end
235248
# base case for data types
236-
if isvarargtype(t)
237-
if isvarargtype(c)
238-
return type_more_complex(unwrapva(t), unwrapva(c), sources, depth + 1, tupledepth, 0)
239-
end
240-
elseif isa(t, DataType)
249+
if isa(t, DataType)
241250
tP = t.parameters
242-
if isvarargtype(c)
243-
return type_more_complex(t, unwrapva(c), sources, depth, tupledepth, 0)
244-
elseif isType(t) # allow taking typeof any source type anywhere as Type{...}, as long as it isn't nesting Type{Type{...}}
251+
if isType(t)
252+
# Treat Type{T} and T as equivalent to allow taking typeof any
253+
# source type (DataType) anywhere as Type{...}, as long as it isn't
254+
# nesting as Type{Type{...}}
245255
tt = unwrap_unionall(t.parameters[1])
246-
(!isa(tt, DataType) || isType(tt)) && (depth += 1)
247-
return !is_derived_type_from_any(tt, sources, depth)
256+
if isa(tt, Union) || isa(tt, TypeVar) || isType(tt)
257+
return !is_derived_type_from_any(tt, sources, depth + 1)
258+
else
259+
isType(c) && (c = unwrap_unionall(c.parameters[1]))
260+
return type_more_complex(tt, c, sources, depth, 0, 0)
261+
end
248262
elseif isa(c, DataType) && t.name === c.name
249263
cP = c.parameters
250264
length(cP) < length(tP) && return true

test/compiler/inference.jl

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,42 @@ end
4646

4747
# obtain Vararg with 2 undefined fields
4848
let va = ccall(:jl_type_intersection_with_env, Any, (Any, Any), Tuple{Tuple}, Tuple{Tuple{Vararg{Any, N}}} where N)[2][1]
49-
@test Core.Compiler.__limit_type_size(Tuple, va, Core.svec(va, Union{}), 2, 2) === Any
50-
end
49+
@test Core.Compiler.__limit_type_size(Tuple, va, Core.svec(va, Union{}), 2, 2) === Tuple
50+
end
51+
52+
# issue #42835
53+
@test !Core.Compiler.type_more_complex(Int, Any, Core.svec(), 1, 1, 1)
54+
@test !Core.Compiler.type_more_complex(Int, Type{Int}, Core.svec(), 1, 1, 1)
55+
@test !Core.Compiler.type_more_complex(Type{Int}, Any, Core.svec(), 1, 1, 1)
56+
@test Core.Compiler.type_more_complex(Type{Type{Int}}, Type{Int}, Core.svec(Type{Int}), 1, 1, 1)
57+
@test Core.Compiler.type_more_complex(Type{Type{Int}}, Int, Core.svec(Type{Int}), 1, 1, 1)
58+
@test Core.Compiler.type_more_complex(Type{Type{Int}}, Any, Core.svec(), 1, 1, 1)
59+
@test Core.Compiler.type_more_complex(Type{Type{Type{Int}}}, Type{Type{Int}}, Core.svec(Type{Type{Int}}), 1, 1, 1)
60+
61+
@test Core.Compiler.type_more_complex(ComplexF32, Any, Core.svec(), 1, 1, 1)
62+
@test !Core.Compiler.type_more_complex(ComplexF32, Any, Core.svec(Type{ComplexF32}), 1, 1, 1)
63+
@test Core.Compiler.type_more_complex(ComplexF32, Type{ComplexF32}, Core.svec(), 1, 1, 1)
64+
@test !Core.Compiler.type_more_complex(Type{ComplexF32}, Any, Core.svec(Type{Type{ComplexF32}}), 1, 1, 1)
65+
@test Core.Compiler.type_more_complex(Type{ComplexF32}, Type{Type{ComplexF32}}, Core.svec(), 1, 1, 1)
66+
@test !Core.Compiler.type_more_complex(Type{ComplexF32}, ComplexF32, Core.svec(), 1, 1, 1)
67+
@test Core.Compiler.type_more_complex(Type{ComplexF32}, Any, Core.svec(), 1, 1, 1)
68+
@test Core.Compiler.type_more_complex(Type{Type{ComplexF32}}, Type{ComplexF32}, Core.svec(Type{ComplexF32}), 1, 1, 1)
69+
@test Core.Compiler.type_more_complex(Type{Type{ComplexF32}}, ComplexF32, Core.svec(ComplexF32), 1, 1, 1)
70+
@test Core.Compiler.type_more_complex(Type{Type{Type{ComplexF32}}}, Type{Type{ComplexF32}}, Core.svec(Type{ComplexF32}), 1, 1, 1)
71+
72+
# n.b. Type{Type{Union{}} === Type{Core.TypeofBottom}
73+
@test !Core.Compiler.type_more_complex(Type{Union{}}, Any, Core.svec(), 1, 1, 1)
74+
@test !Core.Compiler.type_more_complex(Type{Type{Union{}}}, Any, Core.svec(), 1, 1, 1)
75+
@test Core.Compiler.type_more_complex(Type{Type{Type{Union{}}}}, Any, Core.svec(), 1, 1, 1)
76+
@test Core.Compiler.type_more_complex(Type{Type{Type{Union{}}}}, Type{Type{Union{}}}, Core.svec(Type{Type{Union{}}}), 1, 1, 1)
77+
@test Core.Compiler.type_more_complex(Type{Type{Type{Type{Union{}}}}}, Type{Type{Type{Union{}}}}, Core.svec(Type{Type{Type{Union{}}}}), 1, 1, 1)
78+
79+
@test !Core.Compiler.type_more_complex(Type{1}, Type{2}, Core.svec(), 1, 1, 1)
80+
@test Core.Compiler.type_more_complex(Type{Union{Float32,Float64}}, Union{Float32,Float64}, Core.svec(Union{Float32,Float64}), 1, 1, 1)
81+
@test !Core.Compiler.type_more_complex(Type{Union{Float32,Float64}}, Union{Float32,Float64}, Core.svec(Union{Float32,Float64}), 0, 1, 1)
82+
@test_broken Core.Compiler.type_more_complex(Type{<:Union{Float32,Float64}}, Type{Union{Float32,Float64}}, Core.svec(Union{Float32,Float64}), 1, 1, 1)
83+
@test Core.Compiler.type_more_complex(Type{<:Union{Float32,Float64}}, Any, Core.svec(Union{Float32,Float64}), 1, 1, 1)
84+
5185

5286
let # 40336
5387
t = Type{Type{Int}}

0 commit comments

Comments
 (0)