Skip to content

Commit

Permalink
new type union, unionall representation, new subtype and intersection…
Browse files Browse the repository at this point in the history
… algorithms

[ci skip]
  • Loading branch information
JeffBezanson committed Jan 16, 2017
1 parent f6756e5 commit b32dd7c
Show file tree
Hide file tree
Showing 38 changed files with 3,107 additions and 3,238 deletions.
25 changes: 10 additions & 15 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
#end

#type Union <: Type
# types::Tuple
# a
# b
#end

#type TypeVar
Expand All @@ -40,8 +41,8 @@
# ub::Type
#end

#type TypeConstructor
# parameters::Tuple
#type UnionAll
# var::TypeVar
# body
#end

Expand Down Expand Up @@ -120,7 +121,7 @@ import Core.Intrinsics.ccall
export
# key types
Any, DataType, Vararg, ANY, NTuple,
Tuple, Type, TypeConstructor, TypeName, TypeVar, Union, Void,
Tuple, Type, UnionAll, TypeName, TypeVar, Union, Void,
SimpleVector, AbstractArray, DenseArray,
# special objects
Function, CodeInfo, Method, MethodTable, TypeMapEntry, TypeMapLevel,
Expand Down Expand Up @@ -258,18 +259,12 @@ end
TypeVar(n::Symbol) =
ccall(:jl_new_typevar, Ref{TypeVar}, (Any, Any, Any), n, Union{}, Any)
TypeVar(n::Symbol, ub::ANY) =
(isa(ub,Bool) ?
ccall(:jl_new_typevar_, Ref{TypeVar}, (Any, Any, Any, Any), n, Union{}, Any, ub) :
ccall(:jl_new_typevar, Ref{TypeVar}, (Any, Any, Any), n, Union{}, ub::Type))
ccall(:jl_new_typevar, Ref{TypeVar}, (Any, Any, Any), n, Union{}, ub)
TypeVar(n::Symbol, lb::ANY, ub::ANY) =
(isa(ub,Bool) ?
ccall(:jl_new_typevar_, Ref{TypeVar}, (Any, Any, Any, Any), n, Union{}, lb::Type, ub) :
ccall(:jl_new_typevar, Ref{TypeVar}, (Any, Any, Any), n, lb::Type, ub::Type))
TypeVar(n::Symbol, lb::ANY, ub::ANY, b::Bool) =
ccall(:jl_new_typevar_, Ref{TypeVar}, (Any, Any, Any, Any), n, lb::Type, ub::Type, b)

TypeConstructor(p::ANY, t::ANY) =
ccall(:jl_new_type_constructor, Ref{TypeConstructor}, (Any, Any), p::SimpleVector, t::Type)
ccall(:jl_new_typevar, Ref{TypeVar}, (Any, Any, Any), n, lb, ub)

UnionAll(v::TypeVar, t::ANY) =
ccall(:jl_new_unionall_type, Ref{UnionAll}, (Any, Any), v, t)

Void() = nothing

Expand Down
4 changes: 2 additions & 2 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,8 @@ for (Fun, func) in [(:IdFun, :identity),
(::Type{typeof($(func))})() = $(func)
end
end
@deprecate_binding CentralizedAbs2Fun typeof(centralizedabs2fun(0)).name.primary
(::Type{typeof(centralizedabs2fun(0)).name.primary})(m::Number) = centralizedabs2fun(m)
@deprecate_binding CentralizedAbs2Fun typeof(centralizedabs2fun(0)).name.wrapper
(::Type{typeof(centralizedabs2fun(0)).name.wrapper})(m::Number) = centralizedabs2fun(m)
@deprecate specialized_unary(f::Function) f
@deprecate specialized_binary(f::Function) f
@deprecate specialized_bitwise_unary(f::Function) f
Expand Down
23 changes: 19 additions & 4 deletions base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ end
argtail(x, rest...) = rest
tail(x::Tuple) = argtail(x...)

tuple_type_head(T::TypeConstructor) = tuple_type_head(T.body)
tuple_type_head(T::UnionAll) = tuple_type_head(T.body)
function tuple_type_head(T::DataType)
@_pure_meta
T.name === Tuple.name || throw(MethodError(tuple_type_head, (T,)))
return T.parameters[1]
end
tuple_type_tail(T::TypeConstructor) = tuple_type_tail(T.body)
tuple_type_tail(T::UnionAll) = tuple_type_tail(T.body)
function tuple_type_tail(T::DataType)
@_pure_meta
T.name === Tuple.name || throw(MethodError(tuple_type_tail, (T,)))
Expand All @@ -69,9 +69,24 @@ function tuple_type_cons{S,T<:Tuple}(::Type{S}, ::Type{T})
Tuple{S, T.parameters...}
end

isvarargtype(t::ANY) = isa(t, DataType) && (t::DataType).name === Vararg.name
function unwrap_unionall(a::ANY)
while isa(a,UnionAll)
a = a.body
end
return a
end

const _va_typename = Vararg.body.body.name
function isvarargtype(t::ANY)
t = unwrap_unionall(t)
isa(t, DataType) && (t::DataType).name === _va_typename
end

isvatuple(t::DataType) = (n = length(t.parameters); n > 0 && isvarargtype(t.parameters[n]))
unwrapva(t::ANY) = isvarargtype(t) ? t.parameters[1] : t
function unwrapva(t::ANY)
t = unwrap_unionall(t)
isvarargtype(t) ? t.parameters[1] : t
end

convert{T<:Tuple{Any,Vararg{Any}}}(::Type{T}, x::Tuple{Any, Vararg{Any}}) =
tuple(convert(tuple_type_head(T),x[1]), convert(tuple_type_tail(T), tail(x))...)
Expand Down
71 changes: 38 additions & 33 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ type InferenceState
if laty > 0
lastatype = atypes.parameters[laty]
if isvarargtype(lastatype)
lastatype = unwrap_unionall(lastatype)
lastatype = lastatype.parameters[1]
laty -= 1
end
Expand Down Expand Up @@ -297,7 +298,8 @@ tupletype_tail(t::ANY, n) = Tuple{t.parameters[n:end]...}

cmp_tfunc = (x::ANY, y::ANY) -> Bool

isType(t::ANY) = isa(t,DataType) && (t::DataType).name === Type.name
const _Type_name = Type.body.name
isType(t::ANY) = isa(t,DataType) && (t::DataType).name === _Type_name

# true if Type is inlineable as constant
isconstType(t::ANY, b::Bool) =
Expand Down Expand Up @@ -343,13 +345,14 @@ add_tfunc(checked_usub_int, 2, 2, chk_tfunc)
add_tfunc(checked_smul_int, 2, 2, chk_tfunc)
add_tfunc(checked_umul_int, 2, 2, chk_tfunc)

const _Ref_name = Ref.body.name
add_tfunc(Core.Intrinsics.ccall, 3, IInf,
function(fptr::ANY, rt::ANY, at::ANY, a...)
if !isType(rt)
return Any
end
t = rt.parameters[1]
if isa(t,DataType) && (t::DataType).name === Ref.name
if isa(t,DataType) && (t::DataType).name === _Ref_name
t = t.parameters[1]
if t === Any
return Union{} # a return type of Box{Any} is invalid
Expand Down Expand Up @@ -434,7 +437,7 @@ function typeof_tfunc(t::ANY)
Type{TypeVar(:_,t)}
end
elseif isa(t,Union)
Union{map(typeof_tfunc, t.types)...}
Union{typeof_tfunc(t.a), typeof_tfunc(t.b)}
elseif isa(t,TypeVar) && !(Any <: t.ub)
Type{t}
else
Expand Down Expand Up @@ -475,40 +478,42 @@ add_tfunc(issubtype, 2, 2,
end)

function type_depth(t::ANY)
if isa(t, Union)
t === Bottom && return 0
return maximum(type_depth, t.types) + 1
if t === Bottom
return 0
elseif isa(t, Union)
return max(type_depth(t.a), type_depth(t.b)) + 1
elseif isa(t, DataType)
return (t::DataType).depth
end
return 0
end

function limit_type_depth(t::ANY, d::Int, cov::Bool, vars::Vector{Any})
if isa(t,TypeVar) || isa(t,TypeConstructor)
if isa(t,TypeVar) || isa(t,UnionAll)
return t
end
inexact = !cov && d > MAX_TYPE_DEPTH
if isa(t,Union)
t === Bottom && return t
if t === Bottom
return t
elseif isa(t,Union)
if d > MAX_TYPE_DEPTH
R = Any
else
R = Union{map(x->limit_type_depth(x, d+1, cov, vars), t.types)...}
R = Union{map(x->limit_type_depth(x, d+1, cov, vars), (t.a,t.b))...}
end
elseif isa(t,DataType)
P = t.parameters
isempty(P) && return t
if d > MAX_TYPE_DEPTH
R = t.name.primary
R = t.name.wrapper
else
stillcov = cov && (t.name === Tuple.name)
Q = map(x->limit_type_depth(x, d+1, stillcov, vars), P)
if !cov && _any(p->contains_is(vars,p), Q)
R = t.name.primary
R = t.name.wrapper
inexact = true
else
R = t.name.primary{Q...}
R = t.name.wrapper{Q...}
end
end
else
Expand All @@ -526,9 +531,7 @@ function getfield_tfunc(s0::ANY, name)
if isa(s0, TypeVar)
s0 = s0.ub
end
if isa(s0, TypeConstructor)
s0 = s0.body
end
s0 = unwrap_unionall(s0)
s = s0
if isType(s)
s = typeof(s.parameters[1])
Expand All @@ -542,7 +545,8 @@ function getfield_tfunc(s0::ANY, name)
s = typeof(s.val)
end
if isa(s,Union)
return reduce(tmerge, Bottom, map(t->getfield_tfunc(t, name)[1], s.types)), false
return tmerge(getfield_tfunc(t.a, name)[1],
getfield_tfunc(t.b, name)[1]), false
end
if isa(s,DataType)
if s.abstract
Expand Down Expand Up @@ -645,7 +649,7 @@ function valid_tparam(x::ANY)
return isa(x,Int) || isa(x,Symbol) || isa(x,Bool) || (!isa(x,Type) && isbits(x))
end

has_typevars(t::ANY, all=false) = ccall(:jl_has_typevars_, Cint, (Any,Cint), t, all)!=0
has_typevars(t::ANY, all=false) = ccall(:jl_has_free_typevars, Cint, (Any,), t)!=0

# TODO: handle e.g. apply_type(T, R::Union{Type{Int32},Type{Float64}})
function apply_type_tfunc(args...)
Expand Down Expand Up @@ -683,15 +687,16 @@ function apply_type_tfunc(args...)
elseif isa(ai, Const) && valid_tparam(ai.val)
push!(tparams, ai.val)
else
if !istuple && i-1 > length(headtype.parameters)
# too many parameters for type
return Bottom
end
#if !istuple && i-1 > length(headtype.parameters)
# # too many parameters for type
# return Bottom
#end
uncertain = true
if istuple
push!(tparams, Any)
else
push!(tparams, headtype.parameters[i-1])
#push!(tparams, headtype.parameters[i-1])
break
end
end
end
Expand Down Expand Up @@ -827,7 +832,7 @@ function limit_tuple_depth_(params::InferenceParams, t::ANY, d::Int)
if isa(t,Union)
# also limit within Union types.
# may have to recur into other stuff in the future too.
return Union{map(x->limit_tuple_depth_(params,x,d+1), t.types)...}
return Union{map(x->limit_tuple_depth_(params,x,d+1), (t.a,t.b))...}
end
if isa(t,TypeVar)
return limit_tuple_depth_(params, t.ub, d)
Expand Down Expand Up @@ -905,7 +910,8 @@ function abstract_call_gf_by_type(f::ANY, atype::ANY, sv::InferenceState)
end

# limit argument type tuple growth
lsig = length(m[3].sig.parameters)
msig = unwrap_unionall(m[3].sig)
lsig = length(msig.parameters)
ls = length(sig.parameters)
td = type_depth(sig)
# look at the existing edges to detect growing argument lists
Expand Down Expand Up @@ -950,7 +956,7 @@ function abstract_call_gf_by_type(f::ANY, atype::ANY, sv::InferenceState)
# if a Function argument is growing (e.g. nested closures)
# then widen to the outermost function type. without this
# inference fails to terminate on do_quadgk.
newsig[i] = p1[i].name.primary
newsig[i] = p1[i].name.wrapper
limitdepth = true
else
newsig[i] = limit_type_depth(p1[i], 1, true, [])
Expand Down Expand Up @@ -1045,9 +1051,7 @@ function precise_container_types(args, types, vtypes::VarTable, sv)
ai = args[i]
ti = types[i]
tti = widenconst(ti)
if isa(tti, TypeConstructor)
tti = tti.body
end
tti = unwrap_unionall(tti)
if isa(ti, Const) && (isa(ti.val, SimpleVector) || isa(ti.val, Tuple))
result[i] = Any[ abstract_eval_constant(x) for x in ti.val ]
elseif isa(ai, Expr) && ai.head === :call && (abstract_evals_to_constant(ai.args[1], svec, vtypes, sv) ||
Expand Down Expand Up @@ -1413,7 +1417,7 @@ function type_too_complex(t::ANY, d)
return true
end
if isa(t,Union)
p = t.types
return type_too_complex(t.a, d+1) || type_too_complex(t.b, d+1)
elseif isa(t,DataType)
p = t.parameters
elseif isa(t,TypeVar)
Expand Down Expand Up @@ -1480,7 +1484,7 @@ function tmerge(typea::ANY, typeb::ANY)
end
end
u = Union{typea, typeb}
if length(u.types) > MAX_TYPEUNION_LEN || type_too_complex(u, 0)
if unionlen(u) > MAX_TYPEUNION_LEN || type_too_complex(u, 0)
# don't let type unions get too big
# TODO: something smarter, like a common supertype
return Any
Expand Down Expand Up @@ -2185,6 +2189,7 @@ function isinlineable(m::Method, src::CodeInfo)
name = m.name
sig = m.sig
if ((name === :+ || name === :* || name === :min || name === :max) &&
isa(sig,DataType) &&
sig == Tuple{sig.parameters[1],Any,Any,Any,Vararg{Any}})
inlineable = true
elseif (name === :next || name === :done || name === :unsafe_convert ||
Expand Down Expand Up @@ -2729,7 +2734,7 @@ function countunionsplit(atypes::Vector{Any})
nu = 1
for ti in atypes
if isa(ti, Union)
nu *= length((ti::Union).types)
nu *= unionlen(ti::Union)
end
end
return nu
Expand Down Expand Up @@ -2804,7 +2809,7 @@ function invoke_NF(argexprs, etype::ANY, atypes, sv, atype_unlimited::ANY,
local all = true
local stmts = []
local aei = ex.args[i]
for ty in (ti::Union).types
for ty in uniontypes(ti::Union)
local ty
atypes[i] = ty
local match = splitunion(atypes, i - 1)
Expand Down
2 changes: 1 addition & 1 deletion base/interactiveutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ function type_close_enough(x::ANY, t::ANY)
x == t && return true
return (isa(x,DataType) && isa(t,DataType) && x.name === t.name &&
!isleaftype(t) && x <: t) ||
(isa(x,Union) && isa(t,DataType) && any(u -> u===t, x.types))
(isa(x,Union) && isa(t,DataType) && (type_close_enough(x.a, t) || type_close_enough(x.b, t)))
end

# `methodswith` -- shows a list of methods using the type given
Expand Down
5 changes: 1 addition & 4 deletions base/markdown/Julia/interp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,8 @@ toexpr(x) = x

toexpr(xs::Vector{Any}) = Expr(:call, GlobalRef(Base,:vector_any), map(toexpr, xs)...)

function deftoexpr(T)
for T in Any[MD, Paragraph, Header, Link, Bold, Italic]
@eval function toexpr(md::$T)
Expr(:call, typeof(md), $(map(x->:(toexpr(md.$x)), fieldnames(T))...))
end
end

map(deftoexpr, [MD, Paragraph, Header,
Link, Bold, Italic])
Loading

0 comments on commit b32dd7c

Please sign in to comment.