Skip to content

Commit

Permalink
Fix a precision issue in abstract_iteration
Browse files Browse the repository at this point in the history
If the first loop exits in the first iteration, the `statetype` is still
`Bottom`. In that case, the new `stateordonet` needs to be determined
with the two-arg version of `iterate` again.

Fixes #41022.
  • Loading branch information
martinholters committed Aug 19, 2021
1 parent 543386d commit 87e24ee
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 1 deletion.
7 changes: 6 additions & 1 deletion base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -862,8 +862,12 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
# the precise (potentially const) state type
statetype = widenconst(statetype)
valtype = widenconst(valtype)
while valtype !== Any
if statetype === Bottom
stateordonet = abstract_call_known(interp, iteratef, nothing, Any[Const(iteratef), itertype], sv).rt
else
stateordonet = abstract_call_known(interp, iteratef, nothing, Any[Const(iteratef), itertype, statetype], sv).rt
end
while valtype !== Any
stateordonet = widenconst(stateordonet)
nounion = typesubtract(stateordonet, Nothing, 0)
if !isa(nounion, DataType) || !(nounion <: Tuple) || isvatuple(nounion) || length(nounion.parameters) != 2
Expand All @@ -879,6 +883,7 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
end
valtype = tmerge(valtype, nounion.parameters[1])
statetype = tmerge(statetype, nounion.parameters[2])
stateordonet = abstract_call_known(interp, iteratef, nothing, Any[Const(iteratef), itertype, statetype], sv).rt
end
push!(ret, Vararg{valtype})
return ret, nothing
Expand Down
1 change: 1 addition & 0 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2875,6 +2875,7 @@ partial_return_2(x) = Val{partial_return_1(x)[2]}
# Precision of abstract_iteration
f_splat(x) = (x...,)
@test Base.return_types(f_splat, (Pair{Int,Int},)) == Any[Tuple{Int, Int}]
@test Base.return_types(f_splat, (UnitRange{Int},)) == Any[Tuple{Vararg{Int}}]

# issue #32699
f32699(a) = (id = a[1],).id
Expand Down

0 comments on commit 87e24ee

Please sign in to comment.