Skip to content

Commit 5fd036d

Browse files
committed
attempt to refine return type when it could be improved via PartialTuple
1 parent 560e829 commit 5fd036d

File tree

5 files changed

+34
-9
lines changed

5 files changed

+34
-9
lines changed

base/compiler/abstractinterpretation.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ function abstract_call_gf_by_type(@nospecialize(f), argtypes::Vector{Any}, @nosp
104104
# if there's a possibility we could constant-propagate a better result
105105
# (hopefully without doing too much work), try to do that now
106106
# TODO: it feels like this could be better integrated into abstract_call_method / typeinf_edge
107-
const_rettype = abstract_call_method_with_const_args(f, argtypes, applicable[nonbot]::SimpleVector, sv)
107+
const_rettype = abstract_call_method_with_const_args(rettype, f, argtypes, applicable[nonbot]::SimpleVector, sv)
108108
if const_rettype rettype
109109
# use the better result, if it's a refinement of rettype
110110
rettype = const_rettype
@@ -142,7 +142,7 @@ function abstract_call_gf_by_type(@nospecialize(f), argtypes::Vector{Any}, @nosp
142142
return rettype
143143
end
144144

145-
function abstract_call_method_with_const_args(@nospecialize(f), argtypes::Vector{Any}, match::SimpleVector, sv::InferenceState)
145+
function abstract_call_method_with_const_args(@nospecialize(rettype), @nospecialize(f), argtypes::Vector{Any}, match::SimpleVector, sv::InferenceState)
146146
method = match[3]::Method
147147
nargs::Int = method.nargs
148148
method.isva && (nargs -= 1)
@@ -159,7 +159,7 @@ function abstract_call_method_with_const_args(@nospecialize(f), argtypes::Vector
159159
end
160160
end
161161
end
162-
haveconst || return Any
162+
haveconst || improvable_via_constant_propagation(rettype) || return Any
163163
sig = match[1]
164164
sparams = match[2]::SimpleVector
165165
code = code_for_method(method, sig, sparams, sv.params.world)
@@ -1060,7 +1060,7 @@ function typeinf_local(frame::InferenceState)
10601060
elseif hd === :return
10611061
pc´ = n + 1
10621062
rt = widenconditional(abstract_eval(stmt.args[1], s[pc], frame))
1063-
if !isa(rt, Const) && !isa(rt, Type) && (!isa(rt, PartialTuple) || frame.cached)
1063+
if !isa(rt, Const) && !isa(rt, Type) && !isa(rt, PartialTuple)
10641064
# only propagate information we know we can store
10651065
# and is valid inter-procedurally
10661066
rt = widenconst(rt)

base/compiler/ssair/inlining.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,7 @@ function analyze_method!(idx::Int, @nospecialize(f), @nospecialize(ft), @nospeci
671671
return ConstantCase(quoted(linfo.inferred_const), method, Any[methsp...], metharg)
672672
end
673673

674-
isconst, inferred = find_inferred(linfo, atypes, sv)
674+
isconst, inferred = find_inferred(linfo, atypes, sv, stmttyp)
675675
if isconst
676676
return ConstantCase(inferred, method, Any[methsp...], metharg)
677677
end
@@ -1152,7 +1152,7 @@ function ssa_substitute_op!(@nospecialize(val), arg_replacements::Vector{Any},
11521152
return urs[]
11531153
end
11541154

1155-
function find_inferred(linfo::MethodInstance, @nospecialize(atypes), sv::OptimizationState)
1155+
function find_inferred(linfo::MethodInstance, @nospecialize(atypes), sv::OptimizationState, @nospecialize(rettype))
11561156
# see if the method has a InferenceResult in the current cache
11571157
# or an existing inferred code info store in `.inferred`
11581158
haveconst = false
@@ -1163,7 +1163,7 @@ function find_inferred(linfo::MethodInstance, @nospecialize(atypes), sv::Optimiz
11631163
break
11641164
end
11651165
end
1166-
if haveconst
1166+
if haveconst || improvable_via_constant_propagation(rettype)
11671167
inf_result = cache_lookup(linfo, atypes, sv.params.cache) # Union{Nothing, InferenceResult}
11681168
else
11691169
inf_result = nothing

base/compiler/typeinfer.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -495,15 +495,19 @@ function typeinf_edge(method::Method, @nospecialize(atypes), sparams::SimpleVect
495495
frame.parent = caller
496496
end
497497
typeinf(frame)
498-
return frame.bestguess, frame.inferred ? frame.linfo : nothing
498+
return widenconst_bestguess(frame.bestguess), frame.inferred ? frame.linfo : nothing
499499
elseif frame === true
500500
# unresolvable cycle
501501
return Any, nothing
502502
end
503503
frame = frame::InferenceState
504-
return frame.bestguess, nothing
504+
return widenconst_bestguess(frame.bestguess), nothing
505505
end
506506

507+
function widenconst_bestguess(bestguess)
508+
!isa(bestguess, Const) && !isa(bestguess, Type) && return widenconst(bestguess)
509+
return bestguess
510+
end
507511

508512
#### entry points for inferring a MethodInstance given a type signature ####
509513

base/compiler/typeutils.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,12 @@ function unioncomplexity(t::DataType)
160160
end
161161
unioncomplexity(u::UnionAll) = max(unioncomplexity(u.body), unioncomplexity(u.var.ub))
162162
unioncomplexity(@nospecialize(x)) = 0
163+
164+
function improvable_via_constant_propagation(@nospecialize(t))
165+
if isconcretetype(t) && t <: Tuple
166+
for p in t.parameters
167+
p === DataType && return true
168+
end
169+
end
170+
return false
171+
end

test/compiler/inference.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2151,3 +2151,15 @@ g30098() = (h30098(:f30098); 4)
21512151
h30098(f) = getfield(@__MODULE__, f)()
21522152
@test @inferred(g30098()) == 4 # make sure that this
21532153
@test @inferred(f30098()) == 3 # doesn't pollute the inference cache of this
2154+
2155+
# PR #30385
2156+
2157+
g30385(args...) = h30385(args...)
2158+
h30385(f, args...) = f(args...)
2159+
f30385(T, y) = g30385(getfield, g30385(tuple, T, y), 1)
2160+
k30385(::Type{AbstractFloat}) = 1
2161+
k30385(x) = "dummy"
2162+
j30385(T, y) = k30385(f30385(T, y))
2163+
2164+
@test @inferred(j30385(AbstractFloat, 1)) == 1
2165+
@test @inferred(j30385(:dummy, 1)) == "dummy"

0 commit comments

Comments
 (0)