Skip to content

Commit

Permalink
add Core.Inference.return_type
Browse files Browse the repository at this point in the history
This computes a return type (at compile time if possible) in a way that handles
recursive dependencies in inference.
  • Loading branch information
JeffBezanson committed Jun 21, 2016
1 parent 464d4b4 commit e53df0f
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 11 deletions.
12 changes: 3 additions & 9 deletions base/array.jl
Expand Up @@ -243,15 +243,9 @@ function _collect(cont, itr, ::HasEltype, isz::SizeUnknown)
end

if isdefined(:Base)
@eval function _default_eltype(itrt::ANY)
$(Expr(:meta, :pure))
try
rt = return_types(first, (itrt,))
if length(rt) == 1 && isleaftype(rt[1])
return rt[1]
end
end
return Union{}
function _default_eltype(itrt::ANY)
rt = Core.Inference.return_type(first, Tuple{itrt})
return isleaftype(rt) ? rt : Union{}
end
else
_default_eltype(itr::ANY) = Union{}
Expand Down
23 changes: 21 additions & 2 deletions base/inference.jl
Expand Up @@ -917,13 +917,23 @@ function abstract_apply(af::ANY, fargs, aargtypes::Vector{Any}, vtypes::VarTable
return abstract_call(af, (), Any[type_typeof(af), Vararg{Any}], vtypes, sv)
end

function pure_eval_call(f::ANY, argtypes::ANY, atype, sv)
function pure_eval_call(f::ANY, argtypes::ANY, atype, vtypes, sv)
for a in drop(argtypes,1)
if !(isa(a,Const) || (isType(a) && !has_typevars(a.parameters[1])))
return false
end
end

if f === return_type
tt = argtypes[3]
if isType(tt) && tt.parameters[1] <: Tuple
af = argtypes[2]
rt = abstract_call(isa(af,Const) ? af.val : af.parameters[1],
(), Any[argtypes[2], tt.parameters[1].parameters...], vtypes, sv)
return Type{widenconst(rt)}
end
end

meth = _methods_by_ftype(atype, 1)
if meth === false || length(meth) != 1
return false
Expand Down Expand Up @@ -1002,7 +1012,7 @@ function abstract_call(f::ANY, fargs, argtypes::Vector{Any}, vtypes::VarTable, s
end

atype = argtypes_to_type(argtypes)
t = pure_eval_call(f, argtypes, atype, sv)
t = pure_eval_call(f, argtypes, atype, vtypes, sv)
t !== false && return t

if istopfunction(tm, f, :promote_type) || istopfunction(tm, f, :typejoin)
Expand Down Expand Up @@ -3375,6 +3385,15 @@ function reindex_labels!(linfo::LambdaInfo, sv::InferenceState)
end
end

function return_type(f::ANY, t::ANY)
rt = Union{}
for m in _methods(f, t, -1)
_, ty, _ = typeinf(m[3], m[1], m[2], false)
rt = tmerge(rt, ty)
rt === Any && break
end
return rt
end

#### bootstrapping ####

Expand Down

0 comments on commit e53df0f

Please sign in to comment.