Skip to content

Commit

Permalink
Better inference of _apply(..., Union{Tuple...}, ...)
Browse files Browse the repository at this point in the history
  • Loading branch information
martinholters committed Jan 31, 2017
1 parent 8c2b2df commit b80ddc6
Showing 1 changed file with 48 additions and 15 deletions.
63 changes: 48 additions & 15 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1355,7 +1355,19 @@ function precise_container_types(args, types, vtypes::VarTable, sv)
return nothing
end
elseif isa(tti, Union)
return nothing
utis = uniontypes(tti)
if _any(t -> !isa(t,DataType) || !(t <: Tuple) || !isknownlength(t), utis)
return nothing
end
result[i] = Any[Union{} for j in 1:length(utis[1].parameters)]
for t in utis
if length(t.parameters) != length(result[i])
return nothing
end
for j in 1:length(t.parameters)
result[i][j] = tmerge(result[i][j], t.parameters[j])
end
end
elseif isa(tti,DataType) && tti <: Tuple
if i == n
if isvatuple(tti) && length(tti.parameters) == 1
Expand All @@ -1377,22 +1389,43 @@ function precise_container_types(args, types, vtypes::VarTable, sv)
return result
end

function uniontypes_prod(types::Vector{Any})
tp = _uniontypes_prod(Vector{Any}[Any[]], Vector{Any}[uniontypes(t) for t in types])
return tp === false ? [types] : tp
end
function _uniontypes_prod(tp::Vector{Vector{Any}}, tvs::Vector{Vector{Any}})
length(tvs) == 0 && return tp
tvnew = Vector{Any}[]
for tv in tp, t in tvs[1]
push!(tvnew, push!(copy(tv), t))
if length(tvnew) > 7
return false
end
end
return _uniontypes_prod(tvnew, tvs[2:end])
end

# do apply(af, fargs...), where af is a function value
function abstract_apply(af::ANY, fargs, aargtypes::Vector{Any}, vtypes::VarTable, sv)
ctypes = precise_container_types(fargs, aargtypes, vtypes, sv)
if ctypes !== nothing
# apply with known func with known tuple types
# can be collapsed to a call to the applied func
at = append_any(Any[Const(af)], ctypes...)
n = length(at)
if n-1 > sv.params.MAX_TUPLETYPE_LEN
tail = foldl((a,b)->tmerge(a,unwrapva(b)), Bottom, at[sv.params.MAX_TUPLETYPE_LEN+1:n])
at = vcat(at[1:sv.params.MAX_TUPLETYPE_LEN], Any[Vararg{widenconst(tail)}])
end
return abstract_call(af, (), at, vtypes, sv)
end
# apply known function with unknown args => f(Any...)
return abstract_call(af, (), Any[Const(af), Vararg{Any}], vtypes, sv)
res = Union{}
for eaargtypes in uniontypes_prod(aargtypes)
ctypes = precise_container_types(fargs, eaargtypes, vtypes, sv)
if ctypes === nothing
# apply known function with unknown args => f(Any...)
res = tmerge(res, abstract_call(af, (), Any[Const(af), Vararg{Any}], vtypes, sv))
else
# apply with known func with known tuple types
# can be collapsed to a call to the applied func
at = append_any(Any[Const(af)], ctypes...)
n = length(at)
if n-1 > sv.params.MAX_TUPLETYPE_LEN
tail = foldl((a,b)->tmerge(a,unwrapva(b)), Bottom, at[sv.params.MAX_TUPLETYPE_LEN+1:n])
at = vcat(at[1:sv.params.MAX_TUPLETYPE_LEN], Any[Vararg{widenconst(tail)}])
end
res = tmerge(res, abstract_call(af, (), at, vtypes, sv))
end
end
return res
end

function return_type_tfunc(argtypes::ANY, vtypes::VarTable, sv::InferenceState)
Expand Down

0 comments on commit b80ddc6

Please sign in to comment.