Skip to content

Commit d900051

Browse files
committed
inference: permit non-direct recursion reducers
Fix #45759 Fix #46557 Fix #31485
1 parent edba0db commit d900051

File tree

2 files changed

+39
-7
lines changed

2 files changed

+39
-7
lines changed

base/compiler/abstractinterpretation.jl

+13-7
Original file line numberDiff line numberDiff line change
@@ -549,25 +549,30 @@ function abstract_call_method(interp::AbstractInterpreter,
549549
if topmost !== nothing
550550
msig = unwrap_unionall(method.sig)::DataType
551551
spec_len = length(msig.parameters) + 1
552-
ls = length(sigtuple.parameters)
553552
mi = frame_instance(sv)
554553

554+
if isdefined(method, :recursion_relation)
555+
# We don't require the recursion_relation to be transitive, so
556+
# apply a hard limit
557+
hardlimit = true
558+
end
559+
555560
if method === mi.def
556561
# Under direct self-recursion, permit much greater use of reducers.
557562
# here we assume that complexity(specTypes) :>= complexity(sig)
558563
comparison = mi.specTypes
559564
l_comparison = length((unwrap_unionall(comparison)::DataType).parameters)
560565
spec_len = max(spec_len, l_comparison)
566+
elseif !hardlimit && isa(topmost, InferenceState)
567+
# Without a hardlimit, permit use of reducers too.
568+
comparison = frame_instance(topmost).specTypes
569+
# n.b. currently don't allow vararg reducers
570+
#l_comparison = length((unwrap_unionall(comparison)::DataType).parameters)
571+
#spec_len = max(spec_len, l_comparison)
561572
else
562573
comparison = method.sig
563574
end
564575

565-
if isdefined(method, :recursion_relation)
566-
# We don't require the recursion_relation to be transitive, so
567-
# apply a hard limit
568-
hardlimit = true
569-
end
570-
571576
# see if the type is actually too big (relative to the caller), and limit it if required
572577
newsig = limit_type_size(sig, comparison, hardlimit ? comparison : mi.specTypes, InferenceParams(interp).tuple_complexity_limit_depth, spec_len)
573578

@@ -594,6 +599,7 @@ function abstract_call_method(interp::AbstractInterpreter,
594599
poison_callstack!(sv, parentframe === nothing ? topmost : parentframe)
595600
end
596601
end
602+
# n.b. this heuristic depends on the non-local state, so we must record the limit later
597603
sig = newsig
598604
sparams = svec()
599605
edgelimited = true

test/compiler/inference.jl

+26
Original file line numberDiff line numberDiff line change
@@ -5099,3 +5099,29 @@ end
50995099
refine_partial_struct2(42, s)
51005100
end |> only === String
51015101
# JET.test_call(s::AbstractString->Base._string(s, 'c'))
5102+
5103+
# issue #45759 #46557
5104+
g45759(x::Tuple{Any,Vararg}) = x[1] + _g45759(x[2:end])
5105+
g45759(x::Tuple{}) = 0
5106+
_g45759(x) = g45759(x)
5107+
@test only(Base.return_types(g45759, Tuple{Tuple{Int,Int,Int,Int,Int,Int,Int}})) == Int
5108+
5109+
h45759(x::Tuple{Any,Vararg}; kwargs...) = x[1] + h45759(x[2:end]; kwargs...)
5110+
h45759(x::Tuple{}; kwargs...) = 0
5111+
@test only(Base.return_types(h45759, Tuple{Tuple{Int,Int,Int,Int,Int,Int,Int}})) == Int
5112+
5113+
@test only(Base.return_types((typeof([[[1]]]))) do x
5114+
sum(x) do v; sum(length, v); end
5115+
end) == Int
5116+
5117+
struct FunctionSum{Tf}
5118+
functions::Tf
5119+
end
5120+
(F::FunctionSum)(x) = sum(f -> f(x), F.functions)
5121+
F = FunctionSum((x -> sqrt(x), FunctionSum((x -> x^2, x -> x^3))))
5122+
@test @inferred(F(1.)) === 3.0
5123+
5124+
f31485(arr::AbstractArray{T, 0}) where {T} = arr
5125+
indirect31485(arr) = f31485(arr)
5126+
f31485(arr::AbstractArray{T, N}) where {T, N} = indirect31485(view(arr, 1, ntuple(i -> :, Val(N-1))...))
5127+
@test @inferred(f31485(zeros(3,3,3,3,3),)) == fill(0.0)

0 commit comments

Comments
 (0)