diff --git a/base/boot.jl b/base/boot.jl index 400f24f21b028..2d48f7080464a 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -31,7 +31,8 @@ #end #type Union <: Type -# types::Tuple +# a +# b #end #type TypeVar @@ -40,8 +41,8 @@ # ub::Type #end -#type TypeConstructor -# parameters::Tuple +#type UnionAll +# var::TypeVar # body #end @@ -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, @@ -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 diff --git a/base/deprecated.jl b/base/deprecated.jl index 13d19d2601697..2b15c230c69ef 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -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 diff --git a/base/essentials.jl b/base/essentials.jl index 56490c1c469cf..efe5058c444f5 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -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,))) @@ -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))...) diff --git a/base/inference.jl b/base/inference.jl index d96c2922a073f..166f4ed306836 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -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 @@ -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) = @@ -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 @@ -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 @@ -475,9 +478,10 @@ 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 @@ -485,30 +489,31 @@ function type_depth(t::ANY) 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 @@ -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]) @@ -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 @@ -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...) @@ -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 @@ -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) @@ -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 @@ -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, []) @@ -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) || @@ -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) @@ -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 @@ -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 || @@ -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 @@ -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) diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index ddb77a589adf9..3f8c23825225a 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -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 diff --git a/base/markdown/Julia/interp.jl b/base/markdown/Julia/interp.jl index 1bd28599f2209..3befec1f6953c 100644 --- a/base/markdown/Julia/interp.jl +++ b/base/markdown/Julia/interp.jl @@ -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]) diff --git a/base/methodshow.jl b/base/methodshow.jl index 892e003851da9..c4d9ce62a7541 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -19,9 +19,18 @@ function argtype_decl(env, n, sig::DataType, i::Int, nargs, isva::Bool) # -> (ar return s, "" end if isvarargtype(t) + v1, v2 = nothing, nothing + if isa(t, UnionAll) + v1 = t.var + t = t.body + if isa(t, UnionAll) + v2 = t.var + t = t.body + end + end tt, tn = t.parameters[1], t.parameters[2] - if isa(tn, TypeVar) && !tn.bound - if tt === Any || (isa(tt, TypeVar) && !tt.bound) + if isa(tn, TypeVar) && (tn === v1 || tn === v2) + if tt === Any || (isa(tt, TypeVar) && (tt === v1 || tt === v2)) return string(s, "..."), "" else return s, string_with_env(env, tt) * "..." @@ -48,16 +57,17 @@ function arg_decl_parts(m::Method) line = m.line if src !== nothing && src.slotnames !== nothing argnames = src.slotnames[1:m.nargs] - decls = Any[argtype_decl(:tvar_env => tv, argnames[i], m.sig, i, m.nargs, m.isva) + sig = unwrap_unionall(m.sig) + decls = Any[argtype_decl(:tvar_env => tv, argnames[i], sig, i, m.nargs, m.isva) for i = 1:m.nargs] else - decls = Any[("", "") for i = 1:length(m.sig.parameters)] + decls = Any[("", "") for i = 1:length(unwrap_unionall(m.sig).parameters)] end return tv, decls, file, line end function kwarg_decl(m::Method, kwtype::DataType) - sig = Tuple{kwtype, Core.AnyVector, m.sig.parameters...} + sig = Tuple{kwtype, Core.AnyVector, unwrap_unionall(m.sig).parameters...} kwli = ccall(:jl_methtable_lookup, Any, (Any, Any, UInt), kwtype.name.mt, sig, max_world(m)) if kwli !== nothing kwli = kwli::Method @@ -75,9 +85,10 @@ end function show(io::IO, m::Method; kwtype::Nullable{DataType}=Nullable{DataType}()) tv, decls, file, line = arg_decl_parts(m) - ft = m.sig.parameters[1] + sig = unwrap_unionall(m.sig) + ft = sig.parameters[1] d1 = decls[1] - if m.sig === Tuple + if sig === Tuple print(io, m.name) decls = Any[(), ("...", "")] elseif ft <: Function && @@ -85,7 +96,7 @@ function show(io::IO, m::Method; kwtype::Nullable{DataType}=Nullable{DataType}() # TODO: more accurate test? (tn.name === "#" name) ft == typeof(getfield(ft.name.module, ft.name.mt.name)) print(io, ft.name.mt.name) - elseif isa(ft, DataType) && ft.name === Type.name && isleaftype(ft) + elseif isa(ft, DataType) && ft.name === Type.body.name && isleaftype(ft) f = ft.parameters[1] if isa(f, DataType) && isempty(f.parameters) print(io, f) @@ -200,13 +211,14 @@ end function show(io::IO, ::MIME"text/html", m::Method; kwtype::Nullable{DataType}=Nullable{DataType}()) tv, decls, file, line = arg_decl_parts(m) - ft = m.sig.parameters[1] + sig = unwrap_unionall(m.sig) + ft = sig.parameters[1] d1 = decls[1] if ft <: Function && isdefined(ft.name.module, ft.name.mt.name) && ft == typeof(getfield(ft.name.module, ft.name.mt.name)) print(io, ft.name.mt.name) - elseif isa(ft, DataType) && ft.name === Type.name && isleaftype(ft) + elseif isa(ft, DataType) && ft.name === Type.body.name && isleaftype(ft) f = ft.parameters[1] if isa(f, DataType) && isempty(f.parameters) print(io, f) diff --git a/base/promotion.jl b/base/promotion.jl index 3ad9cb11f3497..4850113f01c52 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -7,25 +7,24 @@ typejoin(t::ANY) = (@_pure_meta; t) typejoin(t::ANY, ts...) = (@_pure_meta; typejoin(t, typejoin(ts...))) function typejoin(a::ANY, b::ANY) @_pure_meta - if isa(a,TypeConstructor); a = a.body; end - if isa(b,TypeConstructor); b = b.body; end if a <: b return b elseif b <: a return a end + if isa(a,UnionAll); a = a.body; end + if isa(b,UnionAll); b = b.body; end if isa(a,TypeVar) return typejoin(a.ub, b) end if isa(b,TypeVar) return typejoin(a, b.ub) end - if isa(a,Union) || isa(b,Union) - u = Union{a, b} - if !isa(u,Union) - return u - end - return reduce(typejoin, Bottom, u.types) + if isa(a,Union) + return typejoin(typejoin(a.a,a.b), b) + end + if isa(b,Union) + return typejoin(a, typejoin(b.a,b.b)) end if a <: Tuple if !(b <: Tuple) @@ -72,22 +71,26 @@ function typejoin(a::ANY, b::ANY) return Any end while b !== Any - if a <: b.name.primary + if a <: b.name.wrapper while a.name !== b.name a = supertype(a) end + aprimary = unwrap_unionall(a.name.wrapper) # join on parameters n = length(a.parameters) + if n == 0 + return aprimary + end p = Vector{Any}(n) for i = 1:n ai, bi = a.parameters[i], b.parameters[i] if ai === bi || (isa(ai,Type) && isa(bi,Type) && typeseq(ai,bi)) p[i] = ai else - p[i] = a.name.primary.parameters[i] + p[i] = aprimary.parameters[i] end end - return a.name.primary{p...} + return a.name.wrapper{p...} end b = supertype(b) end diff --git a/base/reducedim.jl b/base/reducedim.jl index cb92311655f3b..42eea53d25a82 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -80,7 +80,7 @@ reducedim_initarray0{T}(A::AbstractArray, region, v0::T) = reducedim_initarray0( # # The current scheme is basically following Steven G. Johnson's original implementation # -promote_union(T::Union) = promote_type(T.types...) +promote_union(T::Union) = promote_type(promote_union(T.a), promote_union(T.b)) promote_union(T) = T function reducedim_init{S}(f, op::typeof(+), A::AbstractArray{S}, region) @@ -117,7 +117,7 @@ reducedim_init(f, op::typeof(|), A::AbstractArray, region) = reducedim_initarray # specialize to make initialization more efficient for common cases for (IT, RT) in ((CommonReduceResult, :(eltype(A))), (SmallSigned, :Int), (SmallUnsigned, :UInt)) - T = Union{[AbstractArray{t} for t in IT.types]..., [AbstractArray{Complex{t}} for t in IT.types]...} + T = Union{[AbstractArray{t} for t in uniontypes(IT)]..., [AbstractArray{Complex{t}} for t in uniontypes(IT)]...} @eval begin reducedim_init(f::typeof(identity), op::typeof(+), A::$T, region) = reducedim_initarray(A, region, zero($RT)) diff --git a/base/reflection.jl b/base/reflection.jl index dbf5b50a7179e..49bfa092df172 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -352,6 +352,13 @@ end # low-level method lookup functions used by the compiler +unionlen(x::Union) = unionlen(x.a) + unionlen(x.b) +unionlen(x::ANY) = 1 + +_uniontypes(x::Union, ts) = (_uniontypes(x.a,ts); _uniontypes(x.b,ts); ts) +_uniontypes(x::ANY, ts) = (push!(ts, x); ts) +uniontypes(x::ANY) = _uniontypes(x, Any[]) + function _methods(f::ANY, t::ANY, lim::Int, world::UInt) ft = isa(f,Type) ? Type{f} : typeof(f) tt = isa(t,Type) ? Tuple{ft, t.parameters...} : Tuple{ft, t...} @@ -366,7 +373,7 @@ function _methods_by_ftype(t::ANY, lim::Int, world::UInt, min::Array{UInt,1}, ma nu = 1 for ti in tp if isa(ti, Union) - nu *= length((ti::Union).types) + nu *= unionlen(ti::Union) end end if 1 < nu <= 64 @@ -385,7 +392,7 @@ function _methods_by_ftype(t::Array, i, lim::Integer, matching::Array{Any,1}, wo else ti = t[i] if isa(ti, Union) - for ty in (ti::Union).types + for ty in uniontypes(ti::Union) t[i] = ty if _methods_by_ftype(t, i - 1, lim, matching, world, min, max) === false t[i] = ti diff --git a/base/replutil.jl b/base/replutil.jl index 4759425fd4d65..0f0a5c75d5530 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -376,7 +376,7 @@ function showerror(io::IO, ex::MethodError) # and sees a no method error for convert if (f === Base.convert && !isempty(arg_types_param) && !is_arg_types && isa(arg_types_param[1], DataType) && - arg_types_param[1].name === Type.name) + arg_types_param[1].name === Type.body.name) construct_type = arg_types_param[1].parameters[1] println(io) print(io, "This may have arisen from a call to the constructor $construct_type(...),", @@ -434,7 +434,7 @@ function show_method_candidates(io::IO, ex::MethodError, kwargs::Vector=Any[]) # pool MethodErrors for these two functions. if f === convert && !isempty(arg_types_param) at1 = arg_types_param[1] - if isa(at1,DataType) && (at1::DataType).name === Type.name && isleaftype(at1) + if isa(at1,DataType) && (at1::DataType).name === Type.body.name && isleaftype(at1) push!(funcs, (at1.parameters[1], arg_types_param[2:end])) end end @@ -442,8 +442,9 @@ function show_method_candidates(io::IO, ex::MethodError, kwargs::Vector=Any[]) for (func,arg_types_param) in funcs for method in methods(func) buf = IOBuffer() - s1 = method.sig.parameters[1] - sig = method.sig.parameters[2:end] + sig0 = unwrap_unionall(method.sig) + s1 = sig0.parameters[1] + sig = sig0.parameters[2:end] print(buf, " ") if !isa(func, s1) # function itself doesn't match diff --git a/base/serialize.jl b/base/serialize.jl index e55be50eb26bc..09e4a7a204955 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -33,7 +33,7 @@ const TAGS = Any[ Module, #=UndefRefTag=#Symbol, Task, String, Float16, SimpleVector, #=BackrefTag=#Symbol, Method, GlobalRef, - (), Bool, Any, :Any, Bottom, :reserved21, :reserved22, Type, + (), Bool, Any, :Any, Bottom, Core.BottomType, :reserved22, Type, :Array, :TypeVar, :Box, :lambda, :body, :return, :call, Symbol("::"), :(=), :null, :gotoifnot, :A, :B, :C, :M, :N, :T, :S, :X, :Y, @@ -386,7 +386,8 @@ function serialize(s::AbstractSerializer, g::GlobalRef) writetag(s.io, GLOBALREF_TAG) if g.mod === Main && isdefined(g.mod, g.name) && isconst(g.mod, g.name) v = getfield(g.mod, g.name) - if isa(v, DataType) && v === v.name.primary && should_send_whole_type(s, v) + unw = unwrap_unionall(v) + if isa(unw,DataType) && v === unw.name.wrapper && should_send_whole_type(s, unw) # handle references to types in Main by sending the whole type. # needed to be able to send nested functions (#15451). write(s.io, UInt8(1)) @@ -410,13 +411,14 @@ end function serialize_typename(s::AbstractSerializer, t::TypeName) serialize(s, t.name) serialize(s, t.names) - serialize(s, t.primary.super) - serialize(s, t.primary.parameters) - serialize(s, t.primary.types) - serialize(s, isdefined(t.primary, :instance)) - serialize(s, t.primary.abstract) - serialize(s, t.primary.mutable) - serialize(s, t.primary.ninitialized) + primary = unwrap_unionall(t.wrapper) + serialize(s, primary.super) + serialize(s, primary.parameters) + serialize(s, primary.types) + serialize(s, isdefined(primary, :instance)) + serialize(s, primary.abstract) + serialize(s, primary.mutable) + serialize(s, primary.ninitialized) if isdefined(t, :mt) serialize(s, t.mt.name) serialize(s, collect(Base.MethodList(t.mt))) @@ -471,7 +473,7 @@ function serialize_type_data(s, t::DataType, type_itself::Bool) serialize(s, mod) end if !isempty(t.parameters) - if (whole ? (t === t.name.primary) : (isdefined(mod,tname) && t === getfield(mod,tname))) + if (whole ? (t === unwrap_unionall(t.name.wrapper)) : (isdefined(mod,tname) && t === getfield(mod,tname))) serialize(s, svec()) else serialize(s, t.parameters) @@ -789,12 +791,13 @@ function deserialize_typename(s::AbstractSerializer, number) tn.names = names # TODO: there's an unhanded cycle in the dependency graph at this point: # while deserializing super and/or types, we may have encountered - # tn.primary and throw UndefRefException before we get to this point - tn.primary = ccall(:jl_new_datatype, Any, (Any, Any, Any, Any, Any, Cint, Cint, Cint), - tn, super, parameters, names, types, - abstr, mutable, ninitialized) - ty = tn.primary - ccall(:jl_set_const, Void, (Any, Any, Any), tn.module, tn.name, ty) + # tn.wrapper and throw UndefRefException before we get to this point + ndt = ccall(:jl_new_datatype, Any, (Any, Any, Any, Any, Any, Cint, Cint, Cint), + tn, super, parameters, names, types, + abstr, mutable, ninitialized) + tn.wrapper = ndt.name.wrapper + ccall(:jl_set_const, Void, (Any, Any, Any), tn.module, tn.name, tn.wrapper) + ty = tn.wrapper if has_instance && !isdefined(ty, :instance) # use setfield! directly to avoid `fieldtype` lowering expecting to see a Singleton object already on ty Core.setfield!(ty, :instance, ccall(:jl_new_struct, Any, (Any, Any...), ty)) @@ -831,7 +834,7 @@ function deserialize_datatype(s::AbstractSerializer) form = read(s.io, UInt8)::UInt8 if (form&2) != 0 tname = deserialize(s)::TypeName - ty = tname.primary + ty = tname.wrapper else name = deserialize(s)::Symbol mod = deserialize(s)::Module diff --git a/base/show.jl b/base/show.jl index 7a6f4f60ff0a5..d6c7d70a3b9aa 100644 --- a/base/show.jl +++ b/base/show.jl @@ -174,13 +174,36 @@ function show(io::IO, x::Core.IntrinsicFunction) print(io, unsafe_string(name)) end +show(io::IO, ::Core.BottomType) = print(io, "Union{}") + function show(io::IO, x::Union) print(io, "Union") - sorted_types = sort!(collect(x.types); by=string) + sorted_types = sort!(uniontypes(x); by=string) show_comma_array(io, sorted_types, '{', '}') end -show(io::IO, x::TypeConstructor) = show(io, x.body) +function print_without_params(x::ANY) + if isa(x,UnionAll) + b = unwrap_unionall(x) + return isa(b,DataType) && b.name.wrapper === x + end + return false +end + +function show(io::IO, x::UnionAll) + if print_without_params(x) + return show(io, unwrap_unionall(x).name) + end + tvar_env = get(io, :tvar_env, false) + if tvar_env !== false && isa(tvar_env, AbstractVector) + tvar_env = Any[tvar_env..., x.var] + else + tvar_env = Any[x.var] + end + show(IOContext(io, tvar_env = tvar_env), x.body) + print(io, " where ") + show(io, x.var) +end function show_type_parameter(io::IO, p::ANY, has_tvar_env::Bool) if has_tvar_env @@ -197,8 +220,7 @@ function show_datatype(io::IO, x::DataType) # and `true` if we are printing type parameters outside a method signature. has_tvar_env = get(io, :tvar_env, false) !== false - if ((!isempty(x.parameters) || x.name === Tuple.name) && x !== Tuple && - !(has_tvar_env && x.name.primary === x)) + if (!isempty(x.parameters) || x.name === Tuple.name) && x !== Tuple n = length(x.parameters) # Print homogeneous tuples with more than 3 elements compactly as NTuple{N, T} @@ -1045,7 +1067,7 @@ function show_lambda_types(io::IO, li::Core.MethodInstance) isdefined(ft.name.module, ft.name.mt.name) && ft == typeof(getfield(ft.name.module, ft.name.mt.name)) print(io, ft.name.mt.name) - elseif isa(ft, DataType) && ft.name === Type.name && isleaftype(ft) + elseif isa(ft, DataType) && ft.name === Type.body.name && isleaftype(ft) f = ft.parameters[1] print(io, f) else @@ -1078,27 +1100,35 @@ function show(io::IO, tv::TypeVar) # already printed and we don't need to print it again. # Otherwise, the lower bound should be printed if it is not `Bottom` # and the upper bound should be printed if it is not `Any`. - # The upper bound `Any` should also be printed if we are not in the - # existing `tvar_env` in order to resolve the ambiguity when printing a - # method signature. - # i.e. `foo{T,N}(::Array{T,N}, ::Vector)` should be printed as - # `foo{T,N}(::Array{T,N}, ::Array{T<:Any,1})` tvar_env = isa(io, IOContext) && get(io, :tvar_env, false) if isa(tvar_env, Vector{Any}) - have_env = true in_env = (tv in tvar_env::Vector{Any}) else - have_env = false in_env = false end - if !in_env && tv.lb !== Bottom - show(io, tv.lb) - print(io, "<:") + function show_bound(io::IO, b::ANY) + parens = isa(b,UnionAll) && !print_without_params(b) + parens && print(io, "(") + show(io, b) + parens && print(io, ")") + end + lb, ub = tv.lb, tv.ub + if !in_env && lb !== Bottom + if ub === Any + write(io, tv.name) + print(io, ">:") + show_bound(io, lb) + else + show_bound(io, lb) + print(io, "<:") + write(io, tv.name) + end + else + write(io, tv.name) end - write(io, tv.name) - if have_env ? !in_env : tv.ub !== Any + if !in_env && ub !== Any print(io, "<:") - show(io, tv.ub) + show_bound(io, ub) end nothing end @@ -1218,8 +1248,8 @@ function dumptype(io::IO, x::ANY, n::Int, indent) end directsubtype(a::DataType, b::DataType) = supertype(a).name === b.name -directsubtype(a::TypeConstructor, b::DataType) = directsubtype(a.body, b) -directsubtype(a::Union, b::DataType) = any(t->directsubtype(t, b), a.types) +directsubtype(a::UnionAll, b::DataType) = directsubtype(a.body, b) +directsubtype(a::Union, b::DataType) = directsubtype(a.a, b) || directsubtype(a.b, b) # Fallback to handle TypeVar's directsubtype(a, b::DataType) = false function dumpsubtypes(io::IO, x::DataType, m::Module, n::Int, indent) @@ -1231,10 +1261,9 @@ function dumpsubtypes(io::IO, x::DataType, m::Module, n::Int, indent) elseif isa(t, Module) && module_name(t) === s && module_parent(t) === m # recurse into primary module bindings dumpsubtypes(io, x, t, n, indent) - elseif isa(t, TypeConstructor) && directsubtype(t::TypeConstructor, x) + elseif isa(t, UnionAll) && directsubtype(t::UnionAll, x) println(io) print(io, indent, " ", m, ".", s) - isempty(t.parameters) || print(io, "{", join(t.parameters, ","), "}") print(io, " = ", t) elseif isa(t, Union) && directsubtype(t::Union, x) println(io) @@ -1696,8 +1725,8 @@ end # returns compact, prefix function array_eltype_show_how(X) e = eltype(X) - if isa(e,DataType) && e === e.name.primary - str = string(e.name) # Print "Array" rather than "Array{T,N}" + if print_without_params(e) + str = string(unwrap_unionall(e).name) # Print "Array" rather than "Array{T,N}" else str = string(e) end diff --git a/src/Makefile b/src/Makefile index 7fb46740a7bef..d7d176a38b144 100644 --- a/src/Makefile +++ b/src/Makefile @@ -40,7 +40,7 @@ SRCS := \ alloc dlload sys init task array dump toplevel jl_uv \ simplevector APInt-C runtime_intrinsics runtime_ccall \ threadgroup threading stackwalk gc gc-debug gc-pages \ - jlapi signal-handling safepoint jloptions timing + jlapi signal-handling safepoint jloptions timing subtype ifeq ($(USEMSVC), 1) SRCS += getopt diff --git a/src/abi_x86.cpp b/src/abi_x86.cpp index 8dabd249e8863..1206a138e5ea2 100644 --- a/src/abi_x86.cpp +++ b/src/abi_x86.cpp @@ -42,14 +42,14 @@ struct ABI_x86Layout : AbiLayout { inline bool is_complex64(jl_datatype_t *dt) const { return jl_complex_type != NULL && jl_is_datatype(dt) && - ((jl_datatype_t*)dt)->name == jl_complex_type->name && + ((jl_datatype_t*)dt)->name == ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_complex_type))->name && jl_tparam0(dt) == (jl_value_t*)jl_float32_type; } inline bool is_complex128(jl_datatype_t *dt) const { return jl_complex_type != NULL && jl_is_datatype(dt) && - ((jl_datatype_t*)dt)->name == jl_complex_type->name && + ((jl_datatype_t*)dt)->name == ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_complex_type))->name && jl_tparam0(dt) == (jl_value_t*)jl_float64_type; } diff --git a/src/alloc.c b/src/alloc.c index 5ecebb73abe04..5709545e9f594 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -18,12 +18,10 @@ JL_DLLEXPORT jl_value_t *jl_true; JL_DLLEXPORT jl_value_t *jl_false; jl_tvar_t *jl_typetype_tvar; -jl_datatype_t *jl_typetype_type; +jl_unionall_t *jl_typetype_type; jl_value_t *jl_ANY_flag; -jl_datatype_t *jl_typector_type; - -jl_datatype_t *jl_array_type; +jl_unionall_t *jl_array_type; jl_typename_t *jl_array_typename; jl_value_t *jl_array_uint8_type; jl_value_t *jl_array_any_type=NULL; @@ -53,8 +51,9 @@ jl_datatype_t *jl_methoderror_type; jl_datatype_t *jl_loaderror_type; jl_datatype_t *jl_initerror_type; jl_datatype_t *jl_undefvarerror_type; -jl_datatype_t *jl_ref_type; -jl_datatype_t *jl_pointer_type; +jl_unionall_t *jl_ref_type; +jl_unionall_t *jl_pointer_type; +jl_typename_t *jl_pointer_typename; jl_datatype_t *jl_void_type; jl_datatype_t *jl_voidpointer_type; jl_value_t *jl_an_empty_vec_any=NULL; @@ -576,7 +575,7 @@ JL_DLLEXPORT jl_code_info_t *jl_copy_code_info(jl_code_info_t *src) } // return a new lambda-info that has some extra static parameters merged in -jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_tupletype_t *types, jl_svec_t *sp) +jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_value_t *types, jl_svec_t *sp) { assert(jl_svec_len(m->sparam_syms) == jl_svec_len(sp) || sp == jl_emptysvec); jl_method_instance_t *new_linfo = jl_new_method_instance_uninit(); @@ -675,9 +674,10 @@ jl_method_t *jl_new_method(jl_code_info_t *definition, jl_svecset(sparam_syms, i, ((jl_tvar_t*)jl_svecref(tvars, i))->name); } jl_value_t *root = (jl_value_t*)sparam_syms; - JL_GC_PUSH1(&root); + jl_method_t *m = NULL; + JL_GC_PUSH2(&root, &m); - jl_method_t *m = jl_new_method_uninit(); + m = jl_new_method_uninit(); m->min_world = ++jl_world_counter; m->isstaged = isstaged; m->name = name; @@ -685,8 +685,14 @@ jl_method_t *jl_new_method(jl_code_info_t *definition, m->isva = isva; m->nargs = nargs; if (jl_svec_len(tvars) == 1) - tvars = (jl_svec_t*)jl_svecref(tvars, 0); - m->tvars = tvars; + m->tvars = (jl_svec_t*)jl_svecref(tvars, 0); + else + m->tvars = tvars; + int j; + for(j=(int)jl_svec_len(tvars)-1; j >= 0 ; j--) { + m->sig = jl_new_unionall_type((jl_tvar_t*)jl_svecref(tvars,j), m->sig); + jl_gc_wb(m, m->sig); + } m->sparam_syms = sparam_syms; root = (jl_value_t*)m; jl_method_set_source(m, definition); @@ -882,7 +888,7 @@ JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *modu jl_typename_type); tn->name = name; tn->module = module; - tn->primary = NULL; + tn->wrapper = NULL; tn->cache = jl_emptysvec; tn->linearcache = jl_emptysvec; tn->names = NULL; @@ -897,11 +903,9 @@ JL_DLLEXPORT jl_typename_t *jl_new_typename(jl_sym_t *name) return jl_new_typename_in(name, ptls->current_module); } -jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_datatype_t *super, - jl_svec_t *parameters) +jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_datatype_t *super, jl_svec_t *parameters) { - jl_datatype_t *dt = jl_new_datatype((jl_sym_t*)name, super, parameters, jl_emptysvec, jl_emptysvec, 1, 0, 0); - return dt; + return jl_new_datatype((jl_sym_t*)name, super, parameters, jl_emptysvec, jl_emptysvec, 1, 0, 0); } jl_datatype_t *jl_new_uninitialized_datatype(void) @@ -909,8 +913,7 @@ jl_datatype_t *jl_new_uninitialized_datatype(void) jl_ptls_t ptls = jl_get_ptls_states(); jl_datatype_t *t = (jl_datatype_t*)jl_gc_alloc(ptls, sizeof(jl_datatype_t), jl_datatype_type); t->depth = 0; - t->hastypevars = 0; - t->haswildcard = 0; + t->hasfreetypevars = 0; t->isleaftype = 1; t->layout = NULL; return t; @@ -1161,9 +1164,15 @@ JL_DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super t->name->names = fnames; jl_gc_wb(t->name, t->name->names); - if (t->name->primary == NULL) { - t->name->primary = (jl_value_t*)t; + if (t->name->wrapper == NULL) { + t->name->wrapper = (jl_value_t*)t; jl_gc_wb(t->name, t); + int i; + int np = jl_svec_len(parameters); + for (i=np-1; i >= 0; i--) { + t->name->wrapper = (jl_value_t*)jl_new_unionall_type((jl_tvar_t*)jl_svecref(parameters,i), t->name->wrapper); + jl_gc_wb(t->name, t->name->wrapper); + } } jl_precompute_memoized_dt(t); @@ -1198,26 +1207,22 @@ JL_DLLEXPORT jl_datatype_t *jl_new_bitstype(jl_value_t *name, jl_datatype_t *sup return bt; } -// type constructor ----------------------------------------------------------- +// unionall types ------------------------------------------------------------- -JL_DLLEXPORT jl_value_t *jl_new_type_constructor(jl_svec_t *p, jl_value_t *body) +JL_DLLEXPORT jl_tvar_t *jl_new_typevar(jl_sym_t *name, jl_value_t *lb, jl_value_t *ub) { jl_ptls_t ptls = jl_get_ptls_states(); -#ifndef NDEBUG - size_t i, np = jl_svec_len(p); - for (i = 0; i < np; i++) { - jl_tvar_t *tv = (jl_tvar_t*)jl_svecref(p, i); - assert(jl_is_typevar(tv) && !tv->bound); - } -#endif - jl_typector_t *tc = - (jl_typector_t*)jl_gc_alloc(ptls, sizeof(jl_typector_t), - jl_typector_type); - tc->parameters = p; - tc->body = body; - return (jl_value_t*)tc; + jl_tvar_t *tv = (jl_tvar_t*)jl_gc_alloc(ptls, sizeof(jl_tvar_t), jl_tvar_type); + tv->name = name; + tv->lb = lb; + tv->ub = ub; + return tv; } +JL_DLLEXPORT jl_unionall_t *jl_new_unionall_type(jl_tvar_t *v, jl_value_t *body) +{ + return (jl_unionall_t*)jl_new_struct(jl_unionall_type, v, body); +} // bits constructors ---------------------------------------------------------- diff --git a/src/array.c b/src/array.c index 9d5f09611994b..55063aa23ceb4 100644 --- a/src/array.c +++ b/src/array.c @@ -434,11 +434,11 @@ JL_DLLEXPORT jl_array_t *jl_alloc_vec_any(size_t n) return jl_alloc_array_1d(jl_array_any_type, n); } -JL_DLLEXPORT jl_value_t *jl_apply_array_type(jl_datatype_t *type, size_t dim) +JL_DLLEXPORT jl_value_t *jl_apply_array_type(jl_value_t *type, size_t dim) { jl_value_t *boxed_dim = jl_box_long(dim); JL_GC_PUSH1(&boxed_dim); - jl_value_t *ret = jl_apply_type((jl_value_t*)jl_array_type, jl_svec2(type, boxed_dim)); + jl_value_t *ret = jl_apply_type2((jl_value_t*)jl_array_type, type, boxed_dim); JL_GC_POP(); return ret; } @@ -563,7 +563,7 @@ JL_DLLEXPORT void jl_arrayset(jl_array_t *a, jl_value_t *rhs, size_t i) assert(i < jl_array_len(a)); jl_value_t *el_type = jl_tparam0(jl_typeof(a)); if (el_type != (jl_value_t*)jl_any_type) { - if (!jl_subtype(rhs, el_type, 1)) + if (!jl_isa(rhs, el_type)) jl_type_error("arrayset", el_type, rhs); } if (!a->flags.ptrarray) { diff --git a/src/ast.c b/src/ast.c index 1c807427286be..13c37387e5dd2 100644 --- a/src/ast.c +++ b/src/ast.c @@ -207,7 +207,7 @@ value_t fl_julia_scalar(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) return fl_ctx->T; else if (iscvalue(args[0]) && fl_ctx->jl_sym == cv_type((cvalue_t*)ptr(args[0]))) { jl_value_t *v = *(jl_value_t**)cptr(args[0]); - if (jl_subtype(v,(jl_value_t*)jl_number_type,1) || jl_is_string(v)) + if (jl_isa(v,(jl_value_t*)jl_number_type) || jl_is_string(v)) return fl_ctx->T; } return fl_ctx->F; diff --git a/src/builtins.c b/src/builtins.c index 00c7806dda4cb..24fd5530b305f 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -356,6 +356,11 @@ JL_CALLABLE(jl_f_sizeof) { JL_NARGS(sizeof, 1, 1); jl_value_t *x = args[0]; + if (jl_is_unionall(x)) { + x = jl_unwrap_unionall(x); + if (!jl_is_datatype(x)) + jl_error("argument is an abstract type; size is indeterminate"); + } if (jl_is_datatype(x)) { jl_datatype_t *dx = (jl_datatype_t*)x; if (dx->name == jl_array_typename || dx == jl_symbol_type || dx == jl_simplevector_type || @@ -384,24 +389,25 @@ JL_CALLABLE(jl_f_sizeof) JL_CALLABLE(jl_f_issubtype) { - JL_NARGS(subtype, 2, 2); - if (!jl_is_typevar(args[0])) - JL_TYPECHK(subtype, type, args[0]); - if (!jl_is_typevar(args[1])) - JL_TYPECHK(subtype, type, args[1]); - return (jl_subtype(args[0],args[1],0) ? jl_true : jl_false); + JL_NARGS(issubtype, 2, 2); + jl_value_t *a = args[0], *b = args[1]; + if (jl_is_typevar(a)) a = ((jl_tvar_t*)a)->ub; // TODO should we still allow this? + if (jl_is_typevar(b)) b = ((jl_tvar_t*)b)->ub; + JL_TYPECHK(issubtype, type, a); + JL_TYPECHK(issubtype, type, b); + return (jl_subtype(a,b) ? jl_true : jl_false); } JL_CALLABLE(jl_f_isa) { JL_NARGS(isa, 2, 2); JL_TYPECHK(isa, type, args[1]); - return (jl_subtype(args[0],args[1],1) ? jl_true : jl_false); + return (jl_isa(args[0],args[1]) ? jl_true : jl_false); } JL_DLLEXPORT void jl_typeassert(jl_value_t *x, jl_value_t *t) { - if (!jl_subtype(x,t,1)) + if (!jl_isa(x,t)) jl_type_error("typeassert", t, x); } @@ -409,7 +415,7 @@ JL_CALLABLE(jl_f_typeassert) { JL_NARGS(typeassert, 2, 2); JL_TYPECHK(typeassert, type, args[1]); - if (!jl_subtype(args[0],args[1],1)) + if (!jl_isa(args[0],args[1])) jl_type_error("typeassert", args[1], args[0]); return args[0]; } @@ -755,7 +761,7 @@ JL_CALLABLE(jl_f_setfield) idx = jl_field_index(st, (jl_sym_t*)args[1], 1); } jl_value_t *ft = jl_field_type(st,idx); - if (!jl_subtype(args[2], ft, 1)) { + if (!jl_isa(args[2], ft)) { jl_type_error("setfield!", ft, args[2]); } jl_set_nth_field(v, idx, args[2]); @@ -995,10 +1001,10 @@ JL_DLLEXPORT void jl_show(jl_value_t *stream, jl_value_t *v) JL_CALLABLE(jl_f_apply_type) { JL_NARGSV(apply_type, 1); - if (!jl_is_datatype(args[0]) && !jl_is_typector(args[0])) { - jl_type_error("Type{...} expression", (jl_value_t*)jl_type_type, args[0]); - } - return jl_apply_type_(args[0], &args[1], nargs-1); + if (!jl_is_unionall(args[0]) && args[0] != (jl_value_t*)jl_anytuple_type && + args[0] != (jl_value_t*)jl_uniontype_type) + jl_type_error("Type{...} expression", (jl_value_t*)jl_unionall_type, args[0]); + return jl_apply_type(args[0], &args[1], nargs-1); } // generic function reflection ------------------------------------------------ @@ -1032,7 +1038,7 @@ JL_CALLABLE(jl_f_invoke) else { jl_check_type_tuple(args[1], jl_gf_name(args[0]), "invoke"); } - if (!jl_tuple_subtype(&args[2], nargs-2, (jl_datatype_t*)argtypes, 1)) + if (!jl_tuple_isa(&args[2], nargs-2, (jl_datatype_t*)argtypes)) jl_error("invoke: argument type error"); args[1] = args[0]; // move function directly in front of arguments jl_value_t *res = jl_gf_invoke((jl_tupletype_t*)argtypes, &args[1], nargs-1); @@ -1087,10 +1093,10 @@ static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v) jl_datatype_t *dt = (jl_datatype_t*)tv; if (dt == jl_datatype_type) { jl_datatype_t *dtv = (jl_datatype_t*)v; - // `name->primary` is cacheable even though it contains TypeVars + // `name->wrapper` is cacheable even though it contains TypeVars // that don't have stable IDs. - if (jl_egal(dtv->name->primary, v)) - return bitmix(~dtv->name->hash, 0xaa5566aa); + //if (jl_egal(dtv->name->wrapper, v)) + // return bitmix(~dtv->name->hash, 0xaa5566aa); return bitmix(~dtv->name->hash, hash_svec(dtv->parameters)); } if (dt == jl_typename_type) @@ -1138,7 +1144,7 @@ static void add_builtin(const char *name, jl_value_t *v) jl_fptr_t jl_get_builtin_fptr(jl_value_t *b) { - assert(jl_subtype(b, (jl_value_t*)jl_builtin_type, 1)); + assert(jl_isa(b, (jl_value_t*)jl_builtin_type)); return jl_gf_mtable(b)->cache.leaf->func.linfo->fptr; } @@ -1183,16 +1189,17 @@ void jl_init_primitives(void) // builtin types add_builtin("Any", (jl_value_t*)jl_any_type); + add_builtin("Type", (jl_value_t*)jl_type_type); add_builtin("Void", (jl_value_t*)jl_void_type); add_builtin("nothing", (jl_value_t*)jl_nothing); - add_builtin("TypeVar", (jl_value_t*)jl_tvar_type); add_builtin("TypeName", (jl_value_t*)jl_typename_type); - add_builtin("TypeConstructor", (jl_value_t*)jl_typector_type); - add_builtin("Tuple", (jl_value_t*)jl_anytuple_type); - add_builtin("Vararg", (jl_value_t*)jl_vararg_type); - add_builtin("Type", (jl_value_t*)jl_type_type); add_builtin("DataType", (jl_value_t*)jl_datatype_type); + add_builtin("TypeVar", (jl_value_t*)jl_tvar_type); + add_builtin("UnionAll", (jl_value_t*)jl_unionall_type); add_builtin("Union", (jl_value_t*)jl_uniontype_type); + add_builtin("BottomType", (jl_value_t*)jl_bottomtype_type); + add_builtin("Tuple", (jl_value_t*)jl_anytuple_type); + add_builtin("Vararg", (jl_value_t*)jl_vararg_type); add_builtin("SimpleVector", (jl_value_t*)jl_simplevector_type); add_builtin("Module", (jl_value_t*)jl_module_type); @@ -1290,7 +1297,7 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt n += jl_static_show_x(out, (jl_value_t*)li->def->module, depth); if (li->specTypes) { n += jl_printf(out, "."); - n += jl_show_svec(out, li->specTypes->parameters, + n += jl_show_svec(out, ((jl_datatype_t*)jl_unwrap_unionall(li->specTypes))->parameters, jl_symbol_name(li->def->name), "(", ")"); } else { @@ -1312,8 +1319,9 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt n += jl_printf(out, "."); } n += jl_printf(out, "%s", jl_symbol_name(dv->name->name)); - if (dv->parameters && (jl_value_t*)dv != dv->name->primary && - !jl_types_equal((jl_value_t*)dv, (jl_value_t*)jl_tuple_type)) { + if (dv->parameters && (jl_value_t*)dv != dv->name->wrapper && + (jl_has_free_typevars(v) || + !jl_types_equal((jl_value_t*)dv, (jl_value_t*)jl_tuple_type))) { size_t j, tlen = jl_nparams(dv); if (tlen > 0) { n += jl_printf(out, "{"); @@ -1383,19 +1391,44 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt n += jl_printf(out, "\""); } else if (vt == jl_uniontype_type) { - n += jl_show_svec(out, ((jl_uniontype_t*)v)->types, "Union", "{", "}"); + n += jl_printf(out, "Union{"); + while (jl_is_uniontype(v)) { + n += jl_static_show_x(out, ((jl_uniontype_t*)v)->a, depth); + n += jl_printf(out, ", "); + v = ((jl_uniontype_t*)v)->b; + } + n += jl_static_show_x(out, v, depth); + n += jl_printf(out, "}"); } - else if (vt == jl_typector_type) { - n += jl_static_show_x(out, ((jl_typector_t*)v)->body, depth); + else if (vt == jl_unionall_type) { + jl_unionall_t *ua = (jl_unionall_t*)v; + n += jl_static_show_x(out, ua->body, depth); + n += jl_printf(out, " where "); + n += jl_static_show_x(out, (jl_value_t*)ua->var, depth->prev); } else if (vt == jl_tvar_type) { - if (((jl_tvar_t*)v)->lb != jl_bottom_type) { - n += jl_static_show(out, ((jl_tvar_t*)v)->lb); + jl_tvar_t *var = (jl_tvar_t*)v; + struct recur_list *p = depth; + int showbounds = 1; + while (showbounds && p) { + if (jl_is_unionall(p->v) && ((jl_unionall_t*)p->v)->var == var) + showbounds = 0; + p = p->prev; + } + jl_value_t *lb = var->lb, *ub = var->ub; + if (showbounds && lb != jl_bottom_type) { + if (jl_is_unionall(lb)) n += jl_printf(out, "("); + n += jl_static_show_x(out, lb, depth); + if (jl_is_unionall(lb)) n += jl_printf(out, ")"); + n += jl_printf(out, "<:"); + } + n += jl_printf(out, "%s", jl_symbol_name(var->name)); + if (showbounds && ub != (jl_value_t*)jl_any_type) { n += jl_printf(out, "<:"); + if (jl_is_unionall(ub)) n += jl_printf(out, "("); + n += jl_static_show_x(out, ub, depth); + if (jl_is_unionall(ub)) n += jl_printf(out, ")"); } - n += jl_printf(out, "%s%s<:", (((jl_tvar_t*)v)->bound)?"#":"", - jl_symbol_name(((jl_tvar_t*)v)->name)); - n += jl_static_show(out, ((jl_tvar_t*)v)->ub); } else if (vt == jl_module_type) { jl_module_t *m = (jl_module_t*)v; @@ -1590,7 +1623,7 @@ JL_DLLEXPORT size_t jl_static_show_func_sig(JL_STREAM *s, jl_value_t *type) if (ftype == NULL) return jl_static_show(s, type); size_t n = 0; - if (jl_nparams(ftype)==0 || ftype == ((jl_datatype_t*)ftype)->name->primary) { + if (jl_nparams(ftype)==0 || ftype == ((jl_datatype_t*)ftype)->name->wrapper) { n += jl_printf(s, "%s", jl_symbol_name(((jl_datatype_t*)ftype)->name->mt->name)); } else { @@ -1598,6 +1631,8 @@ JL_DLLEXPORT size_t jl_static_show_func_sig(JL_STREAM *s, jl_value_t *type) n += jl_static_show(s, ftype); n += jl_printf(s, ")"); } + // TODO: better way to show method parameters + type = jl_unwrap_unionall(type); size_t tl = jl_nparams(type); n += jl_printf(s, "("); size_t i; @@ -1609,7 +1644,7 @@ JL_DLLEXPORT size_t jl_static_show_func_sig(JL_STREAM *s, jl_value_t *type) } else { if (jl_is_vararg_type(tp)) { - n += jl_static_show(s, jl_tparam0(tp)); + n += jl_static_show(s, jl_unwrap_vararg(tp)); n += jl_printf(s, "..."); } else { diff --git a/src/ccall.cpp b/src/ccall.cpp index 1d659a2c1c6de..88528ee69b6ab 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -721,7 +721,7 @@ static jl_cgval_t emit_cglobal(jl_value_t **args, size_t nargs, jl_codectx_t *ct } JL_TYPECHK(cglobal, type, rt); - rt = (jl_value_t*)jl_apply_type((jl_value_t*)jl_pointer_type, jl_svec1(rt)); + rt = (jl_value_t*)jl_apply_type1((jl_value_t*)jl_pointer_type, rt); } else { rt = (jl_value_t*)jl_voidpointer_type; @@ -986,7 +986,7 @@ static jl_cgval_t emit_llvmcall(jl_value_t **args, size_t nargs, jl_codectx_t *c Value *v = julia_to_native(t, toboxed, tti, arg, false, false, false, i, ctx, NULL); // make sure args are rooted - bool issigned = jl_signed_type && jl_subtype(tti, (jl_value_t*)jl_signed_type, 0); + bool issigned = jl_signed_type && jl_subtype(tti, (jl_value_t*)jl_signed_type); argvals[i] = llvm_type_rewrite(v, t, t, false, false, issigned, ctx); } @@ -1203,7 +1203,7 @@ static std::string generate_func_sig( jl_value_t *tti = jl_svecref(tt,i); if (jl_is_vararg_type(tti)) { current_isVa = true; - tti = jl_tparam0(tti); + tti = jl_unwrap_vararg(tti); } Type *t = NULL; bool isboxed; @@ -1222,7 +1222,7 @@ static std::string generate_func_sig( // small integer arguments. jl_datatype_t *bt = (jl_datatype_t*)tti; if (jl_datatype_size(bt) < 4) { - if (jl_signed_type && jl_subtype(tti, (jl_value_t*)jl_signed_type, 0)) + if (jl_signed_type && jl_subtype(tti, (jl_value_t*)jl_signed_type)) ab.addAttribute(Attribute::SExt); else ab.addAttribute(Attribute::ZExt); @@ -1323,11 +1323,11 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) if (rt == NULL) { static_rt = false; if (jl_is_type_type(rtt_)) { - if (jl_subtype(jl_tparam0(rtt_), (jl_value_t*)jl_pointer_type, 0)) { + if (jl_subtype(jl_tparam0(rtt_), (jl_value_t*)jl_pointer_type)) { // substitute Ptr{Void} for statically-unknown pointer type rt = (jl_value_t*)jl_voidpointer_type; } - else if (jl_subtype(jl_tparam0(rtt_), (jl_value_t*)jl_array_type, 0)) { + else if (jl_subtype(jl_tparam0(rtt_), (jl_value_t*)jl_array_type)) { // `Array` used as return type just returns a julia object reference rt = (jl_value_t*)jl_any_type; static_rt = true; @@ -1618,7 +1618,7 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) assert(nargt == 3); jl_value_t *f = static_eval(args[4], ctx, false, false); jl_value_t *frt = expr_type(args[6], ctx); - if (f && (jl_is_type_type((jl_value_t*)frt) && !jl_has_typevars(jl_tparam0(frt)))) { + if (f && (jl_is_type_type((jl_value_t*)frt) && !jl_has_free_typevars(jl_tparam0(frt)))) { jl_value_t *fargt = static_eval(args[8], ctx, true, true); if (fargt) { if (jl_is_tuple(fargt)) { @@ -1759,7 +1759,7 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) Value *v = julia_to_native(largty, toboxed, jargty, arg, addressOf, byRef, false, ai + 1, ctx, &needStackRestore); - bool issigned = jl_signed_type && jl_subtype(jargty, (jl_value_t*)jl_signed_type, 0); + bool issigned = jl_signed_type && jl_subtype(jargty, (jl_value_t*)jl_signed_type); argvals[ai + sret] = llvm_type_rewrite(v, largty, ai + sret < fargt_sig.size() ? fargt_sig.at(ai + sret) : fargt_vasig, false, byRef, issigned, ctx); diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 34b5f66c68555..3f25b1af37958 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -129,7 +129,7 @@ static DIType julia_type_to_di(jl_value_t *jt, DIBuilder *dbuilder, bool isboxed jt == (jl_value_t*)jl_simplevector_type || jt == (jl_value_t*)jl_datatype_type || jt == (jl_value_t*)jl_method_instance_type) return jl_pvalue_dillvmt; - if (jl_is_typector(jt) || jl_is_typevar(jt)) + if (jl_is_unionall(jt) || jl_is_typevar(jt)) return jl_pvalue_dillvmt; assert(jl_is_datatype(jt)); jl_datatype_t *jdt = (jl_datatype_t*)jt; @@ -756,7 +756,7 @@ static void emit_typecheck(const jl_cgval_t &x, jl_value_t *type, const std::str jl_codectx_t *ctx) { Value *istype; - // if (jl_subtype(x.typ, type, 0)) { + // if (jl_subtype(x.typ, type)) { // // This case should already be handled by the caller // return; // } @@ -772,11 +772,9 @@ static void emit_typecheck(const jl_cgval_t &x, jl_value_t *type, const std::str istype = builder. CreateICmpNE( #if JL_LLVM_VERSION >= 30700 - builder.CreateCall(prepare_call(jlsubtype_func), { vx, literal_pointer_val(type), - ConstantInt::get(T_int32,1) }), + builder.CreateCall(prepare_call(jlisa_func), { vx, literal_pointer_val(type) }), #else - builder.CreateCall3(prepare_call(jlsubtype_func), vx, literal_pointer_val(type), - ConstantInt::get(T_int32,1)), + builder.CreateCall2(prepare_call(jlisa_func), vx, literal_pointer_val(type)), #endif ConstantInt::get(T_int32,0)); } @@ -1018,7 +1016,7 @@ static jl_value_t *expr_type(jl_value_t *e, jl_codectx_t *ctx) return (jl_value_t*)jl_any_type; } type_of_constant: - if (jl_is_datatype(e) || jl_is_uniontype(e) || jl_is_typector(e)) + if (jl_is_type(e)) return (jl_value_t*)jl_wrap_Type(e); return (jl_value_t*)jl_typeof(e); } @@ -1595,7 +1593,7 @@ static void emit_cpointercheck(const jl_cgval_t &x, const std::string &msg, jl_c Value *istype = builder.CreateICmpEQ(emit_datatype_name(t), - literal_pointer_val((jl_value_t*)jl_pointer_type->name)); + literal_pointer_val((jl_value_t*)jl_pointer_typename)); BasicBlock *failBB = BasicBlock::Create(jl_LLVMContext,"fail",ctx->f); BasicBlock *passBB = BasicBlock::Create(jl_LLVMContext,"pass"); builder.CreateCondBr(istype, passBB, failBB); @@ -1746,7 +1744,7 @@ static jl_cgval_t emit_new_struct(jl_value_t *ty, size_t nargs, jl_value_t **arg jl_value_t *jtype = jl_svecref(sty->types,i); Type *fty = julia_type_to_llvm(jtype); jl_cgval_t fval_info = emit_expr(args[i+1], ctx); - if (!jl_subtype(fval_info.typ, jtype, 0)) + if (!jl_subtype(fval_info.typ, jtype)) emit_typecheck(fval_info, jtype, "new", ctx); if (!type_is_ghost(fty)) { Value *fval = NULL, *dest = NULL; @@ -1791,7 +1789,7 @@ static jl_cgval_t emit_new_struct(jl_value_t *ty, size_t nargs, jl_value_t **arg jl_cgval_t strctinfo = mark_julia_type(strct, true, ty, ctx); if (f1) { jl_cgval_t f1info = mark_julia_type(f1, true, jl_any_type, ctx); - if (!jl_subtype(expr_type(args[1],ctx), jl_field_type(sty,0), 0)) + if (!jl_subtype(expr_type(args[1],ctx), jl_field_type(sty,0))) emit_typecheck(f1info, jl_field_type(sty,0), "new", ctx); emit_setfield(sty, strctinfo, 0, f1info, ctx, false, false); } @@ -1813,7 +1811,7 @@ static jl_cgval_t emit_new_struct(jl_value_t *ty, size_t nargs, jl_value_t **arg need_wb = true; } if (rhs.isboxed) { - if (!jl_subtype(expr_type(args[i],ctx), jl_svecref(sty->types,i-1), 0)) + if (!jl_subtype(expr_type(args[i],ctx), jl_svecref(sty->types,i-1))) emit_typecheck(rhs, jl_svecref(sty->types,i-1), "new", ctx); } if (might_need_root(args[i])) // TODO: how to remove this? diff --git a/src/codegen.cpp b/src/codegen.cpp index 826530e0d07e5..b3a9f90fb377a 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -365,7 +365,7 @@ static Function *jlleave_func; static Function *jlegal_func; static Function *jlalloc_pool_func; static Function *jlalloc_big_func; -static Function *jlsubtype_func; +static Function *jlisa_func; static Function *setjmp_func; static Function *memcmp_func; static Function *box_int8_func; @@ -674,7 +674,7 @@ static inline jl_cgval_t remark_julia_type(const jl_cgval_t &v, jl_value_t *typ) static inline jl_cgval_t mark_julia_const(jl_value_t *jv) { jl_value_t *typ; - if (jl_is_datatype(jv) || jl_is_uniontype(jv) || jl_is_typector(jv)) + if (jl_is_type(jv)) typ = (jl_value_t*)jl_wrap_Type(jv); else typ = jl_typeof(jv); @@ -2273,8 +2273,8 @@ static Value *emit_f_is(const jl_cgval_t &arg1, const jl_cgval_t &arg2, jl_codec if (rt1==(jl_value_t*)jl_sym_type || rt2==(jl_value_t*)jl_sym_type || jl_is_mutable_datatype(rt1) || jl_is_mutable_datatype(rt2)) // excludes abstract types ptr_comparable = 1; - if (jl_subtype(rt1, (jl_value_t*)jl_type_type, 0) || - jl_subtype(rt2, (jl_value_t*)jl_type_type, 0)) // use typeseq for datatypes + if (jl_subtype(rt1, (jl_value_t*)jl_type_type) || + jl_subtype(rt2, (jl_value_t*)jl_type_type)) // use typeseq for datatypes ptr_comparable = 0; if ((jl_is_type_type(rt1) && jl_is_leaf_type(jl_tparam0(rt1))) || (jl_is_type_type(rt2) && jl_is_leaf_type(jl_tparam0(rt2)))) // can compare leaf types by pointer @@ -2341,7 +2341,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, jl_value_t *ty = expr_type(args[2], ctx); rt2 = ty; if (jl_is_type_type(ty) && !jl_is_typevar(jl_tparam0(ty))) { jl_value_t *tp0 = jl_tparam0(ty); - if (jl_subtype(arg, tp0, 0)) { + if (jl_subtype(arg, tp0)) { *ret = emit_expr(args[1], ctx); JL_GC_POP(); return true; @@ -2362,7 +2362,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, return true; } } - if (jl_subtype(ty, (jl_value_t*)jl_type_type, 0)) { + if (jl_subtype(ty, (jl_value_t*)jl_type_type)) { *ret = emit_expr(args[1], ctx); JL_FEAT_REQUIRE(ctx, runtime); #if JL_LLVM_VERSION >= 30700 @@ -2384,15 +2384,15 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, JL_GC_POP(); return true; } - if (jl_is_type_type(ty) && !jl_has_typevars(jl_tparam0(ty))) { + if (jl_is_type_type(ty) && !jl_has_free_typevars(jl_tparam0(ty))) { jl_value_t *tp0 = jl_tparam0(ty); - if (jl_subtype(arg, tp0, 0)) { + if (jl_subtype(arg, tp0)) { emit_expr(args[1], ctx); // TODO remove if no side effects *ret = mark_julia_type(ConstantInt::get(T_int8, 1), false, jl_bool_type, ctx); JL_GC_POP(); return true; } - if (!jl_subtype(tp0, (jl_value_t*)jl_type_type, 0)) { + if (!jl_subtype(tp0, (jl_value_t*)jl_type_type)) { if (jl_is_leaf_type(arg)) { emit_expr(args[1], ctx); // TODO remove if no side effects *ret = mark_julia_type(ConstantInt::get(T_int8, 0), false, jl_bool_type, ctx); @@ -2418,7 +2418,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, rt2 = expr_type(args[2], ctx); if (jl_is_type_type(rt1) && !jl_is_typevar(jl_tparam0(rt1)) && jl_is_type_type(rt2) && !jl_is_typevar(jl_tparam0(rt2))) { - int issub = jl_subtype(jl_tparam0(rt1), jl_tparam0(rt2), 0); + int issub = jl_subtype(jl_tparam0(rt1), jl_tparam0(rt2)); // TODO: emit args[1] and args[2] in case of side effects? *ret = mark_julia_type(ConstantInt::get(T_int8, issub), false, jl_bool_type, ctx); JL_GC_POP(); @@ -2572,7 +2572,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, } if (jl_is_array_type(aty) && indexes_ok) { jl_value_t *ety = jl_tparam0(aty); - if (!jl_is_typevar(ety) && jl_subtype(vty, ety, 0)) { + if (!jl_is_typevar(ety) && jl_subtype(vty, ety)) { if (!jl_array_store_unboxed(ety)) ety = (jl_value_t*)jl_any_type; jl_value_t *ndp = jl_tparam1(aty); @@ -2668,7 +2668,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, } if (fldt == (jl_value_t*)jl_long_type && jl_is_leaf_type((jl_value_t*)stt)) { - if ((jl_is_structtype(stt) || jl_is_tuple_type(stt)) && !jl_subtype((jl_value_t*)jl_module_type, (jl_value_t*)stt, 0)) { + if ((jl_is_structtype(stt) || jl_is_tuple_type(stt)) && !jl_subtype((jl_value_t*)jl_module_type, (jl_value_t*)stt)) { size_t nfields = jl_datatype_nfields(stt); jl_cgval_t strct = emit_expr(args[1], ctx); // integer index @@ -2704,7 +2704,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, jl_value_t *ft = jl_svecref(sty->types, idx); jl_value_t *rhst = expr_type(args[3], ctx); rt2 = rhst; - if (jl_is_leaf_type((jl_value_t*)sty) && jl_subtype(rhst, ft, 0)) { + if (jl_is_leaf_type((jl_value_t*)sty) && jl_subtype(rhst, ft)) { // TODO: attempt better codegen for approximate types jl_cgval_t strct = emit_expr(args[1], ctx); // emit lhs *ret = emit_expr(args[3], ctx); @@ -2808,7 +2808,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, if (i > nargs) { jl_value_t *ty = static_eval(expr, ctx, true, true); if (ty!=NULL && jl_is_leaf_type(ty)) { - if (jl_has_typevars(ty)) { + if (jl_has_free_typevars(ty)) { // add root for types not cached. issue #7065 jl_add_method_root(ctx->linfo, ty); } @@ -3023,7 +3023,7 @@ static jl_cgval_t emit_call(jl_expr_t *ex, jl_codectx_t *ctx) JL_GC_POP(); return result; } - if (jl_subtype(f, (jl_value_t*)jl_builtin_type, 1)) { + if (jl_isa(f, (jl_value_t*)jl_builtin_type)) { bool handled = emit_builtin_call(&result, (jl_value_t*)f, args, nargs, ctx, expr); if (handled) { JL_GC_POP(); @@ -3033,7 +3033,7 @@ static jl_cgval_t emit_call(jl_expr_t *ex, jl_codectx_t *ctx) } // special case for known builtin not handled by emit_builtin_call - if (f && jl_subtype(f, (jl_value_t*)jl_builtin_type, 1)) { + if (f && jl_isa(f, (jl_value_t*)jl_builtin_type)) { std::map::iterator it = builtin_func_map.find(jl_get_builtin_fptr(f)); if (it != builtin_func_map.end()) { theFptr = (*it).second; @@ -3811,7 +3811,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t // first emit the arguments for (size_t i = 0; i < nargs; i++) { Value *val = &*AI++; - jl_value_t *jargty = jl_nth_slot_type(argt, i); + jl_value_t *jargty = jl_nth_slot_type((jl_value_t*)argt, i); // figure out how to unpack this type jl_cgval_t inputarg; if (jl_is_abstract_ref_type(jargty)) { @@ -3851,7 +3851,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t else { // something of type T // undo whatever we might have done to this poor argument - bool issigned = jl_signed_type && jl_subtype(jargty, (jl_value_t*)jl_signed_type, 0); + bool issigned = jl_signed_type && jl_subtype(jargty, (jl_value_t*)jl_signed_type); val = llvm_type_rewrite(val, val->getType(), fargt[i], true, byRefList[i], issigned, &ctx); bool isboxed; (void)julia_type_to_llvm(jargty, &isboxed); @@ -3945,7 +3945,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t retval = mark_julia_type(ret, true, astrt, &ctx); } - if (!jl_subtype(astrt, declrt, 0)) { + if (!jl_subtype(astrt, declrt)) { // inline a call to typeassert here emit_typecheck(retval, declrt, "cfunction", &ctx); } @@ -3963,7 +3963,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t else if (!type_is_ghost(crt)) { if (sret) prt = fargt_sig[0]->getContainedType(0); // sret is a PointerType - bool issigned = jl_signed_type && jl_subtype(declrt, (jl_value_t*)jl_signed_type, 0); + bool issigned = jl_signed_type && jl_subtype(declrt, (jl_value_t*)jl_signed_type); Value *v = julia_to_native(crt, toboxed, declrt, retval, false, false, false, 0, &ctx, NULL); r = llvm_type_rewrite(v, crt, prt, false, false, issigned, &ctx); @@ -4269,7 +4269,7 @@ static std::unique_ptr emit_function( if (jl_is_typevar(e)) needsparams = true; } - if (!va && ctx.nargs > 0 && !needsparams && lam->specTypes != jl_anytuple_type && src->inferred) { + if (!va && ctx.nargs > 0 && !needsparams && lam->specTypes != (jl_value_t*)jl_anytuple_type && src->inferred) { // not vararg, consider specialized signature for(size_t i=0; i < jl_nparams(lam->specTypes); i++) { if (isbits_spec(jl_tparam(lam->specTypes, i))) { // assumes !va @@ -5886,15 +5886,14 @@ static void init_julia_llvm_env(Module *m) "jl_egal", m); add_named_global(jlegal_func, &jl_egal); - std::vector subt_args(0); - subt_args.push_back(T_pjlvalue); - subt_args.push_back(T_pjlvalue); - subt_args.push_back(T_int32); - jlsubtype_func = - Function::Create(FunctionType::get(T_int32, subt_args, false), + std::vector isa_args(0); + isa_args.push_back(T_pjlvalue); + isa_args.push_back(T_pjlvalue); + jlisa_func = + Function::Create(FunctionType::get(T_int32, isa_args, false), Function::ExternalLinkage, - "jl_subtype", m); - add_named_global(jlsubtype_func, &jl_subtype); + "jl_isa", m); + add_named_global(jlisa_func, &jl_isa); std::vector alloc_pool_args(0); alloc_pool_args.push_back(T_pint8); diff --git a/src/dump.c b/src/dump.c index 79fee8bc7c429..3439f7169b701 100644 --- a/src/dump.c +++ b/src/dump.c @@ -127,7 +127,7 @@ typedef struct { } jl_serializer_state; static jl_value_t *jl_idtable_type = NULL; -static arraylist_t builtin_types; +static arraylist_t builtin_typenames; #define write_uint8(s, n) ios_putc((n), (s)) #define read_uint8(s) ((uint8_t)ios_getc(s)) @@ -504,7 +504,7 @@ static int type_recursively_external(jl_datatype_t *dt) return 0; if (module_in_worklist(p->name->module)) return 0; - if (p->name->primary != (jl_value_t*)p) { + if (jl_unwrap_unionall(p->name->wrapper) != (jl_value_t*)p) { if (!type_recursively_external(p)) return 0; } @@ -518,14 +518,14 @@ static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) int tag = 0; if (s->mode == MODE_MODULE) { int internal = module_in_worklist(dt->name->module); - if (!internal && dt->name->primary == (jl_value_t*)dt) { + if (!internal && jl_unwrap_unionall(dt->name->wrapper) == (jl_value_t*)dt) { tag = 6; // external primary type } else if (dt->uid == 0) { tag = 0; // normal struct } else if (internal) { - if (dt->name->primary == (jl_value_t*)dt) // comes up often since functions create types + if (jl_unwrap_unionall(dt->name->wrapper) == (jl_value_t*)dt) // comes up often since functions create types tag = 5; // internal, and not in the typename cache (just needs uid reassigned) else tag = 10; // anything else that's internal (just needs uid reassigned and possibly recaching) @@ -589,7 +589,7 @@ static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) int has_instance = (dt->instance != NULL); int has_layout = (dt->layout != NULL); write_uint8(s->s, dt->abstract | (dt->mutabl<<1) | (has_layout<<2) | (has_instance<<3) | - (dt->hastypevars<<4) | (dt->haswildcard<<5) | (dt->isleaftype<<6)); + (dt->hasfreetypevars<<4) | (dt->isleaftype<<5)); write_int32(s->s, dt->depth); if (!dt->abstract) { write_uint16(s->s, dt->ninitialized); @@ -600,13 +600,13 @@ static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) if (has_layout) { uint8_t layout = 0; - if (dt->layout == jl_array_type->layout) { + if (dt->layout == ((jl_datatype_t*)jl_unwrap_unionall(jl_array_type))->layout) { layout = 1; } else if (dt->layout == jl_void_type->layout) { layout = 2; } - else if (dt->layout == jl_pointer_type->layout) { + else if (dt->layout == ((jl_datatype_t*)jl_unwrap_unionall(jl_pointer_type))->layout) { layout = 3; } write_uint8(s->s, layout); @@ -869,7 +869,6 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v) jl_serialize_value(s, ((jl_tvar_t*)v)->name); jl_serialize_value(s, ((jl_tvar_t*)v)->lb); jl_serialize_value(s, ((jl_tvar_t*)v)->ub); - write_int8(s->s, ((jl_tvar_t*)v)->bound); } else if (jl_is_method(v)) { writetag(s->s, jl_method_type); @@ -1090,7 +1089,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v) } size_t nf = jl_datatype_nfields(t); if (nf == 0 && jl_datatype_size(t)>0) { - if (t->name == jl_pointer_type->name && jl_unbox_voidpointer(v) != (void*)-1) { + if (t->name == jl_pointer_typename && jl_unbox_voidpointer(v) != (void*)-1) { // normalize most pointers to NULL, to help catch memory errors // but permit MAP_FAILED / INVALID_HANDLE to be stored unchanged write_int32(s->s, 0); @@ -1183,7 +1182,7 @@ static void jl_serialize_lambdas_from_mod(jl_serializer_state *s, jl_module_t *m jl_methtable_t *mt = tn->mt; if (mt != NULL && (jl_value_t*)mt != jl_nothing && - (mt != jl_type_type_mt || tn == jl_type_type->name)) { + (mt != jl_type_type_mt || tn == jl_type_typename)) { jl_serialize_methtable_from_mod(s, tn); jl_serialize_missing_backedges_to_mod(s, mt); } @@ -1328,10 +1327,13 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v int tag = read_uint8(s->s); if (tag == 6 || tag == 7) { jl_typename_t *name = (jl_typename_t*)jl_deserialize_value(s, NULL); - jl_value_t *dtv = name->primary; + jl_value_t *dtv = name->wrapper; if (tag == 7) { jl_svec_t *parameters = (jl_svec_t*)jl_deserialize_value(s, NULL); - dtv = jl_apply_type(dtv, parameters); + dtv = jl_apply_type(dtv, jl_svec_data(parameters), jl_svec_len(parameters)); + } + else { + dtv = jl_unwrap_unionall(dtv); } backref_list.items[pos] = dtv; return dtv; @@ -1371,9 +1373,8 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v dt->mutabl = (flags>>1)&1; int has_layout = (flags>>2)&1; int has_instance = (flags>>3)&1; - dt->hastypevars = (flags>>4)&1; - dt->haswildcard = (flags>>5)&1; - dt->isleaftype = (flags>>6)&1; + dt->hasfreetypevars = (flags>>4)&1; + dt->isleaftype = (flags>>5)&1; dt->depth = depth; dt->types = NULL; dt->parameters = NULL; @@ -1392,13 +1393,13 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v if (has_layout) { uint8_t layout = read_uint8(s->s); if (layout == 1) { - dt->layout = jl_array_type->layout; + dt->layout = ((jl_datatype_t*)jl_unwrap_unionall(jl_array_type))->layout; } else if (layout == 2) { dt->layout = jl_void_type->layout; } else if (layout == 3) { - dt->layout = jl_pointer_type->layout; + dt->layout = ((jl_datatype_t*)jl_unwrap_unionall(jl_pointer_type))->layout; } else { assert(layout == 0); @@ -1965,8 +1966,7 @@ static jl_value_t *jl_deserialize_value_(jl_serializer_state *s, jl_value_t *vta return jl_deserialize_value_expr(s, vtag); } else if (vtag == (jl_value_t*)jl_tvar_type) { - jl_tvar_t *tv = (jl_tvar_t*)jl_gc_alloc(s->ptls, sizeof(jl_tvar_t), - jl_tvar_type); + jl_tvar_t *tv = (jl_tvar_t*)jl_gc_alloc(s->ptls, sizeof(jl_tvar_t), jl_tvar_type); if (usetable) arraylist_push(&backref_list, tv); tv->name = (jl_sym_t*)jl_deserialize_value(s, NULL); @@ -1975,7 +1975,6 @@ static jl_value_t *jl_deserialize_value_(jl_serializer_state *s, jl_value_t *vta jl_gc_wb(tv, tv->lb); tv->ub = jl_deserialize_value(s, &tv->ub); jl_gc_wb(tv, tv->ub); - tv->bound = read_int8(s->s); return (jl_value_t*)tv; } else if (vtag == (jl_value_t*)jl_method_type) { @@ -2242,7 +2241,7 @@ static void jl_reinit_item(jl_value_t *v, int how, arraylist_t *tracee_list) case 3: { // rehash MethodTable jl_methtable_t *mt = (jl_methtable_t*)v; jl_typemap_rehash(mt->defs, 0); - jl_typemap_rehash(mt->cache, (mt == jl_type_type->name->mt) ? 0 : 1); + jl_typemap_rehash(mt->cache, (mt == jl_type_typename->mt) ? 0 : 1); if (tracee_list) arraylist_push(tracee_list, mt); break; @@ -2348,20 +2347,20 @@ static void jl_save_system_image_to_stream(ios_t *f) write_uint64(f, jl_typeinf_world); // deserialize method tables of builtin types - jl_serialize_value(&s, jl_type_type->name->mt); + jl_serialize_value(&s, jl_type_typename->mt); jl_serialize_value(&s, jl_intrinsic_type->name->mt); jl_serialize_value(&s, jl_sym_type->name->mt); - jl_serialize_value(&s, jl_array_type->name->mt); + jl_serialize_value(&s, jl_array_typename->mt); jl_serialize_value(&s, jl_module_type->name->mt); jl_prune_type_cache(jl_tuple_typename->cache); jl_prune_type_cache(jl_tuple_typename->linearcache); - jl_prune_type_cache(jl_type_type->name->cache); + jl_prune_type_cache(jl_type_typename->cache); intptr_t i; - for (i = 0; i < builtin_types.len; i++) { - jl_serialize_value(&s, ((jl_datatype_t*)builtin_types.items[i])->name->cache); - jl_serialize_value(&s, ((jl_datatype_t*)builtin_types.items[i])->name->linearcache); + for (i = 0; i < builtin_typenames.len; i++) { + jl_serialize_value(&s, ((jl_typename_t*)builtin_typenames.items[i])->cache); + jl_serialize_value(&s, ((jl_typename_t*)builtin_typenames.items[i])->linearcache); } // ensure everything in deser_tag is reassociated with its GlobalValue @@ -2453,18 +2452,18 @@ static void jl_restore_system_image_from_stream(ios_t *f) jl_typeinf_world = read_uint64(f); jl_type_type_mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL); - jl_type_type->name->mt = jl_type_type_mt; - jl_typector_type->name->mt = jl_type_type_mt; + jl_type_typename->mt = jl_type_type_mt; + jl_unionall_type->name->mt = jl_type_type_mt; jl_uniontype_type->name->mt = jl_type_type_mt; jl_datatype_type->name->mt = jl_type_type_mt; jl_intrinsic_type->name->mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL); jl_sym_type->name->mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL); - jl_array_type->name->mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL); + jl_array_typename->mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL); jl_module_type->name->mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL); intptr_t i; - for(i=0; i < builtin_types.len; i++) { - jl_typename_t *tn = ((jl_datatype_t*)builtin_types.items[i])->name; + for(i=0; i < builtin_typenames.len; i++) { + jl_typename_t *tn = (jl_typename_t*)builtin_typenames.items[i]; tn->cache = (jl_svec_t*)jl_deserialize_value(&s, NULL); jl_gc_wb(tn, tn->cache); tn->linearcache = (jl_svec_t*)jl_deserialize_value(&s, NULL); jl_gc_wb(tn, tn->linearcache); jl_resort_type_cache(tn->cache); @@ -3023,8 +3022,7 @@ void jl_init_serializer(void) jl_box_int32(30), jl_box_int32(31), jl_box_int32(32), #ifndef _P64 jl_box_int32(33), jl_box_int32(34), jl_box_int32(35), - jl_box_int32(36), jl_box_int32(37), jl_box_int32(38), - jl_box_int32(39), + jl_box_int32(36), jl_box_int32(37), #endif jl_box_int64(0), jl_box_int64(1), jl_box_int64(2), jl_box_int64(3), jl_box_int64(4), jl_box_int64(5), @@ -3039,34 +3037,33 @@ void jl_init_serializer(void) jl_box_int64(30), jl_box_int64(31), jl_box_int64(32), #ifdef _P64 jl_box_int64(33), jl_box_int64(34), jl_box_int64(35), - jl_box_int64(36), jl_box_int64(37), jl_box_int64(38), - jl_box_int64(39), + jl_box_int64(36), jl_box_int64(37), #endif - jl_labelnode_type, jl_linenumbernode_type, - jl_gotonode_type, jl_quotenode_type, jl_abstractstring_type, - jl_type_type, jl_bottom_type, jl_ref_type, jl_pointer_type, - jl_vararg_type, jl_abstractarray_type, - jl_densearray_type, jl_void_type, jl_function_type, - jl_typector_type, jl_typename_type, jl_builtin_type, jl_code_info_type, - jl_task_type, jl_uniontype_type, jl_typetype_type, jl_typetype_tvar, - jl_ANY_flag, jl_array_any_type, jl_intrinsic_type, jl_abstractslot_type, - jl_methtable_type, jl_typemap_level_type, - jl_voidpointer_type, jl_newvarnode_type, + jl_labelnode_type, jl_linenumbernode_type, jl_gotonode_type, + jl_quotenode_type, jl_type_type, jl_bottom_type, jl_ref_type, + jl_pointer_type, jl_vararg_type, jl_abstractarray_type, jl_void_type, + jl_densearray_type, jl_function_type, jl_unionall_type, jl_typename_type, + jl_builtin_type, jl_task_type, jl_uniontype_type, jl_typetype_type, + jl_typetype_tvar, jl_ANY_flag, jl_array_any_type, jl_intrinsic_type, + jl_abstractslot_type, jl_methtable_type, jl_typemap_level_type, + jl_voidpointer_type, jl_newvarnode_type, jl_abstractstring_type, jl_array_symbol_type, jl_anytuple_type, jl_tparam0(jl_anytuple_type), - jl_typeof(jl_emptytuple), jl_array_uint8_type, - jl_symbol_type->name, jl_ssavalue_type->name, jl_tuple_typename, - jl_ref_type->name, jl_pointer_type->name, jl_simplevector_type->name, - jl_datatype_type->name, jl_uniontype_type->name, jl_array_type->name, - jl_expr_type->name, jl_typename_type->name, jl_type_type->name, - jl_methtable_type->name, jl_typemap_level_type->name, jl_typemap_entry_type->name, jl_tvar_type->name, - jl_abstractarray_type->name, jl_vararg_type->name, - jl_densearray_type->name, jl_void_type->name, jl_method_instance_type->name, jl_method_type->name, + jl_typeof(jl_emptytuple), jl_array_uint8_type, jl_symbol_type->name, + jl_ssavalue_type->name, jl_tuple_typename, jl_code_info_type, jl_bottomtype_type, + ((jl_datatype_t*)jl_unwrap_unionall(jl_ref_type))->name, + jl_pointer_typename, jl_simplevector_type->name, jl_datatype_type->name, + jl_uniontype_type->name, jl_array_typename, jl_expr_type->name, + jl_typename_type->name, jl_type_typename, jl_methtable_type->name, + jl_typemap_level_type->name, jl_typemap_entry_type->name, jl_tvar_type->name, + ((jl_datatype_t*)jl_unwrap_unionall(jl_abstractarray_type))->name, + ((jl_datatype_t*)jl_unwrap_unionall(jl_densearray_type))->name, + jl_vararg_typename, jl_void_type->name, jl_method_instance_type->name, jl_method_type->name, jl_module_type->name, jl_function_type->name, jl_typedslot_type->name, - jl_abstractslot_type->name, jl_slotnumber_type->name, - jl_typector_type->name, jl_intrinsic_type->name, jl_task_type->name, - jl_labelnode_type->name, jl_linenumbernode_type->name, jl_builtin_type->name, - jl_gotonode_type->name, jl_quotenode_type->name, - jl_globalref_type->name, jl_string_type->name, jl_abstractstring_type->name, + jl_abstractslot_type->name, jl_slotnumber_type->name, jl_unionall_type->name, + jl_intrinsic_type->name, jl_task_type->name, jl_labelnode_type->name, + jl_linenumbernode_type->name, jl_builtin_type->name, jl_gotonode_type->name, + jl_quotenode_type->name, jl_globalref_type->name, jl_bottomtype_type->name, + jl_string_type->name, jl_abstractstring_type->name, ptls->root_task, @@ -3101,15 +3098,15 @@ void jl_init_serializer(void) } assert(i <= 256); - arraylist_new(&builtin_types, 0); - arraylist_push(&builtin_types, jl_array_type); - arraylist_push(&builtin_types, jl_ref_type); - arraylist_push(&builtin_types, jl_pointer_type); - arraylist_push(&builtin_types, jl_type_type); - arraylist_push(&builtin_types, jl_abstractarray_type); - arraylist_push(&builtin_types, jl_densearray_type); - arraylist_push(&builtin_types, jl_tuple_type); - arraylist_push(&builtin_types, jl_vararg_type); + arraylist_new(&builtin_typenames, 0); + arraylist_push(&builtin_typenames, jl_array_typename); + arraylist_push(&builtin_typenames, ((jl_datatype_t*)jl_ref_type->body)->name); + arraylist_push(&builtin_typenames, jl_pointer_typename); + arraylist_push(&builtin_typenames, jl_type_typename); + arraylist_push(&builtin_typenames, ((jl_datatype_t*)jl_unwrap_unionall(jl_abstractarray_type))->name); + arraylist_push(&builtin_typenames, ((jl_datatype_t*)jl_unwrap_unionall(jl_densearray_type))->name); + arraylist_push(&builtin_typenames, jl_tuple_typename); + arraylist_push(&builtin_typenames, jl_vararg_typename); } #ifdef __cplusplus diff --git a/src/gf.c b/src/gf.c index da41cb5ca0e0d..f798a0549b676 100644 --- a/src/gf.c +++ b/src/gf.c @@ -140,7 +140,7 @@ static int8_t jl_cachearg_offset(jl_methtable_t *mt) /// ----- Insertion logic for special entries ----- /// // get or create the MethodInstance for a specialization -JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m, jl_tupletype_t *type, jl_svec_t *sparams, size_t world) +JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m, jl_value_t *type, jl_svec_t *sparams, size_t world) { assert(world >= m->min_world && world <= m->max_world && "typemap lookup is corrupted"); JL_LOCK(&m->writelock); @@ -211,7 +211,7 @@ void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_t fptr) jl_method_instance_t *li = jl_new_method_instance_uninit(); li->fptr = fptr; li->jlcall_api = 1; - li->specTypes = jl_anytuple_type; + li->specTypes = (jl_value_t*)jl_anytuple_type; li->min_world = 1; li->max_world = ~(size_t)0; @@ -220,7 +220,7 @@ void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_t fptr) li->def->module = jl_core_module; li->def->isva = 1; li->def->nargs = 2; - li->def->sig = jl_anytuple_type; + li->def->sig = (jl_value_t*)jl_anytuple_type; li->def->tvars = jl_emptysvec; li->def->sparam_syms = jl_emptysvec; @@ -397,7 +397,7 @@ JL_DLLEXPORT jl_method_instance_t* jl_set_method_inferred( li->min_world = min_world; li->max_world = max_world; jl_typemap_insert(&li->def->specializations, (jl_value_t*)li->def, - li->specTypes, jl_emptysvec, NULL, jl_emptysvec, + (jl_tupletype_t*)li->specTypes, jl_emptysvec, NULL, jl_emptysvec, (jl_value_t*)li, 0, &tfunc_cache, li->min_world, li->max_world, NULL); } @@ -501,15 +501,16 @@ static int very_general_type(jl_value_t *t) ((jl_tvar_t*)t)->ub==(jl_value_t*)jl_any_type))); } -jl_value_t *jl_nth_slot_type(jl_tupletype_t *sig, size_t i) +jl_value_t *jl_nth_slot_type(jl_value_t *sig, size_t i) { + sig = jl_unwrap_unionall(sig); size_t len = jl_field_count(sig); if (len == 0) return NULL; if (i < len-1) return jl_tparam(sig, i); if (jl_is_vararg_type(jl_tparam(sig,len-1))) - return jl_tparam0(jl_tparam(sig,len-1)); + return jl_unwrap_vararg(jl_tparam(sig,len-1)); if (i == len-1) return jl_tparam(sig, i); return NULL; @@ -533,8 +534,8 @@ static jl_tupletype_t *join_tsig(jl_tupletype_t *tt, jl_tupletype_t *sig) // and the result of matching the type signature // needs to be corrected to the leaf type 'kind' jl_value_t *kind = jl_typeof(jl_tparam0(elt)); - if (jl_subtype(kind, decl_i, 0)) { - if (!jl_subtype((jl_value_t*)jl_type_type, decl_i, 0)) { + if (jl_subtype(kind, decl_i)) { + if (!jl_subtype((jl_value_t*)jl_type_type, decl_i)) { // TypeConstructors are problematic because they can be alternate // representations of any type. If we matched this method because // it matched the leaf type TypeConstructor, then don't @@ -575,6 +576,7 @@ static void jl_cacheable_sig( int *const makesimplesig) { int8_t isstaged = definition->isstaged; + assert(jl_is_tuple_type(type)); size_t i, np = jl_nparams(type); for (i = 0; i < np; i++) { jl_value_t *elt = jl_tparam(type, i); @@ -594,7 +596,7 @@ static void jl_cacheable_sig( // avoid specializing on an argument of type Tuple // unless matching a declared type of `::Type` if (jl_is_type_type(elt) && jl_is_tuple_type(jl_tparam0(elt)) && - (!jl_subtype(decl_i, (jl_value_t*)jl_type_type, 0) || is_kind(decl_i))) { // Type{Tuple{...}} + (!jl_subtype(decl_i, (jl_value_t*)jl_type_type) || is_kind(decl_i))) { // Type{Tuple{...}} elt = (jl_value_t*)jl_anytuple_type_type; // Type{T<:Tuple} if (!*newparams) *newparams = jl_svec_copy(type->parameters); jl_svecset(*newparams, i, elt); @@ -602,7 +604,7 @@ static void jl_cacheable_sig( } int notcalled_func = (i > 0 && i <= 8 && !(definition->called & (1 << (i - 1))) && - jl_subtype(elt, (jl_value_t*)jl_function_type, 0)); + jl_subtype(elt, (jl_value_t*)jl_function_type)); if (decl_i == jl_ANY_flag) { // don't specialize on slots marked ANY if (!*newparams) *newparams = jl_svec_copy(type->parameters); @@ -611,9 +613,9 @@ static void jl_cacheable_sig( } else if (notcalled_func && (decl_i == (jl_value_t*)jl_any_type || decl_i == (jl_value_t*)jl_function_type || - (jl_is_uniontype(decl_i) && jl_svec_len(((jl_uniontype_t*)decl_i)->types)==2 && - jl_subtype((jl_value_t*)jl_function_type, decl_i, 0) && - jl_subtype((jl_value_t*)jl_datatype_type, decl_i, 0)))) { + (jl_is_uniontype(decl_i) && //jl_svec_len(((jl_uniontype_t*)decl_i)->types)==2 && + jl_subtype((jl_value_t*)jl_function_type, decl_i) && + jl_subtype((jl_value_t*)jl_datatype_type, decl_i)))) { // and attempt to despecialize types marked Function, Callable, or Any // when called with a subtype of Function but is not called if (!*newparams) *newparams = jl_svec_copy(type->parameters); @@ -623,7 +625,7 @@ static void jl_cacheable_sig( } else if (jl_is_type_type(elt) && jl_is_type_type(jl_tparam0(elt)) && // give up on specializing static parameters for Type{Type{Type{...}}} - (jl_is_type_type(jl_tparam0(jl_tparam0(elt))) || !jl_has_typevars(decl_i))) { + (jl_is_type_type(jl_tparam0(jl_tparam0(elt))) || !jl_has_free_typevars(decl_i))) { /* actual argument was Type{...}, we computed its type as Type{Type{...}}. we must avoid unbounded nesting here, so @@ -632,11 +634,11 @@ static void jl_cacheable_sig( this can be determined using a type intersection. */ if (!*newparams) *newparams = jl_svec_copy(type->parameters); - if (i < jl_nparams(decl)) { - jl_value_t *declt = jl_tparam(decl, i); + if (decl_i) { + jl_value_t *declt = decl_i; // for T..., intersect with T if (jl_is_vararg_type(declt)) - declt = jl_tparam0(declt); + declt = jl_unwrap_vararg(declt); jl_value_t *di = jl_type_intersection(declt, (jl_value_t*)jl_typetype_type); assert(di != (jl_value_t*)jl_bottom_type); if (is_kind(di)) @@ -653,7 +655,7 @@ static void jl_cacheable_sig( *need_guard_entries = 1; } else if (jl_is_type_type(elt) && very_general_type(decl_i) && - !jl_has_typevars(decl_i)) { + !jl_has_free_typevars(decl_i)) { /* here's a fairly simple heuristic: if this argument slot's declared type is general (Type, Any, or ANY), @@ -712,8 +714,8 @@ JL_DLLEXPORT int jl_is_cacheable_sig( // and the result of matching the type signature // needs to be corrected to the leaf type 'kind' jl_value_t *kind = jl_typeof(jl_tparam0(elt)); - if (kind != (jl_value_t*)jl_tvar_type && jl_subtype(kind, decl_i, 0)) { - if (!jl_subtype((jl_value_t*)jl_type_type, decl_i, 0)) { + if (kind != (jl_value_t*)jl_tvar_type && jl_subtype(kind, decl_i)) { + if (!jl_subtype((jl_value_t*)jl_type_type, decl_i)) { return 0; } } @@ -721,19 +723,19 @@ JL_DLLEXPORT int jl_is_cacheable_sig( // avoid specializing on an argument of type Tuple // unless matching a declared type of `::Type` if (jl_is_type_type(elt) && jl_is_tuple_type(jl_tparam0(elt)) && - (!jl_subtype(decl_i, (jl_value_t*)jl_type_type, 0) || is_kind(decl_i))) { // Type{Tuple{...}} + (!jl_subtype(decl_i, (jl_value_t*)jl_type_type) || is_kind(decl_i))) { // Type{Tuple{...}} if (elt != (jl_value_t*)jl_anytuple_type_type) return 0; continue; } int notcalled_func = (i > 0 && i <= 8 && !(definition->called & (1 << (i - 1))) && - jl_subtype(elt, (jl_value_t*)jl_function_type, 0)); + jl_subtype(elt, (jl_value_t*)jl_function_type)); if (notcalled_func && (decl_i == (jl_value_t*)jl_any_type || decl_i == (jl_value_t*)jl_function_type || - (jl_is_uniontype(decl_i) && jl_svec_len(((jl_uniontype_t*)decl_i)->types)==2 && - jl_subtype((jl_value_t*)jl_function_type, decl_i, 0) && - jl_subtype((jl_value_t*)jl_datatype_type, decl_i, 0)))) { + (jl_is_uniontype(decl_i) && //jl_svec_len(((jl_uniontype_t*)decl_i)->types)==2 && + jl_subtype((jl_value_t*)jl_function_type, decl_i) && + jl_subtype((jl_value_t*)jl_datatype_type, decl_i)))) { // and attempt to despecialize types marked Function, Callable, or Any // when called with a subtype of Function but is not called if (elt != (jl_value_t*)jl_function_type) @@ -742,7 +744,7 @@ JL_DLLEXPORT int jl_is_cacheable_sig( } else if (jl_is_type_type(elt) && jl_is_type_type(jl_tparam0(elt)) && // give up on specializing static parameters for Type{Type{Type{...}}} - (jl_is_type_type(jl_tparam0(jl_tparam0(elt))) || !jl_has_typevars(decl_i))) { + (jl_is_type_type(jl_tparam0(jl_tparam0(elt))) || !jl_has_free_typevars(decl_i))) { /* actual argument was Type{...}, we computed its type as Type{Type{...}}. we must avoid unbounded nesting here, so @@ -755,12 +757,12 @@ JL_DLLEXPORT int jl_is_cacheable_sig( jl_value_t *declt = jl_tparam(decl, i); // for T..., intersect with T if (jl_is_vararg_type(declt)) - declt = jl_tparam0(declt); + declt = jl_unwrap_vararg(declt); jl_value_t *di = jl_type_intersection(declt, (jl_value_t*)jl_typetype_type); assert(di != (jl_value_t*)jl_bottom_type); if (is_kind(di)) return 0; - else if (!jl_subtype(di, elt, 0) || !jl_subtype(elt, di, 0)) + else if (!jl_subtype(di, elt) || !jl_subtype(elt, di)) return 0; } else { @@ -769,7 +771,7 @@ JL_DLLEXPORT int jl_is_cacheable_sig( continue; } else if (jl_is_type_type(elt) && very_general_type(decl_i) && - !jl_has_typevars(decl_i)) { + !jl_has_free_typevars(decl_i)) { /* here's a fairly simple heuristic: if this argument slot's declared type is general (Type, Any, or ANY), @@ -850,7 +852,7 @@ static jl_method_instance_t *cache_method(jl_methtable_t *mt, union jl_typemap_t size_t j = i; int all_are_subtypes = 1; for (; j < jl_svec_len(newparams); j++) { - if (!jl_subtype(jl_svecref(newparams, j), lasttype, 0)) { + if (!jl_subtype(jl_svecref(newparams, j), lasttype)) { all_are_subtypes = 0; break; } @@ -862,7 +864,8 @@ static jl_method_instance_t *cache_method(jl_methtable_t *mt, union jl_typemap_t jl_svecset(limited, i, jl_wrap_vararg(lasttype, (jl_value_t*)NULL)); } else { - jl_value_t *lastdeclt = jl_tparam(decl, jl_nparams(decl) - 1); + jl_value_t *unw = jl_unwrap_unionall(decl); + jl_value_t *lastdeclt = jl_tparam(unw, jl_nparams(unw) - 1); int nsp = jl_svec_len(sparams); if (nsp > 0) { jl_svec_t *env = jl_alloc_svec_uninit(2 * nsp); @@ -1088,16 +1091,16 @@ static int check_ambiguous_visitor(jl_typemap_entry_t *oldentry, struct typemap_ // we're ok if the new definition is actually the one we just // inferred to be required (see issue #3609). ideally this would // never happen, since if New ⊓ Old == New then we should have - // considered New more specific, but jl_args_morespecific is not + // considered New more specific, but jl_type_morespecific is not // perfect, so this is a useful fallback. return 1; } // we know type ∩ sig != Union{} and - // we know !jl_args_morespecific(type, sig) [before] - // or !jl_args_morespecific(sig, type) [after] + // we know !jl_type_morespecific(type, sig) [before] + // or !jl_type_morespecific(sig, type) [after] // now we are checking that the reverse is true - if (!jl_args_morespecific((jl_value_t*)(closure->after ? type : sig), + if (!jl_type_morespecific((jl_value_t*)(closure->after ? type : sig), (jl_value_t*)(closure->after ? sig : type))) { jl_typemap_entry_t *l = jl_typemap_assoc_by_type(map, (jl_tupletype_t*)isect, NULL, 0, 0, 0, closure->newentry->min_world); @@ -1150,12 +1153,13 @@ static jl_value_t *check_ambiguous_matches(union jl_typemap_t defs, jl_typemap_entry_t *newentry) { jl_tupletype_t *type = newentry->sig; - size_t l = jl_svec_len(type->parameters); + jl_tupletype_t *ttypes = jl_unwrap_unionall(type); + size_t l = jl_nparams(ttypes); jl_value_t *va = NULL; if (l > 0) { - va = jl_tparam(type, l - 1); + va = jl_tparam(ttypes, l - 1); if (jl_is_vararg_type(va)) - va = jl_tparam0(va); + va = jl_unwrap_vararg(va); else va = NULL; } @@ -1195,10 +1199,12 @@ static void method_overwrite(jl_typemap_entry_t *newentry, jl_method_t *oldvalue } } -static void update_max_args(jl_methtable_t *mt, jl_tupletype_t *type) +static void update_max_args(jl_methtable_t *mt, jl_value_t *type) { + type = jl_unwrap_unionall(type); + assert(jl_is_datatype(type)); size_t na = jl_nparams(type); - if (jl_va_tuple_kind(type) == JL_VARARG_UNBOUND) + if (jl_va_tuple_kind((jl_datatype_t*)type) == JL_VARARG_UNBOUND) na--; if (na > mt->max_args) mt->max_args = na; @@ -1322,9 +1328,8 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method { assert(jl_is_method(method)); assert(jl_is_mtable(mt)); - jl_tupletype_t *type = method->sig; + jl_value_t *type = method->sig; jl_svec_t *tvars = method->tvars; - assert(jl_is_tuple_type(type)); jl_value_t *oldvalue = NULL; struct invalidate_conflicting_env env; env.max_world = method->min_world - 1; @@ -1361,12 +1366,13 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method } } if (oldvalue) { - size_t l = jl_svec_len(type->parameters); + jl_datatype_t *unw = (jl_datatype_t*)jl_unwrap_unionall(type); + size_t l = jl_svec_len(unw->parameters); jl_value_t *va = NULL; if (l > 0) { - va = jl_tparam(type, l - 1); + va = jl_tparam(unw, l - 1); if (jl_is_vararg_type(va)) - va = jl_tparam0(va); + va = jl_unwrap_vararg(va); else va = NULL; } @@ -1557,7 +1563,7 @@ jl_llvm_functions_t jl_compile_for_dispatch(jl_method_instance_t **pli, size_t w if (li->jlcall_api == 2) return li->functionObjectsDecls; if (jl_options.compile_enabled == JL_OPTIONS_COMPILE_OFF || - jl_options.compile_enabled == JL_OPTIONS_COMPILE_MIN) { + jl_options.compile_enabled == JL_OPTIONS_COMPILE_MIN) { // copy fptr from the template method definition jl_method_t *def = li->def; if (def && !def->isstaged && def->unspecialized) { @@ -1610,7 +1616,7 @@ jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types, size_t world { JL_TIMING(METHOD_LOOKUP_COMPILE); assert(jl_nparams(types) > 0); - if (!jl_is_leaf_type((jl_value_t*)types) || jl_has_typevars((jl_value_t*)types)) + if (!jl_is_leaf_type((jl_value_t*)types) || jl_has_free_typevars((jl_value_t*)types)) return NULL; assert(jl_is_datatype(jl_tparam0(types))); @@ -1696,8 +1702,11 @@ jl_tupletype_t *jl_argtype_with_function(jl_function_t *f, jl_tupletype_t *types return (jl_tupletype_t*)tt; } +#if 0 static int tupletype_any_bottom(jl_value_t *sig) { + sig = jl_unwrap_unionall(sig); + assert(jl_is_tuple_type(sig)); jl_svec_t *types = ((jl_tupletype_t*)sig)->types; size_t i, l = jl_svec_len(types); for (i = 0; i < l; i++) { @@ -1792,7 +1801,8 @@ static int _compile_all_tvar_union(jl_tupletype_t *methsig, jl_svec_t *tvars) JL_GC_POP(); return complete; } - +#endif +#if 0 static int _compile_all_union(jl_tupletype_t *sig, jl_svec_t *tvars) { // f(::Union{...}, ...) is a common pattern @@ -1814,8 +1824,8 @@ static int _compile_all_union(jl_tupletype_t *sig, jl_svec_t *tvars) } } - if (count_unions == 0) - return _compile_all_tvar_union(sig, tvars); + //if (count_unions == 0) + // return _compile_all_tvar_union(sig, tvars); int *idx = (int*)alloca(sizeof(int) * count_unions); for (i = 0; i < count_unions; i++) { @@ -1850,13 +1860,14 @@ static int _compile_all_union(jl_tupletype_t *sig, jl_svec_t *tvars) } } methsig = jl_apply_tuple_type(p); - if (!_compile_all_tvar_union(methsig, tvars)) - complete = 0; + //if (!_compile_all_tvar_union(methsig, tvars)) + // complete = 0; } JL_GC_POP(); return complete; } +#endif static void _compile_all_deq(jl_array_t *found) { @@ -1886,7 +1897,7 @@ static void _compile_all_deq(jl_array_t *found) // keep track of whether all possible signatures have been cached (and thus whether it can skip trying to compile the template function) // this is necessary because many intrinsics try to call static_eval and thus are not compilable unspecialized - int complete = _compile_all_union(ml->sig, ml->tvars); + int complete = 0;//_compile_all_union(ml->sig, ml->tvars); if (complete) { if (linfo->fptr == NULL && linfo->functionObjectsDecls.functionObject == NULL) // indicate that this method doesn't need to be compiled, because it was fully covered above @@ -2030,15 +2041,14 @@ void jl_precompile(int all) { jl_compile_specializations(); } -// - #ifdef JL_TRACE static int trace_en = 0; static int error_en = 1; static void __attribute__ ((unused)) enable_trace(int x) { trace_en=x; } static void show_call(jl_value_t *F, jl_value_t **args, uint32_t nargs) { - jl_printf(JL_STDOUT, "%s(", jl_symbol_name(jl_gf_name(F))); + jl_static_show(JL_STDOUT, F); + jl_printf(JL_STDOUT, "("); for(size_t i=0; i < nargs; i++) { if (i > 0) jl_printf(JL_STDOUT, ", "); jl_static_show(JL_STDOUT, jl_typeof(args[i])); @@ -2184,7 +2194,7 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs) if (mfunc == NULL) { #ifdef JL_TRACE if (error_en) - show_call(F, args, nargs); + show_call(args[0], args, nargs); #endif jl_method_error((jl_function_t*)args[0], args, nargs, world); // unreachable @@ -2193,7 +2203,7 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs) #ifdef JL_TRACE if (traceen) - jl_printf(JL_STDOUT, " at %s:%d\n", jl_symbol_name(mfunc->file), mfunc->line); + jl_printf(JL_STDOUT, " at %s:%d\n", jl_symbol_name(mfunc->def->file), mfunc->def->line); #endif jl_value_t *res = jl_call_method_internal(mfunc, args, nargs); return verify_type(res); @@ -2375,7 +2385,8 @@ static jl_function_t *jl_new_generic_function_with_supertype(jl_sym_t *name, jl_ } jl_sym_t *tname = jl_symbol(prefixed); free(prefixed); - jl_datatype_t *ftype = jl_new_datatype(tname, st, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0); + jl_datatype_t *ftype = (jl_datatype_t*)jl_new_datatype(tname, st, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0); + assert(jl_is_datatype(ftype)); JL_GC_PUSH1(&ftype); ftype->name->mt->name = name; jl_gc_wb(ftype->name->mt, name); ftype->name->module = module; jl_gc_wb(ftype->name, module); @@ -2423,11 +2434,12 @@ JL_DLLEXPORT jl_svec_t *jl_match_method(jl_value_t *type, jl_value_t *sig, // arguments. static int tvar_exists_at_top_level(jl_value_t *tv, jl_tupletype_t *sig, int attop) { + sig = jl_unwrap_unionall(sig); int i, l=jl_nparams(sig); for(i=0; i < l; i++) { jl_value_t *a = jl_tparam(sig, i); if (jl_is_vararg_type(a)) - a = jl_tparam0(a); + a = jl_unwrap_vararg(a); if (a == tv) return 1; if (attop && jl_is_datatype(a)) { @@ -2501,8 +2513,8 @@ static int ml_matches_visitor(jl_typemap_entry_t *ml, struct typemap_intersectio // Instead we should have computed the intersection as (UnionAll S Type{T{S}}), // which is a bigger type that would not have been a subtype of the prior // match (prior_ti). We simulate that for now by checking jl_has_typevars. - if (jl_is_leaf_type(prior_ti) && !jl_has_typevars(closure->match.ti) && !jl_has_typevars(prior_ti) && - jl_subtype(closure->match.ti, prior_ti, 0)) { + if (jl_is_leaf_type(prior_ti) && !jl_has_free_typevars(closure->match.ti) && !jl_has_free_typevars(prior_ti) && + jl_subtype(closure->match.ti, prior_ti)) { skip = 1; break; } @@ -2547,7 +2559,7 @@ static int ml_matches_visitor(jl_typemap_entry_t *ml, struct typemap_intersectio // NOTE: jl_subtype check added in case the intersection is // over-approximated. if (matched_all_typevars && jl_types_equal(closure->match.ti, closure->match.type) && - jl_subtype(closure->match.type, (jl_value_t*)ml->sig, 0)) { + jl_subtype(closure->match.type, (jl_value_t*)ml->sig)) { done = 1; // terminate visiting method list } // here we have reached a definition that fully covers the arguments. @@ -2585,7 +2597,7 @@ static int ml_matches_visitor(jl_typemap_entry_t *ml, struct typemap_intersectio jl_value_t *ambi = jl_type_intersection_matching((jl_value_t*)ml->sig, (jl_value_t*)mambig->sig, &env, mambig->tvars); - if (jl_subtype(closure->match.ti, ambi, 0)) { + if (jl_subtype(closure->match.ti, ambi)) { return_this_match = 0; break; } @@ -2627,7 +2639,7 @@ static jl_value_t *ml_matches(union jl_typemap_t defs, int offs, if (l > 0) { va = jl_tparam(type, l - 1); if (jl_is_vararg_type(va)) - va = jl_tparam0(va); + va = jl_unwrap_vararg(va); else va = NULL; } diff --git a/src/init.c b/src/init.c index af168dd0dfbe9..59e601055e47e 100644 --- a/src/init.c +++ b/src/init.c @@ -624,7 +624,7 @@ void _julia_init(JL_IMAGE_SEARCH rel) if (!jl_options.image_file) { jl_core_module = jl_new_module(jl_symbol("Core")); - jl_type_type->name->mt->module = jl_core_module; + jl_type_typename->mt->module = jl_core_module; jl_top_module = jl_core_module; ptls->current_module = jl_core_module; jl_init_intrinsic_functions(); @@ -663,11 +663,16 @@ void _julia_init(JL_IMAGE_SEARCH rel) for(i=1; i < jl_core_module->bindings.size; i+=2) { if (table[i] != HT_NOTFOUND) { jl_binding_t *b = (jl_binding_t*)table[i]; - if (b->value && jl_is_datatype(b->value)) { - jl_datatype_t *tt = (jl_datatype_t*)b->value; - tt->name->module = jl_core_module; - if (tt->name->mt) - tt->name->mt->module = jl_core_module; + jl_value_t *v = b->value; + if (v) { + if (jl_is_unionall(v)) + v = jl_unwrap_unionall(v); + if (jl_is_datatype(v)) { + jl_datatype_t *tt = (jl_datatype_t*)v; + tt->name->module = jl_core_module; + if (tt->name->mt) + tt->name->mt->module = jl_core_module; + } } } } @@ -840,7 +845,7 @@ JL_DLLEXPORT void jl_get_system_hooks(void) jl_methoderror_type = (jl_datatype_t*)basemod("MethodError"); jl_loaderror_type = (jl_datatype_t*)basemod("LoadError"); jl_initerror_type = (jl_datatype_t*)basemod("InitError"); - jl_complex_type = (jl_datatype_t*)basemod("Complex"); + jl_complex_type = (jl_unionall_t*)basemod("Complex"); } void jl_get_builtins(void) diff --git a/src/interpreter.c b/src/interpreter.c index 0c3f9e7382032..50d940d9ed536 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -114,7 +114,7 @@ static int equiv_svec_dt(jl_svec_t *sa, jl_svec_t *sb) return 0; if (jl_is_typevar(a) && ((jl_tvar_t*)a)->name != ((jl_tvar_t*)b)->name) return 0; - if (!jl_subtype(a, b, 0) || !jl_subtype(b, a, 0)) + if (!jl_subtype(a, b) || !jl_subtype(b, a)) return 0; } return 1; @@ -129,8 +129,8 @@ static int equiv_type(jl_datatype_t *dta, jl_datatype_t *dtb) dta->ninitialized == dtb->ninitialized && equiv_svec_dt(dta->parameters, dtb->parameters) && equiv_svec_dt(dta->types, dtb->types) && - jl_subtype((jl_value_t*)dta->super, (jl_value_t*)dtb->super, 0) && - jl_subtype((jl_value_t*)dtb->super, (jl_value_t*)dta->super, 0) && + jl_subtype((jl_value_t*)dta->super, (jl_value_t*)dtb->super) && + jl_subtype((jl_value_t*)dtb->super, (jl_value_t*)dta->super) && jl_egal((jl_value_t*)dta->name->names, (jl_value_t*)dtb->name->names)); } @@ -148,9 +148,9 @@ void jl_set_datatype_super(jl_datatype_t *tt, jl_value_t *super) { if (!jl_is_datatype(super) || !jl_is_abstracttype(super) || tt->name == ((jl_datatype_t*)super)->name || - jl_subtype(super,(jl_value_t*)jl_vararg_type,0) || + jl_subtype(super,(jl_value_t*)jl_vararg_type) || jl_is_tuple_type(super) || - jl_subtype(super,(jl_value_t*)jl_type_type,0) || + jl_subtype(super,(jl_value_t*)jl_type_type) || super == (jl_value_t*)jl_builtin_type) { jl_errorf("invalid subtyping in definition of %s", jl_symbol_name(tt->name->name)); @@ -313,7 +313,8 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) jl_value_t *super = NULL; jl_value_t *temp = NULL; jl_datatype_t *dt = NULL; - JL_GC_PUSH4(¶, &super, &temp, &dt); + jl_value_t *w = NULL; + JL_GC_PUSH4(¶, &super, &temp, &w); assert(jl_is_svec(para)); if (jl_is_globalref(name)) { modu = jl_globalref_mod(name); @@ -321,11 +322,12 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) } assert(jl_is_symbol(name)); dt = jl_new_abstracttype(name, NULL, (jl_svec_t*)para); + w = dt->name->wrapper; jl_binding_t *b = jl_get_binding_wr(modu, (jl_sym_t*)name); temp = b->value; check_can_assign_type(b); - b->value = (jl_value_t*)dt; - jl_gc_wb_binding(b, dt); + b->value = w; + jl_gc_wb_binding(b, w); JL_TRY { inside_typedef = 1; super = eval(args[2], s); @@ -338,8 +340,8 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) jl_rethrow(); } b->value = temp; - if (temp == NULL || !equiv_type(dt, (jl_datatype_t*)temp)) { - jl_checked_assignment(b, (jl_value_t*)dt); + if (temp == NULL || !equiv_type(dt, (jl_datatype_t*)jl_unwrap_unionall(temp))) { + jl_checked_assignment(b, w); } JL_GC_POP(); return (jl_value_t*)jl_nothing; @@ -350,7 +352,8 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) jl_value_t *name = args[0]; jl_value_t *super = NULL, *para = NULL, *vnb = NULL, *temp = NULL; jl_datatype_t *dt = NULL; - JL_GC_PUSH4(¶, &super, &temp, &dt); + jl_value_t *w = NULL; + JL_GC_PUSH4(¶, &super, &temp, &w); if (jl_is_globalref(name)) { modu = jl_globalref_mod(name); name = (jl_value_t*)jl_globalref_name(name); @@ -367,11 +370,12 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) jl_errorf("invalid number of bits in type %s", jl_symbol_name((jl_sym_t*)name)); dt = jl_new_bitstype(name, NULL, (jl_svec_t*)para, nb); + w = dt->name->wrapper; jl_binding_t *b = jl_get_binding_wr(modu, (jl_sym_t*)name); temp = b->value; check_can_assign_type(b); - b->value = (jl_value_t*)dt; - jl_gc_wb_binding(b, dt); + b->value = w; + jl_gc_wb_binding(b, w); JL_TRY { inside_typedef = 1; super = eval(args[3], s); @@ -384,8 +388,8 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) jl_rethrow(); } b->value = temp; - if (temp == NULL || !equiv_type(dt, (jl_datatype_t*)temp)) { - jl_checked_assignment(b, (jl_value_t*)dt); + if (temp == NULL || !equiv_type(dt, (jl_datatype_t*)jl_unwrap_unionall(temp))) { + jl_checked_assignment(b, w); } JL_GC_POP(); return (jl_value_t*)jl_nothing; @@ -398,7 +402,8 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) jl_value_t *temp = NULL; jl_value_t *super = NULL; jl_datatype_t *dt = NULL; - JL_GC_PUSH4(¶, &super, &temp, &dt); + jl_value_t *w = NULL; + JL_GC_PUSH4(¶, &super, &temp, &w); if (jl_is_globalref(name)) { modu = jl_globalref_mod(name); name = (jl_value_t*)jl_globalref_name(name); @@ -406,22 +411,17 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) assert(jl_is_symbol(name)); assert(jl_is_svec(para)); temp = eval(args[2], s); // field names -#ifndef NDEBUG - size_t i, l = jl_svec_len(para); - for (i = 0; i < l; i++) { - assert(!((jl_tvar_t*)jl_svecref(para, i))->bound); - } -#endif dt = jl_new_datatype((jl_sym_t*)name, NULL, (jl_svec_t*)para, (jl_svec_t*)temp, NULL, 0, args[5]==jl_true ? 1 : 0, jl_unbox_long(args[6])); + w = dt->name->wrapper; jl_binding_t *b = jl_get_binding_wr(modu, (jl_sym_t*)name); temp = b->value; // save old value // temporarily assign so binding is available for field types check_can_assign_type(b); - b->value = (jl_value_t*)dt; - jl_gc_wb_binding(b,dt); + b->value = w; + jl_gc_wb_binding(b,w); JL_TRY { inside_typedef = 1; @@ -454,8 +454,8 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) } b->value = temp; - if (temp == NULL || !equiv_type(dt, (jl_datatype_t*)temp)) { - jl_checked_assignment(b, (jl_value_t*)dt); + if (temp == NULL || !equiv_type(dt, (jl_datatype_t*)jl_unwrap_unionall(temp))) { + jl_checked_assignment(b, w); } JL_GC_POP(); diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index ff1fc3ca02522..84b19ded8e5e1 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -751,7 +751,7 @@ static jl_cgval_t emit_pointerset(jl_value_t *e, jl_value_t *x, jl_value_t *i, j jl_value_t *xty = expr_type(x, ctx); jl_cgval_t val; bool emitted = false; - if (!jl_subtype(xty, ety, 0)) { + if (!jl_subtype(xty, ety)) { emitted = true; val = emit_expr(x, ctx); emit_typecheck(val, ety, "pointerset: type mismatch in assign", ctx); diff --git a/src/jltypes.c b/src/jltypes.c index 1f3ebf3d602f7..c0fb884d6bf8b 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -2,8 +2,7 @@ /* Types - . type predicates (subtype) and type matching - . type union and intersection + . type union, type cache, instantiation, and specificity . builtin type definitions */ #include @@ -21,7 +20,8 @@ extern "C" { #endif jl_datatype_t *jl_any_type; -jl_datatype_t *jl_type_type; +jl_unionall_t *jl_type_type; +jl_typename_t *jl_type_typename; jl_methtable_t *jl_type_type_mt; jl_datatype_t *jl_typename_type; jl_datatype_t *jl_sym_type; @@ -32,19 +32,22 @@ jl_datatype_t *jl_slotnumber_type; jl_datatype_t *jl_typedslot_type; jl_datatype_t *jl_simplevector_type; jl_typename_t *jl_tuple_typename; -jl_tupletype_t *jl_anytuple_type; -jl_datatype_t *jl_anytuple_type_type; +jl_datatype_t *jl_anytuple_type; +jl_unionall_t *jl_anytuple_type_type; jl_typename_t *jl_vecelement_typename; -jl_datatype_t *jl_vararg_type; +jl_unionall_t *jl_vararg_type; +jl_typename_t *jl_vararg_typename; jl_datatype_t *jl_tvar_type; jl_datatype_t *jl_uniontype_type; +jl_datatype_t *jl_unionall_type; jl_datatype_t *jl_datatype_type; jl_datatype_t *jl_function_type; jl_datatype_t *jl_builtin_type; +jl_datatype_t *jl_bottomtype_type; jl_value_t *jl_bottom_type; -jl_datatype_t *jl_abstractarray_type; -jl_datatype_t *jl_densearray_type; +jl_unionall_t *jl_abstractarray_type; +jl_unionall_t *jl_densearray_type; jl_datatype_t *jl_bool_type; jl_datatype_t *jl_char_type; @@ -61,7 +64,7 @@ jl_datatype_t *jl_float32_type; jl_datatype_t *jl_float64_type; jl_datatype_t *jl_floatingpoint_type; jl_datatype_t *jl_number_type; -jl_datatype_t *jl_complex_type; +jl_unionall_t *jl_complex_type; jl_datatype_t *jl_signed_type; JL_DLLEXPORT jl_value_t *jl_emptytuple=NULL; @@ -72,93 +75,92 @@ jl_cgparams_t jl_default_cgparams = {1, 1, 1, 1, 1, 1, 1, {NULL, NULL, NULL}}; // --- type properties and predicates --- -STATIC_INLINE int is_unspec(jl_datatype_t *dt) -{ - return (jl_datatype_t*)dt->name->primary == dt; -} +typedef struct _typeenv { + jl_tvar_t *var; + jl_value_t *val; + struct _typeenv *prev; +} jl_typeenv_t; -static int jl_has_typevars__(jl_value_t *v, int incl_wildcard, jl_value_t **p, size_t np) +static int typeenv_has(jl_typeenv_t *env, jl_tvar_t *v) { - size_t i; - if (jl_typeis(v, jl_tvar_type)) { - if (jl_has_typevars__(((jl_tvar_t*)v)->ub, incl_wildcard, p, np) || - jl_has_typevars__(((jl_tvar_t*)v)->lb, incl_wildcard, p, np)) + while (env != NULL) { + if (env->var == v) return 1; - if (p != NULL) { - for (i = 0; i < np; i++) { - if (v == p[i]) - return 1; - } - return 0; - } - if (!((jl_tvar_t*)v)->bound) - return incl_wildcard; - return 1; + env = env->prev; } - if (jl_is_typector(v)) - return incl_wildcard; - jl_svec_t *t; - int expect = -1; - if (jl_is_uniontype(v)) { - t = ((jl_uniontype_t*)v)->types; - } - else if (jl_is_datatype(v)) { - if (is_unspec((jl_datatype_t*)v)) - return 0; // TODO: fix expect in this case - if (p == NULL) { - if (incl_wildcard) - expect = ((jl_datatype_t*)v)->haswildcard; - else - expect = ((jl_datatype_t*)v)->hastypevars; -#ifdef NDEBUG - return expect; -#endif - } - t = ((jl_datatype_t*)v)->parameters; - } - else { - return 0; + return 0; +} + +static int has_free_typevars(jl_value_t *v, jl_typeenv_t *env) +{ + if (jl_typeis(v, jl_tvar_type)) + return !typeenv_has(env, (jl_tvar_t*)v); + if (jl_is_uniontype(v)) + return has_free_typevars(((jl_uniontype_t*)v)->a, env) || + has_free_typevars(((jl_uniontype_t*)v)->b, env); + if (jl_is_unionall(v)) { + jl_unionall_t *ua = (jl_unionall_t*)v; + jl_typeenv_t newenv = { ua->var, NULL, env }; + return has_free_typevars(ua->var->lb, env) || has_free_typevars(ua->var->ub, env) || + has_free_typevars(ua->body, &newenv); } - size_t l = jl_svec_len(t); - for (i = 0; i < l; i++) { - jl_value_t *elt = jl_svecref(t, i); - if (elt != v) { - if (jl_has_typevars__(elt, incl_wildcard, p, np)) { - if (expect >= 0) assert(expect); + if (jl_is_datatype(v)) { + int expect = ((jl_datatype_t*)v)->hasfreetypevars; + if (expect == 0) + return 0; + size_t i; + for (i=0; i < jl_nparams(v); i++) { + if (has_free_typevars(jl_tparam(v,i), env)) { + assert(expect); return 1; } } } - // probably not necessary; no reason to use match() instead of subtype() - // on the unconstrained version of a type - //if (jl_is_typector(v)) - // return jl_svec_len((((jl_typector_t*)v)->parameters) > 0); - if (expect >= 0) assert(!expect); return 0; } -JL_DLLEXPORT int jl_has_typevars_(jl_value_t *v, int incl_wildcard) +JL_DLLEXPORT int jl_has_free_typevars(jl_value_t *v) { - if (jl_is_typevar(v)) return 1; - return jl_has_typevars__(v, incl_wildcard, NULL, 0); + return has_free_typevars(v, NULL); } -static int jl_has_typevars_from(jl_value_t *v, jl_svec_t *p) +// test whether a type has vars bound by the given environment +JL_DLLEXPORT int jl_has_bound_typevars(jl_value_t *v, jl_typeenv_t *env) { - if (jl_svec_len(p) == 0) return 0; - return jl_has_typevars__(v, 0, jl_svec_data(p), jl_svec_len(p)); -} - -static int jl_has_typevars_from_v(jl_value_t *v, jl_value_t **p, size_t np) -{ - if (np == 0) return 0; - return jl_has_typevars__(v, 0, p, np); + if (jl_typeis(v, jl_tvar_type)) + return typeenv_has(env, (jl_tvar_t*)v); + if (jl_is_uniontype(v)) + return jl_has_bound_typevars(((jl_uniontype_t*)v)->a, env) || + jl_has_bound_typevars(((jl_uniontype_t*)v)->b, env); + if (jl_is_unionall(v)) { + jl_unionall_t *ua = (jl_unionall_t*)v; + if (jl_has_bound_typevars(ua->var->lb, env) || jl_has_bound_typevars(ua->var->ub, env)) + return 1; + jl_typeenv_t *te = env; + while (te != NULL) { + if (te->var == ua->var) + break; + te = te->prev; + } + if (te) te->var = NULL; // temporarily remove this var from env + int ans = jl_has_bound_typevars(ua->body, env); + if (te) te->var = ua->var; + return ans; + } + if (jl_is_datatype(v)) { + size_t i; + for (i=0; i < jl_nparams(v); i++) { + if (jl_has_bound_typevars(jl_tparam(v,i), env)) + return 1; + } + } + return 0; } -JL_DLLEXPORT int jl_has_typevars(jl_value_t *v) +JL_DLLEXPORT int jl_has_typevar(jl_value_t *t, jl_tvar_t *v) { - if (jl_is_typevar(v)) return 1; - return jl_has_typevars__(v, 0, NULL, 0); + jl_typeenv_t env = { v, NULL, NULL }; + return jl_has_bound_typevars(t, &env); } JL_DLLEXPORT int (jl_is_leaf_type)(jl_value_t *v) @@ -170,9 +172,8 @@ JL_DLLEXPORT int (jl_is_leaf_type)(jl_value_t *v) #else if (((jl_datatype_t*)v)->abstract) { int x = 0; - if (jl_is_type_type(v)) { - x = !jl_has_typevars(jl_tparam0(v)); - } + if (jl_is_type_type(v)) + x = !jl_has_free_typevars(jl_tparam0(v)); assert(x == isleaf); return x; } @@ -189,7 +190,7 @@ JL_DLLEXPORT int (jl_is_leaf_type)(jl_value_t *v) else { for(int i=0; i < l; i++) { jl_value_t *p = jl_svecref(t, i); - if (jl_has_typevars(p)) { + if (jl_has_free_typevars(p)) { assert(!isleaf); return 0; } @@ -202,8 +203,6 @@ JL_DLLEXPORT int (jl_is_leaf_type)(jl_value_t *v) return 0; } -static int type_eqv_(jl_value_t *a, jl_value_t *b); - // Return true for any type (Integer or Unsigned) that can fit in a // size_t and pass back value, else return false JL_DLLEXPORT int jl_get_size(jl_value_t *val, size_t *pnt) @@ -217,6 +216,7 @@ JL_DLLEXPORT int jl_get_size(jl_value_t *val, size_t *pnt) } return 0; } + // --- type union --- static int count_union_components(jl_value_t **types, size_t n) @@ -225,8 +225,9 @@ static int count_union_components(jl_value_t **types, size_t n) for(i=0; i < n; i++) { jl_value_t *e = types[i]; if (jl_is_uniontype(e)) { - jl_svec_t *ts = ((jl_uniontype_t*)e)->types; - c += count_union_components(jl_svec_data(ts), jl_svec_len(ts)); + jl_uniontype_t *u = (jl_uniontype_t*)e; + c += count_union_components(&u->a, 1); + c += count_union_components(&u->b, 1); } else { c++; @@ -241,8 +242,9 @@ static void flatten_type_union(jl_value_t **types, size_t n, jl_value_t **out, s for(i=0; i < n; i++) { jl_value_t *e = types[i]; if (jl_is_uniontype(e)) { - jl_svec_t *ts = ((jl_uniontype_t*)e)->types; - flatten_type_union(jl_svec_data(ts), jl_svec_len(ts), out, idx); + jl_uniontype_t *u = (jl_uniontype_t*)e; + flatten_type_union(&u->a, 1, out, idx); + flatten_type_union(&u->b, 1, out, idx); } else { out[*idx] = e; @@ -251,69 +253,8 @@ static void flatten_type_union(jl_value_t **types, size_t n, jl_value_t **out, s } } -static int union_elt_morespecific(const void *a, const void *b) -{ - jl_value_t *va = *(jl_value_t**)a; - jl_value_t *vb = *(jl_value_t**)b; - if (jl_args_morespecific(va, vb)) - return -1; - // impose a partially-arbitrary ordering on Union elements, to make it more - // likely that many Unions will be identical and can be merged. - // NOTE: we know !(a <: b) && !(b <: a), since otherwise one would have - // been eliminated from the Union. - return jl_object_id(va) < jl_object_id(vb) ? -1 : 1; -} - -// NOTE: this is a hack to avoid simplifying type unions too early inside -// type definitions. (issue #2365) -int inside_typedef = 0; - -static jl_svec_t *jl_compute_type_union(jl_value_t **types, size_t ntypes) -{ - size_t n = count_union_components(types, ntypes); - jl_value_t **temp; - JL_GC_PUSHARGS(temp, n+1); - size_t idx=0; - flatten_type_union(types, ntypes, temp, &idx); - assert(idx == n); - size_t i, j, ndel=0; - for(i=0; i < n; i++) { - for(j=0; j < n; j++) { - if (j != i && temp[i] && temp[j]) { - if (temp[i] == temp[j] || - (!jl_has_typevars(temp[i]) && !jl_has_typevars(temp[j]) && - !(inside_typedef && (jl_is_typevar(temp[i]) || - jl_is_typevar(temp[j]))) && - (type_eqv_(temp[i], temp[j]) || - jl_subtype(temp[i], temp[j], 0)))) { - temp[i] = NULL; - ndel++; - } - } - } - } - temp[n] = NULL; - jl_svec_t *result = jl_alloc_svec_uninit(n - ndel); - temp[n] = (jl_value_t*)result; // root result tuple while sorting - j=0; - for(i=0; i < n; i++) { - if (temp[i] != NULL) { - jl_svecset(result, j, temp[i]); - j++; - } - } - assert(j == n-ndel); - // sort Union components by specificity, so "complex" type Unions work as - // long as there are no ambiguities (see e.g. issue #126). - // TODO: maybe warn about ambiguities - qsort(jl_svec_data(result), j, sizeof(jl_value_t*), union_elt_morespecific); - JL_GC_POP(); - return result; -} - -static jl_value_t *jl_type_union_v(jl_value_t **ts, size_t n) +JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n) { - jl_ptls_t ptls = jl_get_ptls_states(); if (n == 0) return (jl_value_t*)jl_bottom_type; size_t i; for(i=0; i < n; i++) { @@ -322,1559 +263,49 @@ static jl_value_t *jl_type_union_v(jl_value_t **ts, size_t n) jl_type_error_rt("Union", "parameter", (jl_value_t*)jl_type_type, pi); } if (n == 1) return ts[0]; - jl_svec_t *types = jl_compute_type_union(ts, n); - if (jl_svec_len(types) == 0) return (jl_value_t*)jl_bottom_type; - if (jl_svec_len(types) == 1) return jl_svecref(types, 0); - JL_GC_PUSH1(&types); - jl_uniontype_t *tu = - (jl_uniontype_t*)jl_gc_alloc(ptls, sizeof(jl_uniontype_t), - jl_uniontype_type); - tu->types = types; - jl_gc_wb(tu, types); - JL_GC_POP(); - return (jl_value_t*)tu; -} - -JL_DLLEXPORT jl_value_t *jl_type_union(jl_svec_t *types) -{ - return jl_type_union_v(jl_svec_data(types), jl_svec_len(types)); -} - -// --- type intersection --- - -typedef enum {invariant, covariant} variance_t; - -#define MAX_CENV_SIZE 128 - -typedef struct { - jl_value_t **data; - size_t n; - jl_svec_t *tvars; -} cenv_t; - -STATIC_INLINE int is_bnd(jl_tvar_t *tv, cenv_t *env) -{ - if (env->tvars == jl_emptysvec) - return tv->bound; - if (jl_is_typevar(env->tvars)) - return (jl_tvar_t*)env->tvars == tv; - for(size_t i=0; i < jl_svec_len(env->tvars); i++) { - if ((jl_tvar_t*)jl_svecref(env->tvars,i) == tv) - return 1; - } - return 0; -} - -STATIC_INLINE int is_btv(jl_value_t *v) -{ - return jl_is_typevar(v) && ((jl_tvar_t*)v)->bound; -} - -static void extend_(jl_value_t *var, jl_value_t *val, cenv_t *soln, int allowself) -{ - if (!allowself && var == val) - return; - for(int i=0; i < soln->n; i+=2) { - if (soln->data[i]==var && - (soln->data[i+1]==val || (!jl_is_typevar(val) && - type_eqv_(soln->data[i+1],val)))) - return; - if (soln->data[i]==val && soln->data[i+1]==var) - return; - } - if (soln->n >= MAX_CENV_SIZE) - jl_error("type too large"); - soln->data[soln->n++] = var; - soln->data[soln->n++] = val; -} - -static void extend(jl_value_t *var, jl_value_t *val, cenv_t *soln) -{ - extend_(var, val, soln, 0); -} - -static jl_value_t *jl_type_intersect(jl_value_t *a, jl_value_t *b, - cenv_t *penv, cenv_t *eqc, - int *recheck_tuple_intersection, - variance_t var); - -static jl_value_t *intersect_union(jl_uniontype_t *a, jl_value_t *b, - cenv_t *penv, cenv_t *eqc, - int *recheck_tuple_intersection, - variance_t var) -{ - int eq0 = eqc->n, co0 = penv->n; - size_t i, l = jl_svec_len(a->types); - // shortcut an easy case: union contains type b - if (!jl_is_typevar(b)) { - for(i=0; i < l; i++) { - if (jl_svecref(a->types,i) == b) - return b; - } - } - jl_svec_t *t = jl_alloc_svec(l); - JL_GC_PUSH1(&t); - for(i=0; i < l; i++) { - int eq_l = eqc->n, co_l = penv->n; - jl_value_t *ti = jl_type_intersect(jl_svecref(a->types,i), b, - penv, eqc, recheck_tuple_intersection, var); - if (ti == (jl_value_t*)jl_bottom_type) { - eqc->n = eq0; penv->n = co0; - ti = jl_type_intersect(jl_svecref(a->types,i), b, - penv, eqc, recheck_tuple_intersection, var); - if (ti != (jl_value_t*)jl_bottom_type) { - // tvar conflict among union elements; keep the conflicting - // constraints rolled back - eqc->n = eq0; penv->n = co0; - } - else { - // union element doesn't overlap no matter what. - // so remove only its constraints. - eqc->n = eq_l; penv->n = co_l; - } - } - jl_svecset(t, i, ti); - } - // problem: an intermediate union type we make here might be too - // complex, even though the final type after typevars are replaced - // might be ok. - jl_value_t *tu = jl_type_union(t); - JL_GC_POP(); - return tu; -} - -/* -Simplification of varargs tuple types: - JL_TUPLE_FIXED: tuples of known length (e.g., JL_VARARG_NONE or JL_VARARG_INT) - JL_TUPLE_VAR: tuples of unknown length (e.g., JL_VARARG_BOUND or JL_VARARG_UNBOUND) - -In some cases, JL_VARARG_BOUND tuples get described as JL_TUPLE_FIXED, -if the constraints on length are already known. - -lenr = "representation length" (the number of parameters) -lenf = "full length" (including the Vararg length, if known) - -In general, lenf >= lenr-1. The lower bound is achieved only for a Vararg of length 0. -*/ -typedef enum { - JL_TUPLE_FIXED = 0, - JL_TUPLE_VAR = 1 -} jl_tuple_lenkind_t; - -// Set the parameters for a single tuple -// returns lenf, sets kind and lenkind -static size_t data_vararg_params(jl_value_t **data, size_t lenr, cenv_t *eqc, jl_vararg_kind_t *kind, jl_tuple_lenkind_t *lenkind) -{ - size_t lenf = lenr; - int i; - if (lenr == 0) { - *kind = JL_VARARG_NONE; - *lenkind = JL_TUPLE_FIXED; - return lenf; - } - *lenkind = JL_TUPLE_VAR; - *kind = jl_vararg_kind(data[lenr-1]); - if (*kind == JL_VARARG_NONE || *kind == JL_VARARG_INT) - *lenkind = JL_TUPLE_FIXED; - if (*kind == JL_VARARG_INT || *kind == JL_VARARG_BOUND) { - // try to set N from eqc parameters - jl_value_t *N = jl_tparam1(data[lenr-1]); - if (!jl_is_long(N) && eqc != NULL) { - for (i = 0; i < eqc->n; i+=2) - if (eqc->data[i] == N && jl_is_long(eqc->data[i+1])) { - N = eqc->data[i+1]; - break; - } - } - if (jl_is_long(N)) { - lenf += jl_unbox_long(N)-1; - *lenkind = JL_TUPLE_FIXED; - } - } - return lenf; -} - -static size_t tuple_vararg_params(jl_svec_t *a, cenv_t *eqc, jl_vararg_kind_t *kind, jl_tuple_lenkind_t *lenkind) -{ - return data_vararg_params(jl_svec_data(a), jl_svec_len(a), eqc, kind, lenkind); -} - -jl_datatype_t *jl_wrap_vararg(jl_value_t *t, jl_value_t *n) -{ - if (n == NULL) { - if (t == NULL) - return (jl_datatype_t*)jl_instantiate_type_with((jl_value_t*)jl_vararg_type, NULL, 0); - jl_value_t *env[2]; - env[0] = jl_tparam0(jl_vararg_type); - env[1] = t; - return (jl_datatype_t*)jl_instantiate_type_with((jl_value_t*)jl_vararg_type, env, 1); - } - jl_value_t *env[4]; - env[0] = jl_tparam0(jl_vararg_type); - env[1] = t; - env[2] = jl_tparam1(jl_vararg_type); - env[3] = n; - return (jl_datatype_t*)jl_instantiate_type_with((jl_value_t*)jl_vararg_type, env, 2); -} - -/* -Tuple intersection -Stage 1: compute lengths of each tuple --------------------------------------- -See above - -Stage 2: paired length analysis -------------------------------- -Check and combine lengths. In cells of the following table, -- row 1 is the criterion that must be satisfied, or Bottom will be returned -- row 2 is the allocated length for the output tuple -- row 3, if present, indicates any additional steps taken at the time - of length computation - - b - FIXED VAR - |---------------------------------------| - | alenf == blenf | alenf+1 >= blenr | - FIXED | alenf | alenf | - | | bind b? | -a |---------------------------------------| - | blenf+1 >= alenr | | - VAR | blenf | max(alenr,blenr) | - | bind a? | flag? | - |---------------------------------------| - -"bind" is performed if the VAR tuple is of state BOUND, using (for -the b BOUND case) N == alenf-blenr+1 for b's length parameter N. - -"flag" is set if at least one of the tuples is of state BOUND. With -this, we signify that the intersection of these tuples is going to -have to be repeated once all lengths are constrained. - -Stage 3: slot type intersection -------------------------------- -Iterate over each slot of the _output_ tuple, intersecting -corresponding pairs of types. Any intersection failure causes Bottom -to be returned, with one exception illustrated by: - typeintersect(Tuple{A, Vararg{B}}, Tuple{A, Vararg{C}}) == Tuple{A} -where typeintersect(B,C) == Bottom. -*/ - -static jl_value_t *intersect_tuple(jl_datatype_t *a, jl_datatype_t *b, - cenv_t *penv, cenv_t *eqc, - int *recheck_tuple_intersection, // "flag" above - variance_t var) -{ - jl_svec_t *ap = a->parameters, *bp = b->parameters; - size_t alenr = jl_svec_len(ap), blenr = jl_svec_len(bp); - size_t alenf, blenf; - jl_vararg_kind_t akind, bkind; - jl_tuple_lenkind_t alenkind, blenkind; - int bottom = 0; - size_t n; - // Stage 1 - alenf = tuple_vararg_params(ap, eqc, &akind, &alenkind); - blenf = tuple_vararg_params(bp, eqc, &bkind, &blenkind); - // Stage 2 - if (alenkind == JL_TUPLE_FIXED && blenkind == JL_TUPLE_FIXED) { - bottom = alenf != blenf; - n = alenf; - } - else if (alenkind == JL_TUPLE_FIXED && blenkind == JL_TUPLE_VAR) { - bottom = alenf+1 < blenf; - n = alenf; - if (bkind == JL_VARARG_BOUND) - extend(jl_tparam1(jl_svecref(bp, blenr-1)), jl_box_long(alenf-blenr+1), eqc); - } - else if (alenkind == JL_TUPLE_VAR && blenkind == JL_TUPLE_FIXED) { - bottom = blenf+1 < alenf; - n = blenf; - if (akind == JL_VARARG_BOUND) - extend(jl_tparam1(jl_svecref(ap, alenr-1)), jl_box_long(blenf-alenr+1), eqc); - } - else { - n = alenr > blenr ? alenr : blenr; - // Do we need to store "at least N" constraints in penv? - // Formerly, typeintersect(Tuple{A,Vararg{B}}, NTuple{N,C}) did that - if (akind == JL_VARARG_BOUND || bkind == JL_VARARG_BOUND) - *recheck_tuple_intersection = 1; - } - if (bottom) return (jl_value_t*) jl_bottom_type; - if (n == 0) return jl_typeof(jl_emptytuple); - jl_svec_t *tc = jl_alloc_svec(n); - jl_value_t *result = (jl_value_t*)tc; - jl_value_t *ce = NULL; - JL_GC_PUSH2(&tc, &ce); - size_t ai=0, bi=0, ci; - jl_value_t *ae=NULL, *be=NULL, *an=NULL, *bn=NULL; - int aseq=0, bseq=0; - // Stage 3 - for(ci=0; ci < n; ci++) { - if (ai < alenr) { - ae = jl_svecref(ap,ai); - if (jl_is_vararg_type(ae)) { - if (alenkind != JL_TUPLE_FIXED) { - an = jl_tparam1(ae); - aseq = 1; - } - ae = jl_tparam0(ae); - } - ai++; - } - if (bi < blenr) { - be = jl_svecref(bp,bi); - if (jl_is_vararg_type(be)) { - if (blenkind != JL_TUPLE_FIXED) { - bn = jl_tparam1(be); - bseq=1; - } - be = jl_tparam0(be); - } - bi++; - } - assert(ae!=NULL && be!=NULL); - ce = jl_type_intersect(ae, be, penv, eqc, recheck_tuple_intersection, var); - if (ce == (jl_value_t*)jl_bottom_type) { - if (var!=invariant && aseq && bseq) { - // (X∩Y)==∅ → (X...)∩(Y...) == () - // We don't need to set bindings here because - // *recheck_tuple_intersection = 1 - if (n == 1) { - JL_GC_POP(); - return (jl_value_t*)jl_typeof(jl_emptytuple); - } - jl_svec_set_len_unsafe(tc, jl_svec_len(tc) - 1); - goto done_intersect_tuple; - } - JL_GC_POP(); - return (jl_value_t*)jl_bottom_type; - } - if (aseq && bseq) - ce = (jl_value_t*)jl_wrap_vararg(ce, akind==JL_VARARG_BOUND ? bn : an); - jl_svecset(tc, ci, ce); - } - done_intersect_tuple: - result = (jl_value_t*)jl_apply_tuple_type(tc); - JL_GC_POP(); - return result; -} -static jl_value_t *intersect_tag(jl_datatype_t *a, jl_datatype_t *b, - cenv_t *penv, cenv_t *eqc, - int *recheck_tuple_intersection, - variance_t var) -{ - assert(a->name == b->name); - assert(jl_svec_len(a->parameters) == jl_svec_len(b->parameters)); - jl_svec_t *p = jl_alloc_svec(jl_svec_len(a->parameters)); - JL_GC_PUSH1(&p); - jl_value_t *ti; - size_t i; - for(i=0; i < jl_svec_len(p); i++) { - jl_value_t *ap = jl_svecref(a->parameters,i); - jl_value_t *bp = jl_svecref(b->parameters,i); - if (jl_is_typevar(ap)) { - if (var==invariant && jl_is_typevar(bp)) { - if (((jl_tvar_t*)ap)->bound != ((jl_tvar_t*)bp)->bound) { - JL_GC_POP(); - return (jl_value_t*)jl_bottom_type; - } - if ((is_unspec(a) && is_bnd((jl_tvar_t*)bp,penv)) || - (is_bnd((jl_tvar_t*)ap,penv) && is_unspec(b))) { - // Foo{T} and Foo can never be equal since the former - // is always a subtype of the latter - JL_GC_POP(); - return (jl_value_t*)jl_bottom_type; - } - } - ti = jl_type_intersect(ap, bp, penv, eqc, recheck_tuple_intersection, invariant); - if (bp == (jl_value_t*)jl_bottom_type && - !((jl_tvar_t*)ap)->bound) { - // "Union{}" as a type parameter - jl_svecset(p, i, ti); - continue; - } - } - else if (jl_is_typevar(bp)) { - ti = jl_type_intersect(ap, bp, penv, eqc, recheck_tuple_intersection, invariant); - if (ap == (jl_value_t*)jl_bottom_type && - !((jl_tvar_t*)bp)->bound) { - // "Union{}" as a type parameter - jl_svecset(p, i, ti); - continue; - } - } - else { - int tva = jl_has_typevars_(ap,0); - int tvb = jl_has_typevars_(bp,0); - if (tva || tvb) { - if (jl_subtype_invariant(ap,bp,0) || - jl_subtype_invariant(bp,ap,0)) { - ti = jl_type_intersect(ap, bp, penv, eqc, recheck_tuple_intersection, invariant); - } - else { - ti = (jl_value_t*)jl_bottom_type; - } - } - else if (type_eqv_(ap,bp)) { - ti = ap; - if (ti == (jl_value_t*)jl_bottom_type) { - // "Union{}" as a type parameter - jl_svecset(p, i, ti); - continue; + size_t nt = count_union_components(ts, n); + jl_value_t **temp; + JL_GC_PUSHARGS(temp, nt+1); + size_t count = 0; + flatten_type_union(ts, n, temp, &count); + assert(count == nt); + size_t j; + for(i=0; i < nt; i++) { + int has_free = temp[i]!=NULL && jl_has_free_typevars(temp[i]); + for(j=0; j < nt; j++) { + if (j != i && temp[i] && temp[j]) { + if (temp[i] == temp[j] || + (!has_free && !jl_has_free_typevars(temp[j]) && + jl_subtype(temp[i], temp[j]))) { + temp[i] = NULL; } } - else { - ti = (jl_value_t*)jl_bottom_type; - } - } - if (ti == (jl_value_t*)jl_bottom_type) { - JL_GC_POP(); - return (jl_value_t*)jl_bottom_type; - } - jl_svecset(p, i, ti); - } - if (a->name->primary != NULL) { - jl_value_t *res = (jl_value_t*)jl_apply_type(a->name->primary, p); - JL_GC_POP(); - return res; - } - assert(0 && "not yet implemented"); - return NULL; -} - -static long meet_tuple_lengths(long bv, long vv, int *bot) -{ - /* - do a meet over the lattice of tuple lengths: - >=0 - | \ - | 0 - >=1 - | \ - | 1 - >=2 - | \ - | 2 - ... - ">=N" is represented as ~N - */ - if (bv < 0) { - if (vv < 0) { - if (bv < vv) - return bv; - else - return vv; - } - else { - if (~bv > vv) { - *bot = 1; - return 0; - } - } - } - else { - if (vv < 0) { - if (~vv > bv) { - *bot = 1; - return 0; - } - return bv; - } - else { - if (bv != vv) { - *bot = 1; - return 0; - } - } - } - return vv; -} - -static int match_intersection_mode = 0; -static jl_value_t *meet_tvars(jl_tvar_t *a, jl_tvar_t *b); - -static jl_value_t *intersect_typevar(jl_tvar_t *a, jl_value_t *b, - cenv_t *penv, cenv_t *eqc, - int *recheck_tuple_intersection, - variance_t var) -{ - jl_value_t *both=NULL; - jl_tvar_t *new_b=NULL; - JL_GC_PUSH3(&b, &both, &new_b); - if (jl_subtype(b, (jl_value_t*)a, 0)) { - if (!is_bnd(a,penv)) { - JL_GC_POP(); - return b; - } - } - else if (var==invariant && !jl_has_typevars_(b,0)) { - // for typevar a and non-typevar type b, b must be within a's bounds - // in invariant contexts. - JL_GC_POP(); - return (jl_value_t*)jl_bottom_type; - } - else if (jl_subtype((jl_value_t*)a, b, 0)) { - /* - TODO: get sharper types when the overlap between a typevar and - a type is not simple. Ex: - tintersect(Type{Array{T,n}}, Type{typevar(:_,Vector)}) - should give Type{_<:Vector} - */ - if (jl_is_typevar(b)) { - if (!is_bnd((jl_tvar_t*)b,penv)) { - JL_GC_POP(); - return (jl_value_t*)a; - } - } - else { - if (a->ub == jl_bottom_type) { - JL_GC_POP(); - return jl_bottom_type; - } - if (!is_bnd(a,penv)) { - JL_GC_POP(); - return (jl_value_t*)a; - } - } - } - else { - b = jl_type_intersect(a->ub, b, penv, eqc, recheck_tuple_intersection, covariant); - if (b == jl_bottom_type) { - JL_GC_POP(); - return b; - } - } - if ((jl_value_t*)a == b) { - JL_GC_POP(); - return b; - } - if (var == invariant) { - if (!jl_has_typevars_(b,0) && !jl_is_typevar(b)) { - int i; - for(i=0; i < eqc->n; i+=2) { - if (eqc->data[i] == (jl_value_t*)a) { - jl_value_t *v = eqc->data[i+1]; - if (jl_is_typevar(v)) - continue; - if (!jl_types_equal(v, b)) { - JL_GC_POP(); - return (jl_value_t*)jl_bottom_type; - } - break; - } - } - if (i >= eqc->n) - extend((jl_value_t*)a, b, eqc); - JL_GC_POP(); - return (jl_value_t*)a; - } - if (jl_is_typevar(b)) { - both = meet_tvars(a, (jl_tvar_t*)b); - if (both == jl_bottom_type) { - JL_GC_POP(); - return both; - } - if (!jl_is_typevar(both)) - both = (jl_value_t*)jl_new_typevar(underscore_sym, jl_bottom_type, both); - extend((jl_value_t*)a, both, penv); - extend((jl_value_t*)b, both, penv); - } - if (is_btv(b)) - extend(b, (jl_value_t*)a, eqc); - else - extend((jl_value_t*)a, b, eqc); - } - else { - int i; - for(i=0; i < penv->n; i+=2) { - if (penv->data[i] == (jl_value_t*)a && !jl_is_typevar(penv->data[i+1])) { - if (jl_types_equal(b, penv->data[i+1])) { - JL_GC_POP(); - return (jl_value_t*)a; - } - break; - } - } - if (jl_is_typevar(b)) { - for(i=0; i < penv->n; i+=2) { - if (penv->data[i] == b && !jl_is_typevar(penv->data[i+1])) { - jl_value_t *ti = jl_type_intersection((jl_value_t*)a, penv->data[i+1]); - if (ti == (jl_value_t*)jl_bottom_type) { - JL_GC_POP(); - return ti; - } - break; - } - } - for(i=0; i < eqc->n; i+=2) { - if (eqc->data[i] == b && !jl_is_typevar(eqc->data[i+1])) { - jl_value_t *ti = jl_type_intersection((jl_value_t*)a, eqc->data[i+1]); - if (ti == (jl_value_t*)jl_bottom_type) { - JL_GC_POP(); - return ti; - } - break; - } - } - } - extend((jl_value_t*)a, b, penv); - if (jl_is_typevar(b)) { - JL_GC_POP(); - return (jl_value_t*)a; - } - else { - new_b = jl_new_typevar(underscore_sym, jl_bottom_type, b); - extend((jl_value_t*)new_b, b, penv); - extend((jl_value_t*)new_b, (jl_value_t*)a, penv); - JL_GC_POP(); - return (jl_value_t*)new_b; - } - } - JL_GC_POP(); - return (jl_value_t*)a; -} - -static jl_value_t *approxify_type(jl_datatype_t *dt, jl_svec_t *pp, int *recheck_tuple_intersection) -{ - size_t i, l = jl_svec_len(dt->parameters); - jl_svec_t *p = jl_alloc_svec(l); - JL_GC_PUSH1(&p); - for(i=0; i < l; i++) { - jl_value_t *el = jl_svecref(dt->parameters, i); - if (jl_has_typevars_from(el, pp)) - jl_svecset(p, i, jl_new_typevar(underscore_sym, jl_bottom_type, el)); - else - jl_svecset(p, i, el); - } - jl_value_t *nt = jl_apply_type(dt->name->primary, p); - JL_GC_POP(); - return nt; -} - -static jl_value_t *jl_type_intersect(jl_value_t *a, jl_value_t *b, - cenv_t *penv, cenv_t *eqc, - int *recheck_tuple_intersection, - variance_t var) -{ - if (jl_is_typector(a)) - a = (jl_value_t*)((jl_typector_t*)a)->body; - if (jl_is_typector(b)) - b = (jl_value_t*)((jl_typector_t*)b)->body; - if (a == b) return a; - if (jl_is_typevar(a)) { - if (var == covariant && !((jl_tvar_t*)a)->bound) - a = ((jl_tvar_t*)a)->ub; - else if (a != jl_ANY_flag) - return intersect_typevar((jl_tvar_t*)a, b, penv, eqc, recheck_tuple_intersection, var); - } - if (jl_is_typevar(b)) { - if (var == covariant && !((jl_tvar_t*)b)->bound) - b = ((jl_tvar_t*)b)->ub; - else if (b != jl_ANY_flag) - return intersect_typevar((jl_tvar_t*)b, a, penv, eqc, recheck_tuple_intersection, var); - } - if (a == (jl_value_t*)jl_bottom_type || b == (jl_value_t*)jl_bottom_type) - return (jl_value_t*)jl_bottom_type; - if (!jl_has_typevars(a) && !jl_has_typevars(b)) { - if (jl_subtype(a, b, 0)) - return a; - if (jl_subtype(b, a, 0)) - return b; - } - // union - if (jl_is_uniontype(a)) - return intersect_union((jl_uniontype_t*)a, b, penv, eqc, recheck_tuple_intersection, var); - if (jl_is_uniontype(b)) - return intersect_union((jl_uniontype_t*)b, a, penv, eqc, recheck_tuple_intersection, var); - if (a == (jl_value_t*)jl_any_type || a == jl_ANY_flag) return b; - if (b == (jl_value_t*)jl_any_type || b == jl_ANY_flag) return a; - // tuple - if (jl_is_tuple_type(a)) { - if (jl_is_tuple_type(b)) { - return intersect_tuple((jl_datatype_t*)a, (jl_datatype_t*)b, penv, eqc, recheck_tuple_intersection, var); - } - } - if (jl_is_tuple_type(b)) { - return jl_type_intersect(b, a, penv, eqc, recheck_tuple_intersection, var); - } - // tag - if (!jl_is_datatype(a) || !jl_is_datatype(b)) - return (jl_value_t*)jl_bottom_type; - jl_datatype_t *tta = (jl_datatype_t*)a; - jl_datatype_t *ttb = (jl_datatype_t*)b; - if (tta->name == ttb->name) - return (jl_value_t*)intersect_tag(tta, ttb, penv, eqc, recheck_tuple_intersection, var); - jl_datatype_t *super = NULL; - jl_datatype_t *sub = NULL; - jl_value_t *env = NULL; - jl_value_t *p = NULL; - jl_value_t *temp3 = NULL; - JL_GC_PUSH5(&super, &sub, &env, &p, &temp3); - while (tta != jl_any_type) { - if (tta->name == ttb->name) { - sub = (jl_datatype_t*)a; - super = (jl_datatype_t*)b; - break; - } - tta = tta->super; - } - if (sub == NULL) { - tta = (jl_datatype_t*)a; - while (ttb != jl_any_type) { - if (tta->name == ttb->name) { - sub = (jl_datatype_t*)b; - super = (jl_datatype_t*)a; - break; - } - ttb = ttb->super; - } - if (sub == NULL) { - JL_GC_POP(); - return (jl_value_t*)jl_bottom_type; - } - } - - if (sub->super == jl_type_type && jl_is_type_type((jl_value_t*)super)) { - // subtypes of Type like DataType do not constrain the type - // parameter, and yet contain Type instances with a more specific - // parameter (like Type{Int}). This is a special case. - jl_value_t *tp0 = jl_tparam0(super); - if (jl_is_typevar(tp0) || (jl_value_t*)sub == jl_typeof(tp0)) { - JL_GC_POP(); - return (jl_value_t*)super; - } - JL_GC_POP(); - return (jl_value_t*)jl_bottom_type; - } - - /* - issue #6387 - Say we have - - type DateRange{C} <: Range{Date{C}}; end - - and - - vcat{T}(r::Range{T}) = ... - - Then inferring vcat(::DateRange) concludes that T==Date{C}, but it should - conclude T<:Date{C}. The core problem seems to be that in moving from a - type to its supertype, we drop the environment that binds C --- we - forget that C is a variable in Range{Date{C}}. For now I work around this - by rewriting this type to Range{_<:Date{C}}, effectively tagging type - parameters that are variable due to the extra (dropped) environment. - */ - if (var == covariant && - sub == (jl_datatype_t*)sub->name->primary && - jl_has_typevars_from((jl_value_t*)sub->super, ((jl_datatype_t*)sub->name->primary)->parameters)) - env = approxify_type((jl_datatype_t*)sub->super, ((jl_datatype_t*)sub->name->primary)->parameters, recheck_tuple_intersection); - else - env = (jl_value_t*)sub->super; - super = (jl_datatype_t*)jl_type_intersect((jl_value_t*)env, (jl_value_t*)super, penv, eqc, recheck_tuple_intersection, var); - - if ((jl_value_t*)super == jl_bottom_type) { - JL_GC_POP(); - return (jl_value_t*)jl_bottom_type; - } - - // super needs to be instantiated so the matching below finds actual types - // and doesn't fail due to the presence of extra typevars. - super = (jl_datatype_t*)jl_instantiate_type_with((jl_value_t*)super, eqc->data, eqc->n/2); - - size_t n = jl_svec_len(sub->parameters); - - assert(sub->name->primary != NULL); - jl_value_t *tc = sub->name->primary; - jl_svec_t *tc_params = ((jl_datatype_t*)tc)->parameters; - // compute what constraints the supertype imposes on the subtype - jl_svec_t *subs_sup_params = - ((jl_datatype_t*)((jl_datatype_t*)tc)->super)->parameters; - // match the intersected supertype against the pattern this subtype - // uses to instantiate its supertype. this tells us what subtype parameter - // values are implied by the intersected supertype, or that the - // intersected supertype cannot come from this subtype (in which case - // our final answer is Union{}). - size_t i; - // hack: we need type_match to find assignments for all typevars - int prev_mim = match_intersection_mode; - match_intersection_mode = 1; - // TODO get rid of these intermediate tuple types - p = (jl_value_t*)jl_apply_tuple_type(super->parameters); - temp3 = (jl_value_t*)jl_apply_tuple_type(subs_sup_params); - env = jl_type_match(p, temp3); - int sub_needs_parameters = 0; - if (env == jl_false) { - env = jl_type_match(temp3, p); - } - else { - // this means it needs to be possible to instantiate the subtype - // such that the supertype gets the matching parameters we just - // determined. - sub_needs_parameters = 1; - } - match_intersection_mode = prev_mim; - if (env == jl_false) { - JL_GC_POP(); - return (jl_value_t*)jl_bottom_type; - } - if (sub_needs_parameters) { - for(int e=0; e < jl_svec_len(env); e+=2) { - jl_value_t *tp = jl_svecref(env, e); - // make sure each needed parameter is actually set by the subtype - size_t j; - for(j=0; j < n; j++) { - if (tp == jl_svecref(tc_params, j)) - break; - } - if (j >= n) { - JL_GC_POP(); - return (jl_value_t*)jl_bottom_type; - } - } - } - - p = (jl_value_t*)jl_alloc_svec(n); - for(i=0; i < n; i++) { - jl_value_t *tp = jl_svecref(tc_params, i); - jl_value_t *elt = jl_svecref(sub->parameters, i); - for(int e=0; e < jl_svec_len(env); e+=2) { - if (jl_svecref(env, e) == tp) { - elt = jl_type_intersect(elt, jl_svecref(env, e+1), - penv, eqc, recheck_tuple_intersection, invariant); - // note: elt might be Union{} if "Union{}" was the type parameter - break; - } - } - jl_svecset(p, i, elt); - } - jl_value_t *result = (jl_value_t*)jl_apply_type(tc, (jl_svec_t*)p); - JL_GC_POP(); - return result; -} - -JL_DLLEXPORT jl_value_t *jl_type_intersection(jl_value_t *a, jl_value_t *b) -{ - jl_svec_t *env = jl_emptysvec; - JL_GC_PUSH1(&env); - jl_value_t *ti = jl_type_intersection_matching(a, b, &env, jl_emptysvec); - JL_GC_POP(); - return ti; -} - -JL_DLLEXPORT jl_svec_t *jl_type_intersection_env(jl_value_t *a, jl_value_t *b, jl_svec_t *tvars) -{ - jl_svec_t *env = jl_emptysvec; - JL_GC_PUSH1(&env); - jl_value_t *ti = jl_type_intersection_matching(a, b, &env, tvars); - jl_svec_t *pair = jl_svec2(ti, env); - JL_GC_POP(); - return pair; -} - -/* - constraint satisfaction algorithm: - - keep lists of equality constraints and subtype constraints - (invariant and covariant) - - all constraints between two typevars are equality, i.e. it means the - two corresponding typevars must end up with the same value. however - they are kept in the subtype constraint list because they are not part - of the final answer yet. - - after computing the intersection, we try to solve the typevar constraints - - for each equality constraint T=S, add T=S to the results - - for each other constraint T=S, do - if T=U is in the results - if S is a typevar - if S=R is in the results - update R to meet(lookup(R),lookup(U)) - else - add S=meet(S,lookup(U)) - end - update U to S - else - update U to meet(lookup(U),S) - end - else - if S has typevars - add T=S - else - add T=_<:S - end - end - - meet(X,Y) = - if X and Y both have no typevars and not equal, fail - if X has no typevars and X<:Y, return X, else fail - if Y has no typevars and Y<:X, return Y, else fail - if one or both is typevar, return meet_typevar(X,Y) - else return intersect(X,Y) - - update X to Y = - if X is a typevar, trace to its class root and put Y there - else put Y where X was - - lookup(X) = - if X is a typevar and X=Y is in the results, return lookup(Y) - else return X -*/ - -static jl_value_t **tvar_lookup(cenv_t *env, jl_value_t **pX) -{ - jl_value_t *v = *pX; - if (is_btv(v)) { - for(int i=0; i < env->n; i+=2) { - if (env->data[i] == v) { - if (env->data[i+1] == v) // allow T=T - return pX; - return tvar_lookup(env, &env->data[i+1]); - } - } - } - return pX; -} - -static jl_value_t *meet_tvars(jl_tvar_t *a, jl_tvar_t *b) -{ - jl_value_t *lb=NULL, *ub=NULL; - if (type_eqv_((jl_value_t*)a->lb, (jl_value_t*)b->lb) && - type_eqv_((jl_value_t*)a->ub, (jl_value_t*)b->ub)) - return (jl_value_t*)b; - ub = jl_type_intersection((jl_value_t*)a->ub, (jl_value_t*)b->ub); - if (ub == (jl_value_t*)jl_bottom_type) - return ub; - JL_GC_PUSH2(&lb, &ub); - lb = (jl_value_t*)jl_svec2(a->lb, b->lb); - lb = jl_type_union((jl_svec_t*)lb); - if (!jl_subtype(lb, ub, 0)) { - JL_GC_POP(); - return (jl_value_t*)jl_bottom_type; - } - // TODO: might not want to collapse tvar to non-tvar in all cases - if (jl_is_leaf_type(ub)) { - JL_GC_POP(); - return ub; - } - jl_value_t *res = (jl_value_t*)jl_new_typevar(underscore_sym, lb, ub); - ((jl_tvar_t*)res)->bound = a->bound & b->bound; - JL_GC_POP(); - return res; -} - -static jl_value_t *meet_tvar(jl_tvar_t *tv, jl_value_t *ty) -{ - if (jl_is_typevar(ty)) - return (jl_value_t*)meet_tvars(tv, (jl_tvar_t*)ty); - //if (jl_types_equal((jl_value_t*)tv->ub, ty)) - // return ty; - if (jl_subtype((jl_value_t*)tv->ub, ty, 0)) - return (jl_value_t*)tv; - // TODO: should we check type_intersection(tv->ub, ty) instead? - if (!jl_subtype(ty, (jl_value_t*)tv->ub, 0)) - return (jl_value_t*)jl_bottom_type; - //if (jl_types_equal((jl_value_t*)tv->lb, ty)) - // return ty; - if (jl_subtype((jl_value_t*)tv->lb, ty, 0)) { - if (jl_is_leaf_type(ty) || !jl_is_type(ty)) - return ty; - jl_tvar_t *ntv = jl_new_typevar(underscore_sym, tv->lb, ty); - // TODO: this would be nice but causes some spurious ambiguity warnings - // due to typevars in covariant position, which we should simplify out somewhere. - //ntv->bound = tv->bound; - return (jl_value_t*)ntv; - } - return (jl_value_t*)jl_bottom_type; -} - -static jl_value_t *meet(jl_value_t *X, jl_value_t *Y, variance_t var) -{ - if (jl_is_typevar(X)) { - jl_value_t *tv; - if (jl_is_typevar(Y)) { - tv = meet_tvars((jl_tvar_t*)X, (jl_tvar_t*)Y); - } - else { - tv = meet_tvar((jl_tvar_t*)X, Y); - } - if (tv == (jl_value_t*)jl_bottom_type) - return NULL; - return tv; - } - if (jl_is_typevar(Y)) { - jl_value_t *tv = meet_tvar((jl_tvar_t*)Y, X); - if (tv == (jl_value_t*)jl_bottom_type) - return NULL; - return tv; - } - if (jl_subtype(X,Y,0)) return X; - if (jl_subtype(Y,X,0)) return Y; - jl_value_t *v = jl_type_intersection(X, Y); - return (v == (jl_value_t*)jl_bottom_type ? NULL : v); -} - -// convert a type to the value it would have if assigned to a static parameter -// in covariant context. -// example: {Type{Int},} => {DataType,} -// calling f{T}(x::T) as f({Int,}) should give T == {DataType,}, but we -// might temporarily represent this type as {Type{Int},} for more precision. -static jl_value_t *type_to_static_parameter_value(jl_value_t *t, jl_value_t *tv, jl_value_t **tvs, int ntv) -{ - int i; - for(i=0; i < ntv; i++) { - if (tv == tvs[i]) - break; - } - if (i >= ntv) - return t; // don't widen vars not in env - if (jl_is_type_type(t) && !jl_is_typevar(jl_tparam0(t))) - return jl_typeof(jl_tparam0(t)); - if (jl_is_tuple_type(t)) { - jl_svec_t *p = ((jl_datatype_t*)t)->parameters; - size_t l = jl_svec_len(p); - int changed = 0; - jl_svec_t *np = jl_alloc_svec(l); - JL_GC_PUSH1(&np); - for(size_t i=0; i < l; i++) { - jl_value_t *el = type_to_static_parameter_value(jl_svecref(p,i), NULL, NULL, 0); - jl_svecset(np, i, el); - if (el != jl_svecref(p,i)) - changed = 1; - } - jl_value_t *result = changed ? (jl_value_t*)jl_apply_tuple_type(np) : t; - JL_GC_POP(); - return result; - } - return t; -} - -/* -void print_env(cenv_t *soln) -{ - for(int i=0; i < soln->n; i+=2) { - jl_value_t *T, *S; - T = soln->data[i]; S = soln->data[i+1]; - jl_printf(JL_STDOUT, "%s@%x=", jl_symbol_name(((jl_tvar_t*)T)->name), T); - jl_static_show(JL_STDOUT, S); - jl_printf(JL_STDOUT, " "); - } - jl_printf(JL_STDOUT, "\n"); -} -*/ - -static int solve_tvar_constraints(cenv_t *env, cenv_t *soln, jl_value_t **tvs, int ntv) -{ - jl_value_t *rt1=NULL, *rt2=NULL, *S=NULL; - JL_GC_PUSH3(&rt1, &rt2, &S); - - while (1) { - int old_n = soln->n; - - // 1. replace each T=S with T=find(S) - for(int i=0; i < soln->n; i+=2) { - jl_value_t **pS = &soln->data[i+1]; - if (jl_is_typevar(*pS)) - *pS = *tvar_lookup(soln, pS); - if (!jl_is_typevar(*pS)) { - // detect cycles - if (jl_has_typevars_from_v(*pS, &soln->data[i], 1)) - goto ret_no; - } - } - - // 2. instantiate all RHSes using soln - if (soln->n > 0) { - for(int i=0; i < env->n; i+=2) { - jl_value_t **pS = &env->data[i+1]; - JL_TRY { - *pS = jl_instantiate_type_with(*pS, &soln->data[0], soln->n/2); - } - JL_CATCH { - } - } - } - - // 3. given T, let S´ = intersect(all S s.t. (T=S) or (S=T) ∈ env). add (T=S´) to soln. - for(int i=0; i < env->n; i+=2) { - jl_value_t *T = env->data[i]; - jl_value_t **pS = &env->data[i+1]; - S = *pS; - if (!jl_is_typevar(S)) { - for(int j=i+2; j < env->n; j+=2) { - jl_value_t *TT = env->data[j]; - jl_value_t *SS = env->data[j+1]; - if (TT == T) { - // found T=SS in env - if (!jl_is_typevar(SS)) { - rt1 = type_to_static_parameter_value(S, T, tvs, ntv); - rt2 = type_to_static_parameter_value(SS, TT, tvs, ntv); - jl_value_t *m = meet(rt1, rt2, covariant); - if (m == NULL) goto ret_no; - S = m; - } - } - else if (SS == T) { - // found TT=T in env; meet with TT - jl_value_t **pTT = tvar_lookup(soln, &TT); - if (pTT != &TT) { - jl_value_t *m = meet(S, *pTT, covariant); - if (m == NULL) goto ret_no; - S = m; - } - } - } - - if (!(jl_is_leaf_type(S) || S == (jl_value_t*)jl_bottom_type)) { - goto next_in_env; - } - - jl_value_t **pT = tvar_lookup(soln, &T); - if (pT != &T) { - size_t lenS, lenT; - if (jl_get_size(S, &lenS) && jl_get_size(*pT, &lenT)) { - int bot = 0; - long mv = meet_tuple_lengths(~lenS, lenT, &bot); - if (bot) - goto ret_no; - // NOTE: this is unused. can we do anything with it? - (void)mv; - //S = jl_box_long(mv); - } - else { - if (meet(*pT,S,covariant) == NULL) - goto ret_no; - } - } - else { - extend(T, type_to_static_parameter_value(S, T, tvs, ntv), soln); - } - } - else { - jl_value_t **pT = tvar_lookup(soln, &T); - if (pT != &T) { - if (tvar_lookup(soln, &S) == &S) { - jl_value_t *v = meet(S, *pT, covariant); - if (v == NULL) goto ret_no; - extend(S, v, soln); - *pT = S; - } - } - } - next_in_env: - ; - } - if (soln->n == old_n) - break; - } - - for(int i=0; i < env->n; i+=2) { - jl_value_t *T = env->data[i]; - jl_value_t **pS = &env->data[i+1]; - S = *pS; - if (tvar_lookup(soln, &T) == &T) { - for(int j=i+2; j < env->n; j+=2) { - jl_value_t *TT = env->data[j]; - jl_value_t *SS = env->data[j+1]; - if (TT == T) { - rt1 = type_to_static_parameter_value(S, T, tvs, ntv); - rt2 = type_to_static_parameter_value(SS, TT, tvs, ntv); - jl_value_t *m = meet(rt1, rt2, covariant); - if (m == NULL) goto ret_no; - S = m; - } - else if (SS == T) { - jl_value_t *m = meet(S, *tvar_lookup(soln, &TT), covariant); - if (m == NULL) goto ret_no; - S = m; - } - } - if (jl_is_type(S) || jl_is_typevar(S)) { - if (!jl_is_typevar(S) && !jl_is_leaf_type(S) && S != jl_bottom_type) { - S = (jl_value_t*)jl_new_typevar(underscore_sym, - (jl_value_t*)jl_bottom_type, S); - } - extend(T, type_to_static_parameter_value(S, T, tvs, ntv), soln); - } - } - } - - JL_GC_POP(); - return 1; - ret_no: - JL_GC_POP(); - return 0; -} - -jl_value_t *jl_type_intersection_matching(jl_value_t *a, jl_value_t *b, - jl_svec_t **penv, jl_svec_t *tvars) -{ - jl_value_t **rts; - JL_GC_PUSHARGS(rts, 2 + 2*MAX_CENV_SIZE); - cenv_t eqc; eqc.n = 0; eqc.data = &rts[2]; - cenv_t env; env.n = 0; env.data = &rts[2+MAX_CENV_SIZE]; - eqc.tvars = tvars; env.tvars = tvars; - jl_value_t **pti = &rts[0]; - jl_value_t **extraroot = &rts[1]; - - int recheck_tuple_intersection = 0; - JL_TRY { - // This is kind of awful, but an inner call to instantiate_type - // might fail due to a mismatched type parameter. The problem is - // that we allow Range{T} to exist, even though the declaration of - // Range specifies Range{T<:Real}. Therefore intersection cannot see - // that some parameter values actually don't match. - *pti = jl_type_intersect(a, b, &env, &eqc, &recheck_tuple_intersection, covariant); - } - JL_CATCH { - *pti = (jl_value_t*)jl_bottom_type; - } - if (*pti == (jl_value_t*)jl_bottom_type || - !(env.n > 0 || eqc.n > 0 || tvars != jl_emptysvec)) { - JL_GC_POP(); - return *pti; - } - - int e; - - if (recheck_tuple_intersection) { - for (e = 0; e < eqc.n; e += 2) { - jl_value_t *val = eqc.data[e + 1]; - if (jl_is_long(val)) - break; - } - if (e < eqc.n) { - /* - if there are integer-valued parameters, repeat intersection - with the full environment visible. this is needed because - NTuple has only one element type, so we can't keep track of - the fact that an arbitrary tuple's length must match some - typevar, e.g. "(Int8,Int32...) of length N". the solution is - to find all other constraints on N first, then do intersection - again with that knowledge. - */ - *pti = jl_type_intersect(a, b, &env, &eqc, &recheck_tuple_intersection, covariant); - if (*pti == (jl_value_t*)jl_bottom_type) { - JL_GC_POP(); - return *pti; - } - } - } - - jl_value_t **tvs; - int tvarslen; - if (jl_is_typevar(tvars)) { - tvs = (jl_value_t**)&tvars; - tvarslen = 1; - } - else { - assert(jl_is_svec(tvars)); - tvs = jl_svec_data(tvars); - tvarslen = jl_svec_len(tvars); - } - - if (!solve_tvar_constraints(&env, &eqc, tvs, tvarslen)) { - JL_GC_POP(); - return (jl_value_t*)jl_bottom_type; - } - //jl_printf(JL_STDOUT, "env: "); print_env(&env); - //jl_printf(JL_STDOUT, "sol: "); print_env(&eqc); - - int env0 = eqc.n; - for(int tk=0; tk < tvarslen; tk++) { - jl_tvar_t *tv = (jl_tvar_t*)tvs[tk]; - for(e=0; e < env0; e+=2) { - if (eqc.data[e] == (jl_value_t*)tv) { - break; - } - } - // bind type vars to new similar tvars if they were not matched explicitly - // during type intersection. - if (e >= env0) { - /* - Note: we used to bind T=T, but this can cause a loop if a recursion - is set up such that in a future call T=Foo{T}. If the RHS is - instantiated, we unintentionally construct Foo{Foo{T}} since the - typevar happens to match. This caused issue #6404. - */ - jl_tvar_t *ntv = jl_new_typevar(tv->name, tv->lb, tv->ub); - ntv->bound = tv->bound; - extend_((jl_value_t*)tv, (jl_value_t*)ntv, &eqc, 1); - } - } - - for(int i=0; i < eqc.n; i+=2) { - eqc.data[i+1] = *tvar_lookup(&eqc, &eqc.data[i+1]); - } - if (env0 > 0) { - /* - in a situation like this: - Type{_<:Array{T,1}} ∩ Type{Array{S,N}} - We end up with environment - _ = Array{S,N} - N = 1 - So we need to instantiate all the RHS's first. - */ - for(int i=0; i < eqc.n; i+=2) { - jl_value_t *rhs = eqc.data[i+1]; - int tvar = jl_is_typevar(rhs); - jl_value_t *rhs2 = rhs; - if (tvar && jl_has_typevars(((jl_tvar_t*)rhs)->ub)) { - rhs2 = ((jl_tvar_t*)rhs)->ub; - } - else tvar = 0; - JL_TRY { - jl_value_t *inst = jl_instantiate_type_with(rhs2, eqc.data, eqc.n/2); - eqc.data[i+1] = inst; - if (tvar) { - *extraroot = rhs; - eqc.data[i+1] = (jl_value_t*)jl_new_typevar(underscore_sym, ((jl_tvar_t*)rhs)->lb, inst); - } - } - JL_CATCH { - } - } - - // detect cycles; e.g. (T,Ptr{T}) ∩ (Ptr{S},S) == ⊥ - for(int i=0; i < eqc.n; i+=2) { - jl_value_t *var = eqc.data[i]; - jl_value_t *val = eqc.data[i+1]; - if (val != var && jl_has_typevars_from_v(val, &var, 1)) { - // var's RHS contains the var itself => unsatisfiable (e.g. T = Foo{T}) - JL_GC_POP(); - return (jl_value_t*)jl_bottom_type; - } - } - - JL_TRY { - *pti = (jl_value_t*)jl_instantiate_type_with(*pti, eqc.data, eqc.n/2); - } - JL_CATCH { - *pti = (jl_value_t*)jl_bottom_type; - } - } - - // return environment in same order as tvars - *penv = jl_alloc_svec_uninit(tvarslen); - for(int tk=0; tk < tvarslen; tk++) { - jl_tvar_t *tv = (jl_tvar_t*)tvs[tk]; - for(e=0; e < eqc.n; e+=2) { - if (eqc.data[e] == (jl_value_t*)tv) { - jl_svecset(*penv, tk, eqc.data[e+1]); - } - } - } - - JL_GC_POP(); - if (jl_is_typevar(*pti) && !(jl_is_typevar(a) && jl_is_typevar(b))) - return ((jl_tvar_t*)*pti)->ub; - return *pti; -} - -// --- type instantiation and cache --- - -static int extensionally_same_type(jl_value_t *a, jl_value_t *b) -{ - return jl_subtype(a, b, 0) && jl_subtype(b, a, 0); -} - -static int type_eqv__(jl_value_t *a, jl_value_t *b, int distinguish_tctor) -{ - if (a == b) return 1; - if (distinguish_tctor && jl_is_typector(a) != jl_is_typector(b)) return 0; - if (jl_is_typector(a)) a = (jl_value_t*)((jl_typector_t*)a)->body; - if (jl_is_typector(b)) b = (jl_value_t*)((jl_typector_t*)b)->body; - if (jl_is_typevar(a)) { - if (jl_is_typevar(b)) { - return !distinguish_tctor && type_eqv_(((jl_tvar_t*)a)->ub, ((jl_tvar_t*)b)->ub) && - type_eqv_(((jl_tvar_t*)a)->lb, ((jl_tvar_t*)b)->lb); - } - else { - return 0; - } - } - if (jl_is_uniontype(a)) { - if (jl_is_uniontype(b)) { - return extensionally_same_type(a, b); - } - return 0; - } - if (!jl_is_datatype(a) || !jl_is_datatype(b)) { - return jl_egal(a, b); - } - jl_datatype_t *tta = (jl_datatype_t*)a; - jl_datatype_t *ttb = (jl_datatype_t*)b; - if (tta->name != ttb->name) return 0; - jl_svec_t *ap = tta->parameters; - jl_svec_t *bp = ttb->parameters; - if (jl_svec_len(ap) != jl_svec_len(bp)) { - assert(tta->name == jl_tuple_typename); - return 0; - } - size_t i; - for(i=0; i < jl_svec_len(ap); i++) { - jl_value_t *api = jl_svecref(ap,i); - jl_value_t *bpi = jl_svecref(bp,i); - if (api == bpi) continue; - if (!type_eqv__(api, bpi, distinguish_tctor)) - return 0; - } - return 1; -} - -static int type_eqv_(jl_value_t *a, jl_value_t *b) -{ - return type_eqv__(a, b, 0); -} - -JL_DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b) -{ - return type_eqv_(a, b); -} - -static int type_le_generic(jl_value_t *a, jl_value_t *b, int useenv) -{ - jl_value_t *env = jl_type_match(a, b); - if (env == jl_false) return 0; - size_t l = jl_svec_len(env); - // make sure all typevars correspond to other unique typevars - for(size_t i=0; i < l; i+=2) { - jl_value_t *envi = jl_svecref(env,i+1); - if (!jl_is_typevar(envi)) - return 0; - if (useenv && ((jl_tvar_t*)envi)->bound!=((jl_tvar_t*)jl_svecref(env,i))->bound) - return 0; - for(size_t j=0; j < l; j+=2) { - if (i != j) { - if (envi == jl_svecref(env,j+1)) - return 0; - } - } - } - return 1; -} - -int jl_types_equal_generic(jl_value_t *a, jl_value_t *b, int useenv) -{ - return type_le_generic(a, b, useenv) && type_le_generic(b, a, useenv); -} - -static int valid_type_param(jl_value_t *v) -{ - if (jl_is_tuple(v)) { - // NOTE: tuples of symbols are not currently bits types, but have been - // allowed as type parameters. this is a bit ugly. - jl_value_t *tt = jl_typeof(v); - size_t i; - size_t l = jl_nparams(tt); - for(i=0; i < l; i++) { - jl_value_t *pi = jl_tparam(tt,i); - if (!(pi == (jl_value_t*)jl_sym_type || jl_isbits(pi))) - return 0; - } - return 1; - } - // TODO: maybe more things - return jl_is_type(v) || jl_is_typevar(v) || jl_is_symbol(v) || jl_isbits(jl_typeof(v)); -} - -jl_value_t *jl_apply_type_(jl_value_t *tc, jl_value_t **params, size_t n) -{ - if (tc == (jl_value_t*)jl_anytuple_type) - return (jl_value_t*)jl_apply_tuple_type_v(params, n); - if (tc == (jl_value_t*)jl_uniontype_type) - return (jl_value_t*)jl_type_union_v(params, n); - if (n == 0) { - if (jl_is_typector(tc)) - return (jl_value_t*)((jl_typector_t*)tc)->body; - return tc; - } - size_t i; - const char *tname; - jl_svec_t *tp; - jl_datatype_t *stprimary = NULL; - if (jl_is_typector(tc)) { - tp = ((jl_typector_t*)tc)->parameters; - tname = "typealias"; - } - else { - assert(jl_is_datatype(tc)); - tp = ((jl_datatype_t*)tc)->parameters; - tname = jl_symbol_name(((jl_datatype_t*)tc)->name->name); - stprimary = (jl_datatype_t*)((jl_datatype_t*)tc)->name->primary; - } - for(i=0; i < n; i++) { - jl_value_t *pi = params[i]; - if (!valid_type_param(pi)) { - jl_type_error_rt(tname, "parameter", - jl_subtype(pi, (jl_value_t*)jl_number_type, 1) ? - (jl_value_t*)jl_long_type : (jl_value_t*)jl_type_type, - pi); - } - } - size_t ntp = jl_svec_len(tp); - if (n > ntp) - jl_errorf("too many parameters for type %s", tname); - jl_value_t **env; - JL_GC_PUSHARGS(env, 2*ntp); - size_t ne = 0; - for(i=0; i < ntp; i++) { - jl_tvar_t *tv = (jl_tvar_t*)jl_svecref(tp,i); - if (!jl_is_typevar(tv)) - continue; - env[ne*2+0] = (jl_value_t*)tv; - if (ne >= n) { - if (stprimary && stprimary->types == NULL) { - // during creation of type Foo{A,B}, fill in missing - // trailing parameters with copies for recursive - // instantiations, so that in the future Foo{A} as a field - // type will only be instantiated with the first parameter. - env[ne*2+1] = (jl_value_t*)jl_new_typevar(tv->name, tv->lb, tv->ub); - } - else { - env[ne*2+1] = (jl_value_t*)tv; - } } - else { - // NOTE: type checking deferred to inst_type_w_ to make sure - // supertype parameters are checked recursively. - jl_value_t *pi = params[ne]; - if (tc!=(jl_value_t*)jl_type_type && jl_is_typector(pi)) - env[ne*2+1] = (jl_value_t*)((jl_typector_t*)pi)->body; + } + jl_value_t **ptu = &temp[nt]; + *ptu = NULL; + int k; + for (k = (int)nt-1; k >= 0; --k) { + if (temp[k] != NULL) { + if (*ptu == NULL) + *ptu = temp[k]; else - env[ne*2+1] = pi; + *ptu = jl_new_struct(jl_uniontype_type, temp[k], *ptu); } - ne++; } - if (ne < n) - jl_errorf("too many parameters for type %s", tname); - if (jl_is_typector(tc)) tc = (jl_value_t*)((jl_typector_t*)tc)->body; - jl_value_t *result = jl_instantiate_type_with((jl_value_t*)tc, env, ne); - JL_GC_POP(); - return (jl_value_t*)result; -} - -JL_DLLEXPORT jl_value_t *jl_apply_type(jl_value_t *tc, jl_svec_t *params) -{ - // NOTE: callers are supposed to root these arguments, but there are - // several uses that don't, so root here just to be safe. - JL_GC_PUSH1(¶ms); - jl_value_t *t = jl_apply_type_(tc, jl_svec_data(params), jl_svec_len(params)); + assert(*ptu != NULL); + jl_value_t *tu = *ptu; JL_GC_POP(); - return t; + return tu; } -JL_DLLEXPORT jl_value_t *jl_tupletype_fill(size_t n, jl_value_t *v) -{ - // TODO: replace with just using NTuple - jl_value_t *p = NULL; - JL_GC_PUSH1(&p); - p = (jl_value_t*)jl_svec_fill(n, v); - p = (jl_value_t*)jl_apply_tuple_type((jl_svec_t*)p); - JL_GC_POP(); - return p; -} +// --- type instantiation and cache --- static int contains_unions(jl_value_t *type) { - if (jl_is_uniontype(type)) return type != jl_bottom_type; - if (jl_is_typector(type)) return contains_unions(((jl_typector_t*)type)->body); + if (jl_is_uniontype(type)) return 1; + if (jl_is_unionall(type)) return contains_unions(((jl_unionall_t*)type)->body); if (!jl_is_datatype(type)) return 0; int i; for(i=0; i < jl_nparams(type); i++) { @@ -1893,11 +324,10 @@ static int is_typekey_ordered(jl_value_t **key, size_t n) jl_value_t *k = key[i]; if (jl_is_typevar(k)) return 0; - if (jl_is_type(k) && + if (jl_is_type(k) && k != jl_bottom_type && !(jl_is_datatype(k) && (((jl_datatype_t*)k)->uid || - k == ((jl_datatype_t*)k)->name->primary || - (!jl_has_typevars_(k,1) && !contains_unions(k)))) && - k != jl_bottom_type) + //k == ((jl_datatype_t*)k)->name->primary || + (!jl_has_free_typevars(k) && !contains_unions(k))))) return 0; } return 1; @@ -1971,7 +401,7 @@ static int typekey_eq(jl_datatype_t *tt, jl_value_t **key, size_t n) if (n != tnp) return 0; for(j=0; j < n; j++) { jl_value_t *kj = key[j], *tj = jl_svecref(tt->parameters,j); - if (tj != kj && !type_eqv__(tj, kj, 1)) + if (tj != kj && !jl_types_equal(tj, kj)) return 0; } return 1; @@ -2043,9 +473,9 @@ static int is_cacheable(jl_datatype_t *type) assert(jl_is_datatype(type)); jl_svec_t *t = type->parameters; if (jl_svec_len(t) == 0) return 0; - // cache abstract types with no type vars + // cache abstract types with no free type vars if (jl_is_abstracttype(type)) - return !jl_has_typevars_((jl_value_t*)type, 1); + return !jl_has_free_typevars((jl_value_t*)type); // ... or concrete types return jl_is_leaf_type((jl_value_t*)type); } @@ -2102,15 +532,142 @@ jl_value_t *jl_cache_type_(jl_datatype_t *type) return (jl_value_t*)type; } +// type instantiation + +static int valid_type_param(jl_value_t *v) +{ + if (jl_is_tuple(v)) { + // NOTE: tuples of symbols are not currently bits types, but have been + // allowed as type parameters. this is a bit ugly. + jl_value_t *tt = jl_typeof(v); + size_t i; + size_t l = jl_nparams(tt); + for(i=0; i < l; i++) { + jl_value_t *pi = jl_tparam(tt,i); + if (!(pi == (jl_value_t*)jl_sym_type || jl_isbits(pi))) + return 0; + } + return 1; + } + // TODO: maybe more things + return jl_is_type(v) || jl_is_typevar(v) || jl_is_symbol(v) || jl_isbits(jl_typeof(v)); +} + +static int within_typevar(jl_value_t *t, jl_tvar_t *v) +{ + jl_value_t *lb = t, *ub = t; + if (jl_is_typevar(t)) { + // TODO: automatically restrict typevars in method definitions based on + // types they are used in. + return 1; + //lb = ((jl_tvar_t*)t)->lb; + //ub = ((jl_tvar_t*)t)->ub; + } + else if (!jl_is_type(t)) { + return v->lb == jl_bottom_type && v->ub == jl_any_type; + } + return jl_subtype(v->lb, lb) && jl_subtype(ub, v->ub); +} + +jl_value_t *jl_apply_type(jl_value_t *tc, jl_value_t **params, size_t n) +{ + if (tc == (jl_value_t*)jl_anytuple_type) + return (jl_value_t*)jl_apply_tuple_type_v(params, n); + if (tc == (jl_value_t*)jl_uniontype_type) + return (jl_value_t*)jl_type_union(params, n); + JL_GC_PUSH1(&tc); + size_t i; + for (i=0; i < n; i++) { + if (!jl_is_unionall(tc)) + jl_error("too many parameters for type"); + jl_value_t *pi = params[i]; + + if (!valid_type_param(pi)) { + jl_type_error_rt("type", "parameter", + jl_isa(pi, (jl_value_t*)jl_number_type) ? + (jl_value_t*)jl_long_type : (jl_value_t*)jl_type_type, + pi); + } + + jl_unionall_t *ua = (jl_unionall_t*)tc; + if (jl_has_free_typevars(ua->var->lb) || jl_has_free_typevars(ua->var->ub)) + jl_error("invalid instantiation"); + if (!within_typevar(pi, ua->var)) + jl_type_error_rt("type", "parameter", (jl_value_t*)ua->var, pi); + + tc = jl_instantiate_unionall(ua, pi); + } + JL_GC_POP(); + return tc; +} + +JL_DLLEXPORT jl_value_t *jl_apply_type1(jl_value_t *tc, jl_value_t *p1) +{ + JL_GC_PUSH1(&p1); + jl_value_t *t = jl_apply_type(tc, &p1, 1); + JL_GC_POP(); + return t; +} + +JL_DLLEXPORT jl_value_t *jl_apply_type2(jl_value_t *tc, jl_value_t *p1, jl_value_t *p2) +{ + jl_value_t **args; + JL_GC_PUSHARGS(args, 2); + args[0] = p1; args[1] = p2; + jl_value_t *t = jl_apply_type(tc, args, 2); + JL_GC_POP(); + return t; +} + +JL_DLLEXPORT jl_value_t *jl_tupletype_fill(size_t n, jl_value_t *v) +{ + // TODO: replace with just using NTuple + jl_value_t *p = NULL; + JL_GC_PUSH1(&p); + p = (jl_value_t*)jl_svec_fill(n, v); + p = (jl_value_t*)jl_apply_tuple_type((jl_svec_t*)p); + JL_GC_POP(); + return p; +} + typedef struct _jl_typestack_t { jl_datatype_t *tt; struct _jl_typestack_t *prev; } jl_typestack_t; -static jl_value_t *inst_type_w_(jl_value_t *t, jl_value_t **env, size_t n, - jl_typestack_t *stack, int check); -static jl_svec_t *inst_all(jl_svec_t *p, jl_value_t **env, size_t n, - jl_typestack_t *stack, int check); +static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t *stack, int check); +static jl_svec_t *inst_all(jl_svec_t *p, jl_typeenv_t *env, jl_typestack_t *stack, int check); + +JL_DLLEXPORT jl_value_t *jl_instantiate_unionall(jl_unionall_t *u, jl_value_t *p) +{ + jl_typeenv_t env = { u->var, p, NULL }; + return inst_type_w_(u->body, &env, NULL, 1); +} + +jl_value_t *jl_substitute_var(jl_value_t *t, jl_tvar_t *var, jl_value_t *val) +{ + jl_typeenv_t env = { var, val, NULL }; + return inst_type_w_(t, &env, NULL, 1); +} + +jl_value_t *jl_unwrap_unionall(jl_value_t *v) +{ + while (jl_is_unionall(v)) + v = ((jl_unionall_t*)v)->body; + return v; +} + +// wrap `t` in the same unionalls that surround `u` +jl_value_t *jl_rewrap_unionall(jl_value_t *t, jl_value_t *u) +{ + if (!jl_is_unionall(u)) + return t; + JL_GC_PUSH1(&t); + t = jl_rewrap_unionall(t, ((jl_unionall_t*)u)->body); + t = jl_new_unionall_type(((jl_unionall_t*)u)->var, t); + JL_GC_POP(); + return t; +} static jl_value_t *lookup_type_stack(jl_typestack_t *stack, jl_datatype_t *tt, size_t ntp, jl_value_t **iparams) @@ -2123,7 +680,9 @@ static jl_value_t *lookup_type_stack(jl_typestack_t *stack, jl_datatype_t *tt, s ntp == jl_svec_len(stack->tt->parameters) && typekey_eq(stack->tt, iparams, ntp)) { jl_value_t *lkup = (jl_value_t*)stack->tt; - return lkup == tn->primary ? NULL : lkup; + // TODO jb/subtype + //return lkup == jl_unwrap_unionall(tn->wrapper) ? NULL : lkup; + return lkup; } stack = stack->prev; } @@ -2133,16 +692,9 @@ static jl_value_t *lookup_type_stack(jl_typestack_t *stack, jl_datatype_t *tt, s static size_t jl_type_depth(jl_value_t *dt) { if (jl_is_uniontype(dt)) { - jl_svec_t *t = ((jl_uniontype_t*)dt)->types; - size_t i, l = jl_svec_len(t); - size_t depth = 0; - for (i = 0; i < l; i++) { - jl_value_t *p = jl_svecref(t, i); - size_t d = jl_type_depth(p); - if (d > depth) - depth = d; - } - return depth; + size_t ad = jl_type_depth(((jl_uniontype_t*)dt)->a); + size_t bd = jl_type_depth(((jl_uniontype_t*)dt)->b); + return ad > bd ? ad : bd; } else if (jl_is_datatype(dt)) { return ((jl_datatype_t*)dt)->depth; @@ -2154,31 +706,28 @@ void jl_precompute_memoized_dt(jl_datatype_t *dt) { int istuple = dt->name == jl_tuple_typename; size_t i, l = jl_nparams(dt); - dt->isleaftype = !dt->abstract || (jl_type_type != NULL && dt->name == jl_type_type->name); + dt->isleaftype = !dt->abstract || (jl_type_type != NULL && dt->name == jl_type_typename); for (i = 0; i < l; i++) { jl_value_t *p = jl_tparam(dt, i); size_t d = jl_type_depth(p) + 1; if (d > dt->depth) dt->depth = d; - if (!dt->hastypevars) - dt->hastypevars = jl_has_typevars__(p, 0, NULL, 0); - if (!dt->haswildcard) - dt->haswildcard = jl_has_typevars__(p, 1, NULL, 0); + if (!dt->hasfreetypevars) + dt->hasfreetypevars = jl_has_free_typevars(p); if (dt->isleaftype) - dt->isleaftype = (istuple ? jl_is_leaf_type(p) : !jl_has_typevars(p)); + dt->isleaftype = (istuple ? jl_is_leaf_type(p) : !dt->hasfreetypevars); } } static arraylist_t partial_inst; +int inside_typedef = 0; static jl_value_t *inst_datatype(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **iparams, size_t ntp, - int cacheable, jl_typestack_t *stack, - jl_value_t **env, size_t n) + int cacheable, jl_typestack_t *stack, jl_typeenv_t *env) { jl_ptls_t ptls = jl_get_ptls_states(); jl_typestack_t top; jl_typename_t *tn = dt->name; - jl_value_t *tc = tn->primary; int istuple = (tn == jl_tuple_typename); // check type cache if (cacheable) { @@ -2195,21 +744,20 @@ static jl_value_t *inst_datatype(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **i return stack_lkup; } - if (istuple && ntp > 0 && jl_is_vararg_type(iparams[ntp - 1])) { + jl_value_t *last = iparams[ntp - 1]; + if (istuple && ntp > 0 && jl_is_vararg_type(last)) { // normalize Tuple{..., Vararg{Int, 3}} to Tuple{..., Int, Int, Int} - jl_value_t *va = iparams[ntp - 1]; + jl_value_t *va = jl_unwrap_unionall(last); // return same `Tuple` object for types equal to it if (ntp == 1 && jl_tparam0(va) == (jl_value_t*)jl_any_type && - jl_tparam1(va) == jl_tparam1(jl_tparam0(jl_anytuple_type))) { - if (cacheable) JL_UNLOCK(&typecache_lock); // Might GC + jl_is_unionall(last) && jl_tparam1(va) == (jl_value_t*)((jl_unionall_t*)last)->var) return (jl_value_t*)jl_anytuple_type; - } if (jl_is_long(jl_tparam1(va))) { ssize_t nt = jl_unbox_long(jl_tparam1(va)); if (nt < 0) jl_errorf("apply_type: Vararg length N is negative: %zd", nt); va = jl_tparam0(va); - if (nt == 0 || !jl_has_typevars(va)) { + if (nt == 0 || !jl_has_free_typevars(va)) { if (cacheable) JL_UNLOCK(&typecache_lock); // Might GC if (ntp == 1) return jl_tupletype_fill(nt, va); @@ -2230,17 +778,12 @@ static jl_value_t *inst_datatype(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **i } } - // always use original type constructor if (!istuple) { if (jl_is_vararg_type((jl_value_t*)dt) && ntp == 2) { if (!jl_is_long(iparams[1]) && !jl_is_typevar(iparams[1])) { jl_type_error_rt("apply_type", "Vararg count", (jl_value_t*)jl_long_type, iparams[1]); } } - if (tc != (jl_value_t*)dt) { - if (cacheable) JL_UNLOCK(&typecache_lock); // Might GC - return (jl_value_t*)jl_apply_type_(tc, iparams, ntp); - } } else if (ntp == 0 && jl_emptytuple != NULL) { if (cacheable) JL_UNLOCK(&typecache_lock); // Might GC @@ -2288,7 +831,7 @@ static jl_value_t *inst_datatype(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **i ndt->super = jl_any_type; } else if (dt->super) { - ndt->super = (jl_datatype_t*)inst_type_w_((jl_value_t*)dt->super, env,n,stack, 1); + ndt->super = (jl_datatype_t*)inst_type_w_((jl_value_t*)dt->super, env, stack, 1); jl_gc_wb(ndt, ndt->super); } ftypes = dt->types; @@ -2313,7 +856,7 @@ static jl_value_t *inst_datatype(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **i assert(!ndt->abstract); if (!istuple) { // recursively instantiate the types of the fields - ndt->types = inst_all(ftypes, env, n, stack, 1); + ndt->types = inst_all(ftypes, env, stack, 1); jl_gc_wb(ndt, ndt->types); } if (cacheable) { @@ -2362,7 +905,7 @@ static jl_tupletype_t *jl_apply_tuple_type_v_(jl_value_t **p, size_t np, jl_svec cacheable = 0; } jl_datatype_t *ndt = (jl_datatype_t*)inst_datatype(jl_anytuple_type, params, p, np, - cacheable, NULL, NULL, 0); + cacheable, NULL, NULL); return ndt; } @@ -2378,30 +921,28 @@ JL_DLLEXPORT jl_tupletype_t *jl_apply_tuple_type_v(jl_value_t **p, size_t np) jl_datatype_t *jl_inst_concrete_tupletype(jl_svec_t *p) { - return (jl_datatype_t*)inst_datatype(jl_anytuple_type, p, jl_svec_data(p), jl_svec_len(p), 1, NULL, NULL, 0); + return (jl_datatype_t*)inst_datatype(jl_anytuple_type, p, jl_svec_data(p), jl_svec_len(p), 1, NULL, NULL); } jl_datatype_t *jl_inst_concrete_tupletype_v(jl_value_t **p, size_t np) { - return (jl_datatype_t*)inst_datatype(jl_anytuple_type, NULL, p, np, 1, NULL, NULL, 0); + return (jl_datatype_t*)inst_datatype(jl_anytuple_type, NULL, p, np, 1, NULL, NULL); } -static jl_svec_t *inst_all(jl_svec_t *p, jl_value_t **env, size_t n, - jl_typestack_t *stack, int check) +static jl_svec_t *inst_all(jl_svec_t *p, jl_typeenv_t *env, jl_typestack_t *stack, int check) { size_t i; size_t lp = jl_svec_len(p); jl_svec_t *np = jl_alloc_svec(lp); JL_GC_PUSH1(&np); for(i=0; i < lp; i++) { - jl_svecset(np, i, (jl_value_t*)inst_type_w_(jl_svecref(p,i), env, n, stack, check)); + jl_svecset(np, i, (jl_value_t*)inst_type_w_(jl_svecref(p,i), env, stack, check)); } JL_GC_POP(); return np; } -static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_value_t **env, size_t n, - jl_typestack_t *stack, int check) +static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t *stack, int check) { jl_datatype_t *tt = (jl_datatype_t*)t; jl_svec_t *tp = tt->parameters; @@ -2413,17 +954,16 @@ static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_value_t **env, size_t n, // If this is a Tuple{Vararg{T,N}} with known N, expand it to // a fixed-length tuple jl_value_t *T=NULL, *N=NULL; - jl_value_t *ttT = jl_tparam0(jl_tparam0(tt)); - jl_value_t *ttN = jl_tparam1(jl_tparam0(tt)); - int i; - for (i = 0; i < 2*n; i+=2) { - jl_value_t *tv = env[i]; - if (jl_is_typevar(tv)) { - if (tv == ttT) - T = env[i+1]; - else if (tv == ttN) - N = env[i+1]; - } + jl_value_t *va = jl_unwrap_unionall(jl_tparam0(tt)); + jl_value_t *ttT = jl_tparam0(va); + jl_value_t *ttN = jl_tparam1(va); + jl_typeenv_t *e = env; + while (e != NULL) { + if ((jl_value_t*)e->var == ttT) + T = e->val; + else if ((jl_value_t*)e->var == ttN) + N = e->val; + e = e->prev; } if (T != NULL && N != NULL && jl_is_long(N)) { ssize_t nt = jl_unbox_long(N); @@ -2448,7 +988,7 @@ static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_value_t **env, size_t n, int i; for(i=0; i < ntp; i++) { jl_value_t *elt = jl_svecref(tp, i); - jl_value_t *pi = (jl_value_t*)inst_type_w_(elt, env, n, stack, 0); + jl_value_t *pi = (jl_value_t*)inst_type_w_(elt, env, stack, 0); iparams[i] = pi; if (ip_heap) jl_gc_wb(ip_heap, pi); @@ -2458,34 +998,74 @@ static jl_value_t *inst_tuple_w_(jl_value_t *t, jl_value_t **env, size_t n, } } jl_value_t *result = inst_datatype((jl_datatype_t*)tt, ip_heap, iparams, ntp, cacheable, - stack, env, n); + stack, env); JL_GC_POP(); return result; } -static jl_value_t *inst_type_w_(jl_value_t *t, jl_value_t **env, size_t n, - jl_typestack_t *stack, int check) +static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t *stack, int check) { - size_t i, j; - if (n == 0) return t; + size_t i; if (jl_is_typevar(t)) { - for(i=0; i < n; i++) { - if (env[i*2] == t) { - jl_value_t *val = env[i*2+1]; - if (check && !jl_is_typevar(val) && !jl_subtype(val, t, 0)) { + jl_typeenv_t *e = env; + while (e != NULL) { + if (e->var == (jl_tvar_t*)t) { + jl_value_t *val = e->val; + if (check && !jl_is_typevar(val) && !within_typevar(val, (jl_tvar_t*)t)) { jl_type_error_rt("type parameter", - jl_symbol_name(((jl_tvar_t*)t)->name), - t, val); + jl_symbol_name(((jl_tvar_t*)t)->name), t, val); } return val; } + e = e->prev; } return (jl_value_t*)t; } + if (jl_is_unionall(t)) { + jl_unionall_t *ua = (jl_unionall_t*)t; + jl_value_t *res; + if (!jl_has_free_typevars(t)) { + return t; + } + else if (typeenv_has(env, ua->var) || jl_has_bound_typevars(ua->var->lb, env) || + jl_has_bound_typevars(ua->var->ub, env)) { + jl_value_t *lb=NULL, *ub=NULL, *body=NULL; + jl_tvar_t *ntv=NULL; + JL_GC_PUSH4(&lb, &ub, &ntv, &body); + lb = inst_type_w_(ua->var->lb, env, stack, check); + ub = inst_type_w_(ua->var->ub, env, stack, check); + ntv = jl_new_typevar(ua->var->name, lb, ub); + jl_typeenv_t newenv = { ua->var, (jl_value_t*)ntv, env }; + body = inst_type_w_(ua->body, &newenv, stack, check); + res = jl_new_struct(jl_unionall_type, ntv, body); + JL_GC_POP(); + } + else { + jl_value_t *body=NULL; + JL_GC_PUSH1(&body); + body = inst_type_w_(ua->body, env, stack, check); + if (body == ua->body) + res = t; + else + res = jl_new_struct(jl_unionall_type, ua->var, body); + JL_GC_POP(); + } + return res; + } if (jl_is_uniontype(t)) { - jl_svec_t *p = inst_all(((jl_uniontype_t*)t)->types, env, n, stack, 1); - JL_GC_PUSH1(&p); - jl_value_t *res = (jl_value_t*)jl_type_union(p); + jl_uniontype_t *u = (jl_uniontype_t*)t; + jl_value_t *a = inst_type_w_(u->a, env, stack, check); + jl_value_t *b = NULL; + JL_GC_PUSH2(&a, &b); + b = inst_type_w_(u->b, env, stack, check); + jl_value_t *res; + if (a == u->a && b == u->b) { + res = t; + } + else { + jl_value_t *uargs[2] = {a, b}; + res = jl_type_union(uargs, 2); + } JL_GC_POP(); return res; } @@ -2496,68 +1076,63 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_value_t **env, size_t n, if (tp == jl_emptysvec) return (jl_value_t*)t; jl_typename_t *tn = tt->name; - jl_value_t *tc = tn->primary; - // don't instantiate "Foo" without parameters inside Foo - if (t == tc && stack!=NULL) - return (jl_value_t*)t; - assert(jl_is_datatype(tc)); if (tn == jl_tuple_typename) - return inst_tuple_w_(t, env, n, stack, check); + return inst_tuple_w_(t, env, stack, check); size_t ntp = jl_svec_len(tp); - assert(ntp == jl_svec_len(((jl_datatype_t*)tc)->parameters)); + jl_value_t *wrapper = tn->wrapper; jl_value_t **iparams; JL_GC_PUSHARGS(iparams, ntp); int cacheable = 1, bound = 0; for(i=0; i < ntp; i++) { jl_value_t *elt = jl_svecref(tp, i); - if (elt == t) { - iparams[i] = t; - } - else { - jl_value_t *tv = jl_svecref(((jl_datatype_t*)tc)->parameters, i); - iparams[i] = (jl_value_t*)inst_type_w_(elt, env, n, stack, elt != tv); - if (jl_is_typevar(tv) && !jl_is_typevar(iparams[i])) { - if (!jl_subtype(iparams[i], tv, 0)) { - jl_type_error_rt(jl_symbol_name(tt->name->name), - jl_symbol_name(((jl_tvar_t*)tv)->name), - tv, iparams[i]); - } - } - if (!bound) { - for(j=0; j < n; j++) { - if (env[j*2] == tv) { - bound = 1; break; - } - } - } - if (cacheable && jl_has_typevars(iparams[i])) - cacheable = 0; - } + iparams[i] = (jl_value_t*)inst_type_w_(elt, env, stack, check); + assert(jl_is_unionall(wrapper)); + jl_tvar_t *tv = ((jl_unionall_t*)wrapper)->var; + if (!within_typevar(iparams[i], tv)) { + jl_type_error_rt(jl_symbol_name(tn->name), jl_symbol_name(tv->name), + tv, iparams[i]); + } + wrapper = ((jl_unionall_t*)wrapper)->body; + bound |= (iparams[i] != elt); + if (cacheable && jl_has_free_typevars(iparams[i])) + cacheable = 0; } // if t's parameters are not bound in the environment, return it uncopied (#9378) - if (!bound && t == tc) { JL_GC_POP(); return (jl_value_t*)t; } + if (!bound) { JL_GC_POP(); return (jl_value_t*)t; } jl_value_t *result = inst_datatype((jl_datatype_t*)tt, NULL, iparams, ntp, cacheable, - stack, env, n); + stack, env); JL_GC_POP(); return result; } +jl_value_t *instantiate_with(jl_value_t *t, jl_value_t **env, size_t n, jl_typeenv_t *te, jl_typestack_t *stack) +{ + if (n > 0) { + jl_typeenv_t en = { (jl_tvar_t*)env[0], env[1], te }; + return instantiate_with(t, &env[2], n-1, &en, stack); + } + return inst_type_w_(t, te, stack, 1); +} + jl_value_t *jl_instantiate_type_with(jl_value_t *t, jl_value_t **env, size_t n) { - return inst_type_w_((jl_value_t*)t, env, n, NULL, 1); + return instantiate_with(t, env, n, NULL, NULL); } jl_datatype_t *jl_wrap_Type(jl_value_t *t) { - jl_value_t *env[2]; - env[0] = jl_tparam0(jl_type_type); - //if (jl_is_typector(t)) - // env[1] = (jl_value_t*)((jl_typector_t*)t)->body; - //else - env[1] = t; - return (jl_datatype_t*) - jl_instantiate_type_with((jl_value_t*)jl_type_type, env, 1); + return (jl_datatype_t*)jl_instantiate_unionall(jl_type_type, t); +} + +jl_value_t *jl_wrap_vararg(jl_value_t *t, jl_value_t *n) +{ + if (n == NULL) { + if (t == NULL) + return (jl_value_t*)jl_vararg_type; + return jl_instantiate_unionall(jl_vararg_type, t); + } + return jl_instantiate_unionall((jl_unionall_t*)jl_instantiate_unionall(jl_vararg_type, t), n); } void jl_reinstantiate_inner_types(jl_datatype_t *t) // can throw! @@ -2569,268 +1144,58 @@ void jl_reinstantiate_inner_types(jl_datatype_t *t) // can throw! top.tt = t; top.prev = NULL; size_t i, j, n = jl_svec_len(t->parameters); - if (n == 0) { - assert(partial_inst.len == 0); - return; - } - - jl_value_t **env = (jl_value_t**)alloca(n * 2 * sizeof(void*)); - for (i = 0; i < n; i++) { - env[i * 2] = jl_svecref(t->parameters, i); - env[i * 2 + 1] = NULL; - } - - for (j = 0; j < partial_inst.len; j++) { - jl_datatype_t *ndt = (jl_datatype_t*)partial_inst.items[j]; - assert(ndt->name->primary == (jl_value_t*)t); - for (i = 0; i < n; i++) - env[i * 2 + 1] = jl_svecref(ndt->parameters, i); - - ndt->super = (jl_datatype_t*)inst_type_w_((jl_value_t*)t->super, env, n, &top, 1); - jl_gc_wb(ndt, ndt->super); - } - - if (t->name->names != jl_emptysvec) { - for (j = 0; j < partial_inst.len; j++) { - jl_datatype_t *ndt = (jl_datatype_t*)partial_inst.items[j]; - assert(ndt->name->primary == (jl_value_t*)t); - for (i = 0; i < n; i++) - env[i * 2 + 1] = jl_svecref(ndt->parameters, i); - - ndt->types = inst_all(t->types, env, n, &top, /*check*/1); - jl_gc_wb(ndt, ndt->types); - if (ndt->uid) { // cacheable - jl_compute_field_offsets(ndt); - if (jl_is_datatype_make_singleton(ndt)) { - ndt->instance = jl_gc_alloc(ptls, 0, ndt); - jl_gc_wb(ndt, ndt->instance); - } - } - } - } - else { - assert(t->types == jl_emptysvec); - } - partial_inst.len = 0; -} - -void jl_reset_instantiate_inner_types(jl_datatype_t *t) -{ - // the declaration of `t` is invalid, forget about all of the WIP - inside_typedef = 0; - partial_inst.len = 0; -} - -// subtype comparison - -static int jl_subtype_le(jl_value_t *a, jl_value_t *b, int ta, int invariant); - -static int jl_tuple_subtype_(jl_value_t **child, size_t clenr, - jl_datatype_t *pdt, int ta, int invariant) -{ - size_t plenr = jl_nparams(pdt); - jl_value_t **parent = jl_svec_data(pdt->parameters); - size_t plenf, clenf; - jl_vararg_kind_t ckind, pkind; - jl_tuple_lenkind_t clenkind, plenkind; - int bottom = 0; - // Stage 1 - clenf = data_vararg_params(child, clenr, NULL, &ckind, &clenkind); - plenf = tuple_vararg_params(pdt->parameters, NULL, &pkind, &plenkind); - // Stage 2 - if (clenkind == JL_TUPLE_FIXED && plenkind == JL_TUPLE_FIXED) { - bottom = clenf != plenf; - } - else if (clenkind == JL_TUPLE_FIXED && plenkind == JL_TUPLE_VAR) { - bottom = clenf+1 < plenf; - } - if (plenr == 0 && clenr > 0) - bottom = 1; - if (bottom) return 0; - size_t ci=0, pi=0; - jl_value_t *ce=NULL, *pe=NULL; - int cseq=0, pseq=0; - // Stage 3 - int result = 0; - while (1) { - if (!cseq) - cseq = !ta && ci= clenf) { - result = pi >= plenf || (pseq && !invariant); - break; - } - if (pi >= plenf && !pseq) - break; - if (ci < clenr) { - ce = child[ci]; - if (jl_is_vararg_type(ce)) ce = jl_tparam0(ce); - } - if (pi < plenr) { - pe = parent[pi]; - if (jl_is_vararg_type(pe)) pe = jl_tparam0(pe); - } - - if (!jl_subtype_le(ce, pe, ta, invariant)) - break; - - if (cseq && pseq) { - result = 1; - break; - } - ci++; - pi++; - } - return result; -} - -int jl_tuple_subtype(jl_value_t **child, size_t cl, jl_datatype_t *pdt, int ta) -{ - return jl_tuple_subtype_(child, cl, pdt, ta, 0); -} - -// ta specifies whether typeof() should be implicitly applied to a. -int jl_subtype_le(jl_value_t *a, jl_value_t *b, int ta, int invariant) -{ - if (!ta&&jl_is_typector(a)) a = (jl_value_t*)((jl_typector_t*)a)->body; - if (jl_is_typector(b)) b = (jl_value_t*)((jl_typector_t*)b)->body; - if (ta) { - if (jl_is_type_type(b)) { - return jl_is_type(a) && jl_subtype_le(a, jl_tparam0(b), 0, 1); - } - } - else if (a == b) { - // Union{} <: Union{} - return 1; - } - - size_t i; - if (!ta && jl_is_uniontype(a)) { - jl_svec_t *ap = ((jl_uniontype_t*)a)->types; - size_t l_ap = jl_svec_len(ap); - if (invariant && !jl_is_typevar(b)) { - return jl_subtype_le(a,b,0,0) && jl_subtype_le(b,a,0,0); - } - for(i=0; i < l_ap; i++) { - if (!jl_subtype_le(jl_svecref(ap,i), b, 0, invariant)) - return 0; - } - return 1; - } - - if (!ta && jl_is_type_type(a) && !invariant) { - jl_value_t *tp0a = jl_tparam0(a); - if (jl_is_typevar(tp0a)) { - jl_value_t *ub = ((jl_tvar_t*)tp0a)->ub; - jl_value_t *lb = ((jl_tvar_t*)tp0a)->lb; - if (jl_subtype_le(ub, b, 1, 0) && - !jl_subtype_le((jl_value_t*)jl_any_type, ub, 0, 0)) { - if (jl_subtype_le(lb, b, 1, 0)) - return 1; - } - } - else { - if (jl_subtype_le(tp0a, b, 1, 0)) - return 1; - } - } - - if (jl_is_uniontype(b)) { - if (invariant) - return 0; - jl_svec_t *bp = ((jl_uniontype_t*)b)->types; - for(i=0; i < jl_svec_len(bp); i++) { - if (jl_subtype_le(a, jl_svecref(bp,i), ta, invariant)) - return 1; - } - if (!ta && jl_is_typevar(a) && ((jl_tvar_t*)a)->ub == jl_bottom_type) - return 1; - return 0; + if (n == 0) { + assert(partial_inst.len == 0); + return; + } + + jl_value_t **env = (jl_value_t**)alloca(n * 2 * sizeof(void*)); + for (i = 0; i < n; i++) { + env[i * 2] = jl_svecref(t->parameters, i); + env[i * 2 + 1] = NULL; } - if (ta) a = (jl_value_t*)jl_typeof(a); + for (j = 0; j < partial_inst.len; j++) { + jl_datatype_t *ndt = (jl_datatype_t*)partial_inst.items[j]; + assert(jl_unwrap_unionall(ndt->name->wrapper) == (jl_value_t*)t); + for (i = 0; i < n; i++) + env[i * 2 + 1] = jl_svecref(ndt->parameters, i); - if (jl_is_tuple_type(a)) { - if (jl_is_tuple_type(b)) { - return jl_tuple_subtype_(jl_svec_data(((jl_datatype_t*)a)->parameters), jl_nparams(a), - (jl_datatype_t*)b, 0, invariant); - } + ndt->super = (jl_datatype_t*)instantiate_with((jl_value_t*)t->super, env, n, NULL, &top); + jl_gc_wb(ndt, ndt->super); } - if (a == b) return 1; - if (!invariant && (jl_datatype_t*)b == jl_any_type) return 1; + if (t->name->names != jl_emptysvec) { + for (j = 0; j < partial_inst.len; j++) { + jl_datatype_t *ndt = (jl_datatype_t*)partial_inst.items[j]; + for (i = 0; i < n; i++) + env[i * 2 + 1] = jl_svecref(ndt->parameters, i); - if (jl_is_datatype(a) && jl_is_datatype(b)) { - if ((jl_datatype_t*)a == jl_any_type) return 0; - jl_datatype_t *tta = (jl_datatype_t*)a; - jl_datatype_t *ttb = (jl_datatype_t*)b; - int super=0; - while (tta != (jl_datatype_t*)jl_any_type) { - if (tta->name == ttb->name) { - if (super && ttb->name == jl_type_type->name && jl_is_typevar(jl_tparam0(b))) { - if (jl_subtype_le(a, jl_tparam0(b), 0, 1)) - return 1; - } - assert(jl_nparams(tta) == jl_nparams(ttb)); - size_t l = jl_nparams(tta); - for(i=0; i < l; i++) { - jl_value_t *apara = jl_tparam(tta,i); - jl_value_t *bpara = jl_tparam(ttb,i); - if (invariant) { - if (jl_is_typevar(bpara) && !((jl_tvar_t*)bpara)->bound) { - if (!jl_is_typevar(apara)) - return 0; - } - } - if (!jl_subtype_le(apara, bpara, 0, 1)) - return 0; - } - return 1; + int k; + // TODO jb/subtype - might need to allocate a new svec here + for (k=0; k < jl_svec_len(t->types); k++) { + jl_svecset(t->types, k, instantiate_with(jl_svecref(t->types,k), env, n, NULL, &top)); } - else if (invariant) { - return 0; + if (ndt->uid) { // cacheable + jl_compute_field_offsets(ndt); + if (jl_is_datatype_make_singleton(ndt)) { + ndt->instance = jl_gc_alloc(ptls, 0, ndt); + jl_gc_wb(ndt, ndt->instance); + } } - if (tta->super == NULL) - jl_errorf("circular type parameter constraint in definition of %s", jl_symbol_name(tta->name->name)); - tta = tta->super; super = 1; - } - assert(!invariant); - return 0; - } - - if (jl_is_typevar(a)) { - if (jl_is_typevar(b)) { - return - jl_subtype_le((jl_value_t*)((jl_tvar_t*)a)->ub, - (jl_value_t*)((jl_tvar_t*)b)->ub, 0, 0) && - jl_subtype_le((jl_value_t*)((jl_tvar_t*)b)->lb, - (jl_value_t*)((jl_tvar_t*)a)->lb, 0, 0); - } - if (invariant) { - return 0; } - return jl_subtype_le((jl_value_t*)((jl_tvar_t*)a)->ub, b, 0, 0); } - if (jl_is_typevar(b)) { - return jl_subtype_le(a, (jl_value_t*)((jl_tvar_t*)b)->ub, 0, 0) && - jl_subtype_le((jl_value_t*)((jl_tvar_t*)b)->lb, a, 0, 0); + else { + assert(t->types == jl_emptysvec); } - if ((jl_datatype_t*)a == jl_any_type) return 0; - - return jl_egal(a, b); -} - -JL_DLLEXPORT int jl_subtype(jl_value_t *a, jl_value_t *b, int ta) -{ - return jl_subtype_le(a, b, ta, 0); + partial_inst.len = 0; } -int jl_subtype_invariant(jl_value_t *a, jl_value_t *b, int ta) +void jl_reset_instantiate_inner_types(jl_datatype_t *t) { - return jl_subtype_le(a, b, ta, 1); + // the declaration of `t` is invalid, forget about all of the WIP + inside_typedef = 0; + partial_inst.len = 0; } // specificity comparison @@ -2840,26 +1205,73 @@ static int type_eqv_with_ANY(jl_value_t *a, jl_value_t *b) // equate ANY and Any for specificity purposes, #16153 return ((a == (jl_value_t*)jl_any_type && b == jl_ANY_flag) || (b == (jl_value_t*)jl_any_type && a == jl_ANY_flag) || - type_eqv_(a, b)); + jl_types_equal(a, b)); } -static int jl_type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant); +static int type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant); -jl_datatype_t *jl_fix_vararg_bound(jl_datatype_t *tt, int nfix) +static jl_datatype_t *jl_fix_vararg_bound(jl_datatype_t *tt, int nfix) { assert(jl_is_va_tuple(tt)); assert(nfix >= 0); jl_svec_t *tp = tt->parameters; size_t ntp = jl_svec_len(tp); - jl_value_t *env[2] = {NULL, NULL}; - JL_GC_PUSH2(&env[0], &env[1]); - env[0] = jl_tparam1(jl_tparam(tt, ntp-1)); - env[1] = jl_box_long(nfix); - jl_datatype_t *ret = (jl_datatype_t*)jl_instantiate_type_with((jl_value_t*)tt, env, 1); + jl_typeenv_t env = { (jl_tvar_t*)jl_tparam1(jl_unwrap_unionall(jl_tparam(tt, ntp-1))), jl_box_long(nfix), NULL }; + JL_GC_PUSH2(&env.var, &env.val); + jl_datatype_t *ret = (jl_datatype_t*)inst_type_w_((jl_value_t*)tt, &env, NULL, 1); JL_GC_POP(); return ret; } +/* +Simplification of varargs tuple types: + JL_TUPLE_FIXED: tuples of known length (e.g., JL_VARARG_NONE or JL_VARARG_INT) + JL_TUPLE_VAR: tuples of unknown length (e.g., JL_VARARG_BOUND or JL_VARARG_UNBOUND) + +In some cases, JL_VARARG_BOUND tuples get described as JL_TUPLE_FIXED, +if the constraints on length are already known. + +lenr = "representation length" (the number of parameters) +lenf = "full length" (including the Vararg length, if known) + +In general, lenf >= lenr-1. The lower bound is achieved only for a Vararg of length 0. +*/ +typedef enum { + JL_TUPLE_FIXED = 0, + JL_TUPLE_VAR = 1 +} jl_tuple_lenkind_t; + +// Set the parameters for a single tuple +// returns lenf, sets kind and lenkind +static size_t data_vararg_params(jl_value_t **data, size_t lenr, jl_vararg_kind_t *kind, jl_tuple_lenkind_t *lenkind) +{ + size_t lenf = lenr; + int i; + if (lenr == 0) { + *kind = JL_VARARG_NONE; + *lenkind = JL_TUPLE_FIXED; + return lenf; + } + *lenkind = JL_TUPLE_VAR; + jl_value_t *last = jl_unwrap_unionall(data[lenr-1]); + *kind = jl_vararg_kind(last); + if (*kind == JL_VARARG_NONE || *kind == JL_VARARG_INT) + *lenkind = JL_TUPLE_FIXED; + if (*kind == JL_VARARG_INT || *kind == JL_VARARG_BOUND) { + jl_value_t *N = jl_tparam1(last); + if (jl_is_long(N)) { + lenf += jl_unbox_long(N)-1; + *lenkind = JL_TUPLE_FIXED; + } + } + return lenf; +} + +static size_t tuple_vararg_params(jl_svec_t *a, jl_vararg_kind_t *kind, jl_tuple_lenkind_t *lenkind) +{ + return data_vararg_params(jl_svec_data(a), jl_svec_len(a), kind, lenkind); +} + static int jl_tuple_morespecific(jl_datatype_t *cdt, jl_datatype_t *pdt, int invariant) { size_t clenr = jl_nparams(cdt); @@ -2869,8 +1281,8 @@ static int jl_tuple_morespecific(jl_datatype_t *cdt, jl_datatype_t *pdt, int inv size_t plenf, clenf; jl_vararg_kind_t ckind, pkind; jl_tuple_lenkind_t clenkind, plenkind; - clenf = tuple_vararg_params(cdt->parameters, NULL, &ckind, &clenkind); - plenf = tuple_vararg_params(pdt->parameters, NULL, &pkind, &plenkind); + clenf = tuple_vararg_params(cdt->parameters, &ckind, &clenkind); + plenf = tuple_vararg_params(pdt->parameters, &pkind, &plenkind); size_t ci=0, pi=0; int cseq=0, pseq=0; int some_morespecific = 0; @@ -2883,17 +1295,17 @@ static int jl_tuple_morespecific(jl_datatype_t *cdt, jl_datatype_t *pdt, int inv if (ci >= clenf && !cseq) return 1; if (pi >= plenf && !pseq) - return some_morespecific; + return 0; if (ci < clenr) { ce = child[ci]; - if (jl_is_vararg_type(ce)) ce = jl_tparam0(ce); + if (jl_is_vararg_type(ce)) ce = jl_unwrap_vararg(ce); } if (pi < plenr) { pe = parent[pi]; - if (jl_is_vararg_type(pe)) pe = jl_tparam0(pe); + if (jl_is_vararg_type(pe)) pe = jl_unwrap_vararg(pe); } - if (!jl_type_morespecific_(ce, pe, invariant)) { + if (!type_morespecific_(ce, pe, invariant)) { if (type_eqv_with_ANY(ce,pe)) { if (ci==clenf-1 && pi==plenf-1) { if (!cseq && pseq) @@ -2941,24 +1353,21 @@ static int jl_tuple_morespecific(jl_datatype_t *cdt, jl_datatype_t *pdt, int inv static int partially_morespecific(jl_value_t *a, jl_value_t *b, int invariant) { if (jl_is_uniontype(b)) { - jl_svec_t *bp = ((jl_uniontype_t*)b)->types; - size_t i, l=jl_svec_len(bp); - for(i=0; i < l; i++) { - jl_value_t *bi = jl_svecref(bp,i); - if (jl_type_morespecific_(a, bi, invariant) && - !jl_type_morespecific_(bi, a, invariant)) { - return 1; - } - } + jl_uniontype_t *u = (jl_uniontype_t*)b; + if ((type_morespecific_(a, u->a, invariant) && + !type_morespecific_(u->a, a, invariant)) || + (type_morespecific_(a, u->b, invariant) && + !type_morespecific_(u->b, a, invariant))) + return 1; return 0; } - return jl_type_morespecific_(a, b, invariant); + return type_morespecific_(a, b, invariant); } -static int jl_type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant) +static int type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant) { - if (jl_is_typector(a)) a = (jl_value_t*)((jl_typector_t*)a)->body; - if (jl_is_typector(b)) b = (jl_value_t*)((jl_typector_t*)b)->body; + while (jl_is_unionall(a)) a = (jl_value_t*)((jl_unionall_t*)a)->body; + while (jl_is_unionall(b)) b = (jl_value_t*)((jl_unionall_t*)b)->body; if (a == b) { // TODO; maybe change this return 1; @@ -2971,27 +1380,27 @@ static int jl_type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant) } if (jl_is_uniontype(a)) { - jl_svec_t *ap = ((jl_uniontype_t*)a)->types; - size_t l_ap = jl_svec_len(ap); - if (jl_subtype_le(b, a, 0, 0)) { + if (jl_subtype(b, a)) { // fixes issue #4413 - if (!jl_subtype_le(a, b, 0, invariant)) + if (!jl_subtype(a, b)) return 0; } - else if (jl_subtype_le(a, b, 0, invariant)) { + else if (jl_subtype(a, b)) { return 1; } // Union a is more specific than b if some element of a is // more specific than b, and b is not more specific than any // element of a. - for(i=0; i < l_ap; i++) { - jl_value_t *ai = jl_svecref(ap,i); - if (partially_morespecific(ai, b, invariant) && - !jl_type_morespecific_(b, ai, invariant)) { - if (partially_morespecific(b, a, invariant)) - return 0; - return 1; - } + jl_uniontype_t *u = (jl_uniontype_t*)a; + if (partially_morespecific(u->a, b, invariant) && !type_morespecific_(b, u->a, invariant)) { + if (partially_morespecific(b, a, invariant)) + return 0; + return 1; + } + if (partially_morespecific(u->b, b, invariant) && !type_morespecific_(b, u->b, invariant)) { + if (partially_morespecific(b, a, invariant)) + return 0; + return 1; } return 0; } @@ -3000,13 +1409,13 @@ static int jl_type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant) jl_value_t *tp0a = jl_tparam0(a); if (jl_is_typevar(tp0a)) { jl_value_t *ub = ((jl_tvar_t*)tp0a)->ub; - if (jl_subtype_le(ub, b, 1, 0) && - !jl_subtype_le((jl_value_t*)jl_any_type, ub, 0, 0)) { + if (jl_subtype(ub, b) && + !jl_subtype((jl_value_t*)jl_any_type, ub)) { return 1; } } else { - if (jl_subtype_le(tp0a, b, 1, 0)) + if (jl_subtype(tp0a, b)) return 1; } } @@ -3014,11 +1423,9 @@ static int jl_type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant) if (jl_is_uniontype(b)) { if (invariant) return 0; - jl_svec_t *bp = ((jl_uniontype_t*)b)->types; - for(i=0; i < jl_svec_len(bp); i++) { - if (jl_type_morespecific_(a, jl_svecref(bp,i), invariant)) - return 1; - } + jl_uniontype_t *u = (jl_uniontype_t*)b; + if (type_morespecific_(a, u->a, invariant) || type_morespecific_(a, u->b, invariant)) + return 1; return 0; } @@ -3032,18 +1439,18 @@ static int jl_type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant) while (tta != (jl_datatype_t*)jl_any_type) { if (tta->name == ttb->name) { if (super) { - if (tta->name != jl_type_type->name) + if (tta->name != jl_type_typename) return 1; } - if (super && ttb->name == jl_type_type->name && jl_is_typevar(jl_tparam0(b))) { - if (jl_type_morespecific_(a, jl_tparam0(b), 1)) + if (super && ttb->name == jl_type_typename && jl_is_typevar(jl_tparam0(b))) { + if (type_morespecific_(a, jl_tparam0(b), 1)) return 1; } assert(jl_nparams(tta) == jl_nparams(ttb)); for(i=0; i < jl_nparams(tta); i++) { jl_value_t *apara = jl_tparam(tta,i); jl_value_t *bpara = jl_tparam(ttb,i); - if (!jl_type_morespecific_(apara, bpara, 1)) + if (!type_morespecific_(apara, bpara, 1)) return 0; } return 1; @@ -3058,69 +1465,28 @@ static int jl_type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant) if (jl_is_typevar(a)) { if (jl_is_typevar(b)) { - return - jl_type_morespecific_((jl_value_t*)((jl_tvar_t*)a)->ub, + return type_morespecific_((jl_value_t*)((jl_tvar_t*)a)->ub, (jl_value_t*)((jl_tvar_t*)b)->ub, 0) && - jl_type_morespecific_((jl_value_t*)((jl_tvar_t*)b)->lb, - (jl_value_t*)((jl_tvar_t*)a)->lb, 0); + type_morespecific_((jl_value_t*)((jl_tvar_t*)b)->lb, + (jl_value_t*)((jl_tvar_t*)a)->lb, 0); } if (invariant) return 0; - return jl_subtype_le((jl_value_t*)((jl_tvar_t*)a)->ub, b, 0, 0); + return jl_subtype((jl_value_t*)((jl_tvar_t*)a)->ub, b); } if (jl_is_typevar(b)) { - return jl_subtype_le(a, (jl_value_t*)((jl_tvar_t*)b)->ub, 0, 0) && - jl_subtype_le((jl_value_t*)((jl_tvar_t*)b)->lb, a, 0, 0); + return jl_subtype(a, (jl_value_t*)((jl_tvar_t*)b)->ub) && + jl_subtype((jl_value_t*)((jl_tvar_t*)b)->lb, a); } if ((jl_datatype_t*)a == jl_any_type) return 0; return 0; } -JL_DLLEXPORT int jl_type_morespecific(jl_value_t *a, jl_value_t *b) -{ - return jl_type_morespecific_(a, b, 0); -} - -int jl_args_morespecific_(jl_value_t *a, jl_value_t *b) -{ - int msp = jl_type_morespecific(a,b); - int btv = jl_has_typevars(b); - if (btv) { - if (jl_type_match_morespecific(a,b) == (jl_value_t*)jl_false) { - if (jl_has_typevars(a)) - return 0; - return msp; - } - if (jl_has_typevars(a)) { - type_match_invariance_mask = 0; - //int result = jl_type_match_morespecific(b,a) == (jl_value_t*)jl_false); - // this rule seems to work better: - int result = jl_type_match(b,a) == (jl_value_t*)jl_false; - type_match_invariance_mask = 1; - if (result) - return 1; - } - int nmsp = jl_type_morespecific(b,a); - if (nmsp == msp) - return 0; - } - if (jl_has_typevars((jl_value_t*)a)) { - int nmsp = jl_type_morespecific(b,a); - if (nmsp && msp) - return 1; - if (!btv && jl_types_equal(a,b)) - return 1; - if (jl_type_match_morespecific(b,a) != (jl_value_t*)jl_false) - return 0; - } - return msp; -} - // Called when a is a bound-vararg and b is not a vararg. Sets the // vararg length in a to match b, as long as this makes some earlier // argument more specific. -int jl_args_morespecific_fix1(jl_value_t *a, jl_value_t *b, int swap) +static int args_morespecific_fix1(jl_value_t *a, jl_value_t *b, int swap) { jl_datatype_t *tta = (jl_datatype_t*)a; jl_datatype_t *ttb = (jl_datatype_t*)b; @@ -3136,371 +1502,48 @@ int jl_args_morespecific_fix1(jl_value_t *a, jl_value_t *b, int swap) if (changed) { JL_GC_PUSH1(&newtta); int ret; - if (type_eqv_(b, (jl_value_t*)newtta)) + if (jl_types_equal(b, (jl_value_t*)newtta)) ret = swap; else if (swap) - ret = jl_args_morespecific_(b, (jl_value_t*)newtta); + ret = type_morespecific_(b, (jl_value_t*)newtta, 0); else - ret = jl_args_morespecific_((jl_value_t*)newtta, b); + ret = type_morespecific_((jl_value_t*)newtta, b, 0); JL_GC_POP(); return ret; } if (swap) - return jl_args_morespecific_(b, a); - return jl_args_morespecific_(a, b); + return type_morespecific_(b, a, 0); + return type_morespecific_(a, b, 0); } -JL_DLLEXPORT int jl_args_morespecific(jl_value_t *a, jl_value_t *b) +JL_DLLEXPORT int jl_type_morespecific(jl_value_t *a, jl_value_t *b) { + if (jl_subtype(a, b)) + return 1; + if (jl_subtype(b, a)) + return 0; if (jl_is_tuple_type(a) && jl_is_tuple_type(b)) { jl_datatype_t *tta = (jl_datatype_t*)a; jl_datatype_t *ttb = (jl_datatype_t*)b; size_t alenf, blenf; jl_vararg_kind_t akind, bkind; jl_tuple_lenkind_t alenkind, blenkind; - alenf = tuple_vararg_params(tta->parameters, NULL, &akind, &alenkind); - blenf = tuple_vararg_params(ttb->parameters, NULL, &bkind, &blenkind); + alenf = tuple_vararg_params(tta->parameters, &akind, &alenkind); + blenf = tuple_vararg_params(ttb->parameters, &bkind, &blenkind); // When one is JL_VARARG_BOUND and the other has fixed length, // allow the argument length to fix the tvar if (akind == JL_VARARG_BOUND && blenkind == JL_TUPLE_FIXED && blenf >= alenf) { - return jl_args_morespecific_fix1(a, b, 0); + return args_morespecific_fix1(a, b, 0); } if (bkind == JL_VARARG_BOUND && alenkind == JL_TUPLE_FIXED && alenf >= blenf) { - return jl_args_morespecific_fix1(b, a, 1); - } - } - return jl_args_morespecific_(a, b); -} - -// ---------------------------------------------------------------------------- - -int type_match_invariance_mask = 1; - -static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent, - cenv_t *env, int morespecific, int invariant); - -static jl_value_t *tuple_match(jl_datatype_t *child, jl_datatype_t *parent, - cenv_t *env, int morespecific, int invariant) -{ - size_t ci=0, pi=0; - size_t clenr = jl_nparams(child); - size_t plenr = jl_nparams(parent); - size_t plenf, clenf; - jl_vararg_kind_t ckind, pkind; - jl_tuple_lenkind_t clenkind, plenkind; - clenf = tuple_vararg_params(child->parameters, NULL, &ckind, &clenkind); - plenf = tuple_vararg_params(parent->parameters, NULL, &pkind, &plenkind); - int cseq=0, pseq=0; - jl_value_t *ce=NULL, *pe=NULL, *cn=NULL, *pn=NULL; - int mode = 0; - invariant = invariant & type_match_invariance_mask; - while(1) { - if (!cseq) - cseq = (ci= clenf && !cseq) - return (mode || pi>=plenf || (pseq && !invariant)) ? jl_true : jl_false; - if (pi >= plenf && !pseq) - return mode ? jl_true : jl_false; - if (ci < clenr) { - ce = jl_tparam(child,ci); - if (jl_is_vararg_type(ce)) { - cn = jl_tparam1(ce); - ce = jl_tparam0(ce); - } - } - if (pi < plenr) { - pe = jl_tparam(parent,pi); - if (jl_is_vararg_type(pe)) { - pn = jl_tparam1(pe); - pe = jl_tparam0(pe); - } - } - - int n = env->n; - if (type_match_(ce, pe, env, morespecific, invariant) == jl_false) { - env->n = n; - if (jl_types_equal_generic(ce,pe,1)) { - if (ci==clenf-1 && pi==plenf-1 && !cseq && pseq) { - return jl_true; - } - if (!mode) return jl_false; - } - else { - return jl_false; - } - } - // Match the number parameter in Vararg, too - if (cseq && pseq) { - n = env->n; - if (type_match_(cn, pn, env, morespecific, invariant) == jl_false) { - env->n = n; - return jl_false; - } - } - - if (mode && cseq && !pseq) - return jl_true; - - if (morespecific) { - if (!(jl_types_equal_generic(ce,pe,1) || - (jl_is_typevar(pe) && - jl_types_equal(ce,((jl_tvar_t*)pe)->ub)))) { - mode = 1; - } - } - - if (cseq && pseq) return jl_true; - ci++; - pi++; - } - return jl_false; -} - -static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent, - cenv_t *env, int morespecific, int invariant) -{ - jl_value_t *tmp, *tmp2; - invariant = invariant & type_match_invariance_mask; - if (jl_is_typector(child)) - child = (jl_value_t*)((jl_typector_t*)child)->body; - if (jl_is_typector(parent)) - parent = (jl_value_t*)((jl_typector_t*)parent)->body; - size_t i, j; - if (match_intersection_mode && jl_is_typevar(child) && !jl_is_typevar(parent)) { - tmp = child; - child = parent; - parent = tmp; - } - if (jl_is_typevar(parent)) { - // make sure type is within this typevar's bounds - if (morespecific) { - if (!jl_type_morespecific_(child, parent, 0)) - return jl_false; - } - else { - if (!jl_subtype_le(child, parent, 0, 0)) - return jl_false; - } - if (!match_intersection_mode) { - if (!((jl_tvar_t*)parent)->bound) return jl_true; - } - for(int i=0; i < env->n; i+=2) { - if (env->data[i] == (jl_value_t*)parent) { - jl_value_t *pv = env->data[i+1]; - if (jl_is_typevar(pv) && jl_is_typevar(child)) { - if (pv == (jl_value_t*)child) - return jl_true; - return jl_false; - } - if (morespecific) { - if (jl_type_morespecific_(child, pv, 0)) { - return jl_true; - } - else if (!jl_is_typevar(child) && !jl_type_morespecific_(pv, child, 0)) { - return jl_true; - } - else if (jl_subtype(pv, child, 0)) { - env->data[i+1] = (jl_value_t*)child; - return jl_true; - } - } - else { - if (type_eqv_(child, pv)) - return jl_true; - } - return jl_false; - } - } - extend(parent, child, env); - return jl_true; - } - - if (child == parent) return jl_true; - - if (jl_is_typevar(child)) { - if (!invariant || morespecific) { - if (morespecific) { - if (jl_type_morespecific_(child, parent, 0)) - return jl_true; - } - else { - if (jl_subtype_le(child, parent, 0, 0)) - return jl_true; - } - } - return jl_false; - } - if (!invariant && parent == (jl_value_t*)jl_any_type) - return jl_true; - if (child == (jl_value_t*)jl_any_type) return jl_false; - - if (jl_is_uniontype(child)) { - jl_svec_t *t = ((jl_uniontype_t*)child)->types; - if (morespecific) { - jl_value_t **rts; - JL_GC_PUSHARGS(rts, MAX_CENV_SIZE); - cenv_t tenv; tenv.data = rts; - for(i=0; i < jl_svec_len(t); i++) { - int n = env->n; - tmp = type_match_(jl_svecref(t,i), parent, env, 1, invariant); - if (tmp != jl_false) { - tenv.n = 0; - tmp2 = type_match_(parent, jl_svecref(t,i), &tenv, 1, invariant); - if (tmp2 == jl_false) { - n = env->n; - for(j=0; j < jl_svec_len(t); j++) { - tenv.n = 0; - env->n = n; - if (type_match_(parent, jl_svecref(t,j), - &tenv, 1, invariant) != jl_false && - type_match_(jl_svecref(t,j), parent, - env, 1, invariant) == jl_false) { - env->n = n; - JL_GC_POP(); - return jl_false; - } - } - JL_GC_POP(); - return jl_true; - } - } - else { - env->n = n; - } - } - JL_GC_POP(); - return jl_false; - } - else { - for(i=0; i < jl_svec_len(t); i++) { - int n = env->n; - if (type_match_(jl_svecref(t,i), parent, env, morespecific, - invariant) == jl_false) - { env->n = n; return jl_false; } - } - if (invariant && child == (jl_value_t*)jl_bottom_type && - !jl_is_typevar(parent)) - return jl_false; - } - return jl_true; - } - if (jl_is_uniontype(parent)) { - jl_svec_t *t = ((jl_uniontype_t*)parent)->types; - int n = env->n; - for(i=0; i < jl_svec_len(t); i++) { - env->n = n; - if (type_match_(child, jl_svecref(t,i), env, - morespecific, invariant) != jl_false) - return jl_true; - } - return jl_false; - } - - if (jl_is_tuple_type(child)) { - if (jl_is_tuple_type(parent)) { - return tuple_match((jl_datatype_t*)child, (jl_datatype_t*)parent, env, - morespecific, invariant); - } - return jl_false; - } - if (jl_is_tuple_type(parent)) { - return jl_false; - } - - if (!jl_is_datatype(child) || !jl_is_datatype(parent)) { - return jl_egal(child,parent) ? jl_true : jl_false; - } - jl_datatype_t *tta = (jl_datatype_t*)child; - jl_datatype_t *ttb = (jl_datatype_t*)parent; - int super = 0; - while (tta != (jl_datatype_t*)jl_any_type) { - if (tta->name == ttb->name) { - // note: DataType <: Type, but Type{T} <: DataType - // for any specific T. - if (super && morespecific && tta->name != jl_type_type->name) - return jl_true; - assert(jl_nparams(tta) == jl_nparams(ttb)); - for(i=0; i < jl_nparams(tta); i++) { - int n = env->n; - if (type_match_(jl_tparam(tta,i), jl_tparam(ttb,i), - env, morespecific, 1) == jl_false) - { env->n = n; return jl_false; } - } - return jl_true; - } - else if (invariant) { - return jl_false; - } - tta = tta->super; super = 1; - } - assert(!invariant); - if (((jl_datatype_t*)child)->name == jl_type_type->name && - ttb->name != jl_type_type->name) { - // Type{T} also matches >:typeof(T) - return type_match_(jl_typeof(jl_tparam0(child)), - parent, env, morespecific, 0); - } - return jl_false; -} - -/* - typically a is a concrete type and b is a type containing typevars. - this function tries to find a typevar assignment such that "a" is a subtype - of "b". - returns a tuple of (typevar,type,...) pairs. - used to infer static parameter values in generic method definitions. -*/ -jl_value_t *jl_type_match_(jl_value_t *a, jl_value_t *b, int morespecific) -{ - jl_value_t **rts; - JL_GC_PUSHARGS(rts, MAX_CENV_SIZE); - cenv_t env; env.n = 0; env.data = rts; - jl_value_t *m = type_match_(a, b, &env, morespecific, 0); - if (m != jl_false) { - m = (jl_value_t*)jl_alloc_svec_uninit(env.n); - for(int i=0; i < env.n; i++) { - jl_svecset(m, i, env.data[i]); + return args_morespecific_fix1(b, a, 1); } } - JL_GC_POP(); - return m; -} - -jl_value_t *jl_type_match(jl_value_t *a, jl_value_t *b) -{ - return jl_type_match_(a, b, 0); -} - -jl_value_t *jl_type_match_morespecific(jl_value_t *a, jl_value_t *b) -{ - return jl_type_match_(a, b, 1); + return type_morespecific_(a, b, 0); } // initialization ------------------------------------------------------------- -JL_DLLEXPORT jl_tvar_t *jl_new_typevar_(jl_sym_t *name, jl_value_t *lb, - jl_value_t *ub, jl_value_t *b) -{ - jl_ptls_t ptls = jl_get_ptls_states(); - jl_tvar_t *tv = (jl_tvar_t*)jl_gc_alloc(ptls, sizeof(jl_tvar_t), - jl_tvar_type); - tv->name = name; - tv->lb = lb; - tv->ub = ub; - tv->bound = (b != jl_false); - return tv; -} - -JL_DLLEXPORT jl_tvar_t *jl_new_typevar(jl_sym_t *name, jl_value_t *lb, - jl_value_t *ub) -{ - return jl_new_typevar_(name, lb, ub, jl_false); -} - static jl_tvar_t *tvar(const char *name) { return jl_new_typevar(jl_symbol(name), (jl_value_t*)jl_bottom_type, @@ -3531,18 +1574,19 @@ void jl_init_types(void) jl_simplevector_type); jl_svec_set_len_unsafe(jl_emptysvec, 0); - jl_any_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Any"), NULL, jl_emptysvec); + jl_any_type = (jl_datatype_t*)jl_new_abstracttype((jl_value_t*)jl_symbol("Any"), NULL, jl_emptysvec); jl_any_type->super = jl_any_type; - jl_type_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Type"), jl_any_type, jl_emptysvec); - jl_type_type_mt = jl_new_method_table(jl_type_type->name->name, ptls->current_module); - jl_type_type->name->mt = jl_type_type_mt; + jl_type_type = (jl_unionall_t*)jl_new_abstracttype((jl_value_t*)jl_symbol("Type"), jl_any_type, jl_emptysvec); + jl_type_typename = ((jl_datatype_t*)jl_type_type)->name; + jl_type_type_mt = jl_new_method_table(jl_type_typename->name, ptls->current_module); + jl_type_typename->mt = jl_type_type_mt; // initialize them. lots of cycles. jl_datatype_type->name = jl_new_typename(jl_symbol("DataType")); - jl_datatype_type->name->primary = (jl_value_t*)jl_datatype_type; - jl_datatype_type->super = jl_type_type; + jl_datatype_type->name->wrapper = (jl_value_t*)jl_datatype_type; + jl_datatype_type->super = (jl_datatype_t*)jl_type_type; jl_datatype_type->parameters = jl_emptysvec; - jl_datatype_type->name->names = jl_svec(17, + jl_datatype_type->name->names = jl_svec(16, jl_symbol("name"), jl_symbol("super"), jl_symbol("parameters"), @@ -3557,10 +1601,9 @@ void jl_init_types(void) jl_symbol("llvm::StructType"), jl_symbol("llvm::DIType"), jl_symbol("depth"), - jl_symbol("hastypevars"), - jl_symbol("haswildcard"), + jl_symbol("hasfreetypevars"), jl_symbol("isleaftype")); - jl_datatype_type->types = jl_svec(17, + jl_datatype_type->types = jl_svec(16, jl_typename_type, jl_type_type, jl_simplevector_type, @@ -3568,7 +1611,7 @@ void jl_init_types(void) jl_any_type, // instance jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_any_type, - jl_any_type, jl_any_type, jl_any_type, jl_any_type); + jl_any_type, jl_any_type, jl_any_type); jl_datatype_type->instance = NULL; jl_datatype_type->uid = jl_assign_type_uid(); jl_datatype_type->struct_decl = NULL; @@ -3580,12 +1623,12 @@ void jl_init_types(void) jl_datatype_type->ninitialized = 4; jl_typename_type->name = jl_new_typename(jl_symbol("TypeName")); - jl_typename_type->name->primary = (jl_value_t*)jl_typename_type; + jl_typename_type->name->wrapper = (jl_value_t*)jl_typename_type; jl_typename_type->name->mt = jl_new_method_table(jl_typename_type->name->name, ptls->current_module); jl_typename_type->super = jl_any_type; jl_typename_type->parameters = jl_emptysvec; jl_typename_type->name->names = jl_svec(8, jl_symbol("name"), jl_symbol("module"), - jl_symbol("names"), jl_symbol("primary"), + jl_symbol("names"), jl_symbol("wrapper"), jl_symbol("cache"), jl_symbol("linearcache"), jl_symbol("hash"), jl_symbol("mt")); jl_typename_type->types = jl_svec(8, jl_sym_type, jl_any_type, jl_simplevector_type, @@ -3600,7 +1643,7 @@ void jl_init_types(void) jl_typename_type->ninitialized = 2; jl_methtable_type->name = jl_new_typename(jl_symbol("MethodTable")); - jl_methtable_type->name->primary = (jl_value_t*)jl_methtable_type; + jl_methtable_type->name->wrapper = (jl_value_t*)jl_methtable_type; jl_methtable_type->name->mt = jl_new_method_table(jl_methtable_type->name->name, ptls->current_module); jl_methtable_type->super = jl_any_type; jl_methtable_type->parameters = jl_emptysvec; @@ -3620,7 +1663,7 @@ void jl_init_types(void) jl_methtable_type->ninitialized = 4; jl_sym_type->name = jl_new_typename(jl_symbol("Symbol")); - jl_sym_type->name->primary = (jl_value_t*)jl_sym_type; + jl_sym_type->name->wrapper = (jl_value_t*)jl_sym_type; jl_sym_type->name->mt = jl_new_method_table(jl_sym_type->name->name, ptls->current_module); jl_sym_type->super = jl_any_type; jl_sym_type->parameters = jl_emptysvec; @@ -3636,7 +1679,7 @@ void jl_init_types(void) jl_sym_type->ninitialized = 0; jl_simplevector_type->name = jl_new_typename(jl_symbol("SimpleVector")); - jl_simplevector_type->name->primary = (jl_value_t*)jl_simplevector_type; + jl_simplevector_type->name->wrapper = (jl_value_t*)jl_simplevector_type; jl_simplevector_type->name->mt = jl_new_method_table(jl_simplevector_type->name->name, ptls->current_module); jl_simplevector_type->super = jl_any_type; jl_simplevector_type->parameters = jl_emptysvec; @@ -3656,43 +1699,50 @@ void jl_init_types(void) jl_set_typeof(jl_nothing, jl_void_type); jl_void_type->instance = jl_nothing; - jl_uniontype_type = jl_new_datatype(jl_symbol("Union"), - jl_type_type, jl_emptysvec, - jl_svec(1, jl_symbol("types")), - jl_svec(1, jl_simplevector_type), - 0, 0, 1); - - jl_bottom_type = (jl_value_t*)jl_new_struct(jl_uniontype_type, jl_emptysvec); - - jl_tvar_type = jl_new_datatype(jl_symbol("TypeVar"), - jl_any_type, jl_emptysvec, - jl_svec(4, jl_symbol("name"), - jl_symbol("lb"), jl_symbol("ub"), - jl_symbol("bound")), - jl_svec(4, jl_sym_type, jl_type_type, - jl_type_type, jl_any_type), + jl_datatype_t *type_type = (jl_datatype_t*)jl_type_type; + jl_bottomtype_type = jl_new_datatype(jl_symbol("BottomType"), type_type, jl_emptysvec, + jl_emptysvec, jl_emptysvec, 0, 0, 0); + jl_bottom_type = jl_new_struct(jl_bottomtype_type); + jl_bottomtype_type->instance = jl_bottom_type; + + jl_uniontype_type = jl_new_datatype(jl_symbol("Union"), type_type, jl_emptysvec, + jl_svec(2, jl_symbol("a"), jl_symbol("b")), + jl_svec(2, jl_any_type, jl_any_type), + 0, 0, 2); + + jl_tvar_type = jl_new_datatype(jl_symbol("TypeVar"), jl_any_type, jl_emptysvec, + jl_svec(3, jl_symbol("name"), + jl_symbol("lb"), jl_symbol("ub")), + jl_svec(3, jl_sym_type, + jl_any_type, jl_any_type), 0, 1, 3); + jl_unionall_type = jl_new_datatype(jl_symbol("UnionAll"), type_type, jl_emptysvec, + jl_svec(2, jl_symbol("var"), jl_symbol("body")), + jl_svec(2, jl_tvar_type, jl_any_type), + 0, 0, 2); + vararg_sym = jl_symbol("Vararg"); jl_svec_t *tv; tv = jl_svec2(tvar("T"),tvar("N")); - jl_vararg_type = jl_new_abstracttype((jl_value_t*)vararg_sym, jl_any_type, tv); + jl_vararg_type = (jl_unionall_t*)jl_new_abstracttype((jl_value_t*)vararg_sym, jl_any_type, tv)->name->wrapper; + jl_vararg_typename = ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_vararg_type))->name; jl_anytuple_type = jl_new_datatype(jl_symbol("Tuple"), jl_any_type, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0); jl_tuple_typename = jl_anytuple_type->name; jl_anytuple_type->uid = 0; jl_anytuple_type->parameters = jl_svec(1, jl_wrap_vararg((jl_value_t*)jl_any_type, (jl_value_t*)NULL)); - //jl_anytuple_type->parameters = jl_svec(1, jl_wrap_vararg((jl_value_t*)NULL, (jl_value_t*)NULL)); jl_anytuple_type->types = jl_anytuple_type->parameters; jl_anytuple_type->layout = NULL; - jl_anytuple_type->hastypevars = 1; - jl_anytuple_type->haswildcard = 1; + jl_anytuple_type->hasfreetypevars = 0; jl_anytuple_type->isleaftype = 0; - jl_tvar_t *tttvar = jl_new_typevar(jl_symbol("T"), - (jl_value_t*)jl_bottom_type,(jl_value_t*)jl_any_type); - jl_type_type->parameters = jl_svec(1, tttvar); + jl_tvar_t *tttvar = tvar("T"); + ((jl_datatype_t*)jl_type_type)->parameters = jl_svec(1, tttvar); + ((jl_datatype_t*)jl_type_type)->hasfreetypevars = 1; + jl_type_typename->wrapper = (jl_value_t*)jl_new_unionall_type(tttvar, (jl_value_t*)jl_type_type); + jl_type_type = (jl_unionall_t*)jl_type_typename->wrapper; jl_tupletype_t *empty_tuple_type = jl_apply_tuple_type(jl_emptysvec); empty_tuple_type->uid = jl_assign_type_uid(); @@ -3786,40 +1836,32 @@ void jl_init_types(void) jl_builtin_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Builtin"), jl_function_type, jl_emptysvec); tv = jl_svec2(tvar("T"), tvar("N")); - jl_abstractarray_type = + jl_abstractarray_type = (jl_unionall_t*) jl_new_abstracttype((jl_value_t*)jl_symbol("AbstractArray"), - jl_any_type, tv); + jl_any_type, tv)->name->wrapper; tv = jl_svec2(tvar("T"), tvar("N")); - jl_densearray_type = + jl_densearray_type = (jl_unionall_t*) jl_new_abstracttype((jl_value_t*)jl_symbol("DenseArray"), - (jl_datatype_t*)jl_apply_type((jl_value_t*)jl_abstractarray_type, tv), - tv); + (jl_datatype_t*)jl_apply_type((jl_value_t*)jl_abstractarray_type, jl_svec_data(tv), 2), + tv)->name->wrapper; tv = jl_svec2(tvar("T"), tvar("N")); - jl_array_type = + jl_array_type = (jl_unionall_t*) jl_new_datatype(jl_symbol("Array"), (jl_datatype_t*) - jl_apply_type((jl_value_t*)jl_densearray_type, tv), + jl_apply_type((jl_value_t*)jl_densearray_type, jl_svec_data(tv), 2), tv, - jl_emptysvec, jl_emptysvec, 0, 1, 0); - jl_array_typename = jl_array_type->name; - jl_array_type->ninitialized = 0; + jl_emptysvec, jl_emptysvec, 0, 1, 0)->name->wrapper; + jl_array_typename = ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_array_type))->name; static const jl_datatype_layout_t _jl_array_layout = { 0, sizeof(void*), 0, 0, 0 }; - jl_array_type->layout = &_jl_array_layout; + ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_array_type))->layout = &_jl_array_layout; - jl_array_any_type = - (jl_value_t*)jl_apply_type((jl_value_t*)jl_array_type, - jl_svec(2, jl_any_type, - jl_box_long(1))); + jl_array_any_type = jl_apply_type2((jl_value_t*)jl_array_type, (jl_value_t*)jl_any_type, jl_box_long(1)); - jl_array_symbol_type = - (jl_value_t*)jl_apply_type((jl_value_t*)jl_array_type, - jl_svec(2, jl_sym_type, - jl_box_long(1))); + jl_array_symbol_type = jl_apply_type2((jl_value_t*)jl_array_type, (jl_value_t*)jl_sym_type, jl_box_long(1)); - jl_array_uint8_type = jl_apply_type((jl_value_t*)jl_array_type, - jl_svec2(jl_uint8_type, jl_box_long(1))); + jl_array_uint8_type = jl_apply_type2((jl_value_t*)jl_array_type, (jl_value_t*)jl_uint8_type, jl_box_long(1)); jl_expr_type = jl_new_datatype(jl_symbol("Expr"), @@ -3976,36 +2018,34 @@ void jl_init_types(void) jl_any_type, jl_any_type), // void*, void* 0, 1, 3); - jl_typector_type = - jl_new_datatype(jl_symbol("TypeConstructor"), - jl_type_type, jl_emptysvec, - jl_svec(2, jl_symbol("parameters"), - jl_symbol("body")), - jl_svec(2, jl_simplevector_type, jl_any_type), - 0, 0, 2); - // all kinds of types share a method table - jl_typector_type->name->mt = jl_uniontype_type->name->mt = jl_datatype_type->name->mt = - jl_type_type->name->mt; + jl_unionall_type->name->mt = jl_uniontype_type->name->mt = jl_datatype_type->name->mt = + jl_type_typename->mt; jl_intrinsic_type = jl_new_bitstype((jl_value_t*)jl_symbol("IntrinsicFunction"), jl_builtin_type, jl_emptysvec, 32); tv = jl_svec1(tvar("T")); - jl_ref_type = - jl_new_abstracttype((jl_value_t*)jl_symbol("Ref"), jl_any_type, tv); + jl_ref_type = (jl_unionall_t*) + jl_new_abstracttype((jl_value_t*)jl_symbol("Ref"), jl_any_type, tv)->name->wrapper; tv = jl_svec1(tvar("T")); - jl_pointer_type = + jl_pointer_type = (jl_unionall_t*) jl_new_bitstype((jl_value_t*)jl_symbol("Ptr"), - (jl_datatype_t*)jl_apply_type((jl_value_t*)jl_ref_type, tv), tv, - sizeof(void*)*8); + (jl_datatype_t*)jl_apply_type((jl_value_t*)jl_ref_type, jl_svec_data(tv), 1), tv, + sizeof(void*)*8)->name->wrapper; + jl_pointer_typename = ((jl_datatype_t*)jl_unwrap_unionall(jl_pointer_type))->name; + + // U T<:Tuple Type{T} + tttvar = jl_new_typevar(jl_symbol("T"), + (jl_value_t*)jl_bottom_type, + (jl_value_t*)jl_anytuple_type); + jl_anytuple_type_type = jl_new_unionall_type(tttvar, (jl_value_t*)jl_wrap_Type((jl_value_t*)tttvar)); // Type{T} - jl_typetype_tvar = jl_new_typevar(jl_symbol("T"), - (jl_value_t*)jl_bottom_type,(jl_value_t*)jl_any_type); - jl_typetype_type = (jl_datatype_t*)jl_apply_type((jl_value_t*)jl_type_type, - jl_svec1(jl_typetype_tvar)); + jl_typetype_tvar = tvar("T"); + jl_typetype_type = jl_new_unionall_type(jl_typetype_tvar, + jl_apply_type1((jl_value_t*)jl_type_type, (jl_value_t*)jl_typetype_tvar)); jl_ANY_flag = (jl_value_t*)tvar("ANY"); @@ -4015,8 +2055,7 @@ void jl_init_types(void) 0, 1, 1); // complete builtin type metadata - jl_value_t *pointer_void = jl_apply_type((jl_value_t*)jl_pointer_type, - jl_svec1(jl_void_type)); + jl_value_t *pointer_void = jl_apply_type1((jl_value_t*)jl_pointer_type, (jl_value_t*)jl_void_type); jl_voidpointer_type = (jl_datatype_t*)pointer_void; jl_svecset(jl_datatype_type->types, 5, jl_voidpointer_type); jl_svecset(jl_datatype_type->types, 6, jl_int32_type); @@ -4029,8 +2068,6 @@ void jl_init_types(void) jl_svecset(jl_datatype_type->types, 13, jl_int32_type); jl_svecset(jl_datatype_type->types, 14, jl_bool_type); jl_svecset(jl_datatype_type->types, 15, jl_bool_type); - jl_svecset(jl_datatype_type->types, 16, jl_bool_type); - jl_svecset(jl_tvar_type->types, 3, jl_bool_type); jl_svecset(jl_simplevector_type->types, 0, jl_long_type); jl_svecset(jl_typename_type->types, 1, jl_module_type); jl_svecset(jl_typename_type->types, 6, jl_long_type); @@ -4062,7 +2099,7 @@ void jl_init_types(void) jl_compute_field_offsets(jl_quotenode_type); jl_compute_field_offsets(jl_module_type); jl_compute_field_offsets(jl_method_instance_type); - jl_compute_field_offsets(jl_typector_type); + jl_compute_field_offsets(jl_unionall_type); jl_compute_field_offsets(jl_simplevector_type); jl_compute_field_offsets(jl_sym_type); @@ -4128,10 +2165,6 @@ void jl_init_types(void) inline_sym = jl_symbol("inline"); propagate_inbounds_sym = jl_symbol("propagate_inbounds"); - tttvar = jl_new_typevar(jl_symbol("T"), - (jl_value_t*)jl_bottom_type, - (jl_value_t*)jl_anytuple_type); - jl_anytuple_type_type = jl_wrap_Type((jl_value_t*)tttvar); jl_cfunction_list.unknown = jl_nothing; } diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 8133036bf67dc..b8c287b1bcb0d 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -187,11 +187,10 @@ ;; convert list of names (sl) and list of upper bounds to expressions that ;; construct TypeVars -(define (symbols->typevars sl upperbounds bnd) - (let ((bnd (if bnd '(true) '()))) - (if (null? upperbounds) - (map (lambda (x) `(call (core TypeVar) ',x ,@bnd)) sl) - (map (lambda (x ub) `(call (core TypeVar) ',x ,ub ,@bnd)) sl upperbounds)))) +(define (symbols->typevars sl upperbounds) + (if (null? upperbounds) + (map (lambda (x) `(call (core TypeVar) ',x)) sl) + (map (lambda (x ub) `(call (core TypeVar) ',x ,ub)) sl upperbounds))) ;; extract type variable name from A<:B expressions (define (sparam-name sp) @@ -230,7 +229,7 @@ (let ((lst '())) (pattern-replace (pattern-set - (pattern-lambda (= v (call (core (-/ TypeVar)) (quote T) y z)) + (pattern-lambda (= v (call (core (-/ TypeVar)) (quote T) ...)) (begin (set! lst (cons T lst)) __))) (butlast (cdr (caddr m)))) (reverse! lst)) @@ -349,7 +348,8 @@ ,body ,isstaged) `(method ,name (block - ,@(map make-assignment temps (symbols->typevars names bounds #t)) + ,@(map (lambda (l r) (make-assignment l (replace-vars r renames))) + temps (symbols->typevars names bounds)) (call (core svec) (call (core svec) ,@(dots->vararg (map (lambda (ty) @@ -822,7 +822,7 @@ (block (global ,name) (const ,name) ,@(map (lambda (v) `(local ,v)) params) - ,@(map make-assignment params (symbols->typevars params bounds #f)) + ,@(map make-assignment params (symbols->typevars params bounds)) (composite_type ,name (call (core svec) ,@params) (call (core svec) ,@(map (lambda (x) `',x) field-names)) ,super (call (core svec) ,@field-types) ,mut ,min-initialized))) @@ -858,7 +858,7 @@ (scope-block (block ,@(map (lambda (v) `(local ,v)) params) - ,@(map make-assignment params (symbols->typevars params bounds #f)) + ,@(map make-assignment params (symbols->typevars params bounds)) (abstract_type ,name (call (core svec) ,@params) ,super)))))) (define (bits-def-expr n name params super) @@ -869,7 +869,7 @@ (scope-block (block ,@(map (lambda (v) `(local ,v)) params) - ,@(map make-assignment params (symbols->typevars params bounds #f)) + ,@(map make-assignment params (symbols->typevars params bounds)) (bits_type ,name (call (core svec) ,@params) ,n ,super)))))) ;; take apart a type signature, e.g. T{X} <: S{Y} @@ -1210,10 +1210,10 @@ ,@(map (lambda (v) `(local ,v)) params) ,@(map (lambda (l r) (make-assignment l (expand-forms r))) params - (symbols->typevars params bounds #f)) - (call (core TypeConstructor) - (call (core svec) ,@params) - ,(expand-forms type-ex)))))))) + (symbols->typevars params bounds)) + ,(foldl (lambda (var type) `(call (core UnionAll) ,var ,type)) + (expand-forms type-ex) + (reverse params)))))))) (expand-forms `(const (= ,(cadr e) ,(caddr e)))))) @@ -2592,7 +2592,7 @@ f(x) = yt(x) (lambda () (() () 0 ()) (body (global ,name) (const ,name) - ,@(map (lambda (p n) `(= ,p (call (core TypeVar) ',n (core Any) false))) P names) + ,@(map (lambda (p n) `(= ,p (call (core TypeVar) ',n (core Any)))) P names) (composite_type ,name (call (core svec) ,@P) (call (core svec) ,@(map (lambda (v) `',v) fields)) ,super @@ -2619,7 +2619,7 @@ f(x) = yt(x) ; (let ((n (length P))) ; `((global ,name) ; (const ,name) -; ,@(map (lambda (p n) `(= ,p (call (core TypeVar) ',n (core Any) false))) P names) +; ,@(map (lambda (p n) `(= ,p (call (core TypeVar) ',n (core Any)))) P names) ; (composite_type ,name (call (core svec) ,@P) ; (call (core svec) ,@(map (lambda (v) `',v) fields)) ; ,super @@ -3016,7 +3016,7 @@ f(x) = yt(x) (fix-function-arg-type sig type-name iskw namemap closure-param-syms) renamemap))) (append (map (lambda (gs tvar) - (make-assignment gs `(call (core TypeVar) ',tvar (core Any) true))) + (make-assignment gs `(call (core TypeVar) ',tvar (core Any)))) closure-param-syms closure-param-names) `((method #f ,(cl-convert arg-defs fname lam namemap toplevel interp) ,(convert-lambda lam2 diff --git a/src/julia.h b/src/julia.h index 2ca168fa11bb0..36a7ce2e4309d 100644 --- a/src/julia.h +++ b/src/julia.h @@ -229,7 +229,7 @@ typedef struct _jl_method_t { int32_t line; // method's type signature. redundant with TypeMapEntry->specTypes - jl_tupletype_t *sig; + jl_value_t *sig; // bound type variables (static parameters) jl_svec_t *tvars; size_t min_world; @@ -270,7 +270,7 @@ typedef struct _jl_method_t { // This type caches the data for a specType signature specialization of a Method typedef struct _jl_method_instance_t { JL_DATA_TYPE - jl_tupletype_t *specTypes; // argument types this was specialized for + jl_value_t *specTypes; // argument types this was specialized for jl_value_t *rettype; // return type for fptr jl_svec_t *sparam_vals; // the values for the tvars, indexed by def->sparam_syms jl_array_t *backedges; @@ -295,15 +295,20 @@ typedef struct _jl_method_instance_t { // all values are callable as Functions typedef jl_value_t jl_function_t; -// a TypeConstructor (typealias) -// for example, Vector{T}: -// body is the Vector{T} <: Type -// parameters is the set {T}, the bound TypeVars in body typedef struct { JL_DATA_TYPE - jl_svec_t *parameters; + jl_sym_t *name; + jl_value_t *lb; // lower bound + jl_value_t *ub; // upper bound +} jl_tvar_t; + +// UnionAll type (iterated union over all values of a variable in certain bounds) +// written `body where lb<:var<:ub` +typedef struct { + JL_DATA_TYPE + jl_tvar_t *var; jl_value_t *body; -} jl_typector_t; +} jl_unionall_t; // represents the "name" part of a DataType, describing the syntactic structure // of a type and storing all data common to different instantiations of the type, @@ -313,11 +318,9 @@ typedef struct { jl_sym_t *name; struct _jl_module_t *module; jl_svec_t *names; // field names - // if this is the name of a parametric type, this field points to the - // original type. - // a type alias, for example, might make a type constructor that is - // not the original. - jl_value_t *primary; + // `wrapper` is either the only instantiation of the type (if no parameters) + // or a UnionAll accepting parameters to make an instantiation. + jl_value_t *wrapper; jl_svec_t *cache; // sorted array jl_svec_t *linearcache; // unsorted array intptr_t hash; @@ -326,7 +329,12 @@ typedef struct { typedef struct { JL_DATA_TYPE - jl_svec_t *types; +} jl_bottomtype_t; + +typedef struct { + JL_DATA_TYPE + jl_value_t *a; + jl_value_t *b; } jl_uniontype_t; // in little-endian, isptr is always the first bit, avoiding the need for a branch in computing isptr @@ -378,19 +386,10 @@ typedef struct _jl_datatype_t { void *struct_decl; //llvm::Type* void *ditype; // llvm::MDNode* to be used as llvm::DIType(ditype) int32_t depth; - int8_t hastypevars; // bound - int8_t haswildcard; // unbound + int8_t hasfreetypevars; int8_t isleaftype; } jl_datatype_t; -typedef struct { - JL_DATA_TYPE - jl_sym_t *name; - jl_value_t *lb; // lower bound - jl_value_t *ub; // upper bound - uint8_t bound; // part of a constraint environment -} jl_tvar_t; - typedef struct { JL_DATA_TYPE jl_value_t *value; @@ -477,13 +476,20 @@ typedef struct { // constants and type objects ------------------------------------------------- +// kinds +extern JL_DLLEXPORT jl_datatype_t *jl_bottomtype_type; +extern JL_DLLEXPORT jl_datatype_t *jl_datatype_type; +extern JL_DLLEXPORT jl_datatype_t *jl_uniontype_type; +extern JL_DLLEXPORT jl_datatype_t *jl_unionall_type; +extern JL_DLLEXPORT jl_datatype_t *jl_tvar_type; + extern JL_DLLEXPORT jl_datatype_t *jl_any_type; -extern JL_DLLEXPORT jl_datatype_t *jl_type_type; +extern JL_DLLEXPORT jl_unionall_t *jl_type_type; extern JL_DLLEXPORT jl_tvar_t *jl_typetype_tvar; -extern JL_DLLEXPORT jl_datatype_t *jl_typetype_type; +extern JL_DLLEXPORT jl_unionall_t *jl_typetype_type; extern JL_DLLEXPORT jl_value_t *jl_ANY_flag; extern JL_DLLEXPORT jl_datatype_t *jl_typename_type; -extern JL_DLLEXPORT jl_datatype_t *jl_typector_type; +extern JL_DLLEXPORT jl_typename_t *jl_type_typename; extern JL_DLLEXPORT jl_datatype_t *jl_sym_type; extern JL_DLLEXPORT jl_datatype_t *jl_symbol_type; extern JL_DLLEXPORT jl_datatype_t *jl_ssavalue_type; @@ -495,24 +501,21 @@ extern JL_DLLEXPORT jl_typename_t *jl_tuple_typename; extern JL_DLLEXPORT jl_typename_t *jl_vecelement_typename; extern JL_DLLEXPORT jl_datatype_t *jl_anytuple_type; #define jl_tuple_type jl_anytuple_type -extern JL_DLLEXPORT jl_datatype_t *jl_anytuple_type_type; -extern JL_DLLEXPORT jl_datatype_t *jl_vararg_type; -extern JL_DLLEXPORT jl_datatype_t *jl_tvar_type; +extern JL_DLLEXPORT jl_unionall_t *jl_anytuple_type_type; +extern JL_DLLEXPORT jl_unionall_t *jl_vararg_type; +extern JL_DLLEXPORT jl_typename_t *jl_vararg_typename; extern JL_DLLEXPORT jl_datatype_t *jl_task_type; extern JL_DLLEXPORT jl_datatype_t *jl_function_type; extern JL_DLLEXPORT jl_datatype_t *jl_builtin_type; -extern JL_DLLEXPORT jl_datatype_t *jl_uniontype_type; -extern JL_DLLEXPORT jl_datatype_t *jl_datatype_type; - extern JL_DLLEXPORT jl_value_t *jl_bottom_type; extern JL_DLLEXPORT jl_datatype_t *jl_method_instance_type; extern JL_DLLEXPORT jl_datatype_t *jl_code_info_type; extern JL_DLLEXPORT jl_datatype_t *jl_method_type; extern JL_DLLEXPORT jl_datatype_t *jl_module_type; -extern JL_DLLEXPORT jl_datatype_t *jl_abstractarray_type; -extern JL_DLLEXPORT jl_datatype_t *jl_densearray_type; -extern JL_DLLEXPORT jl_datatype_t *jl_array_type; +extern JL_DLLEXPORT jl_unionall_t *jl_abstractarray_type; +extern JL_DLLEXPORT jl_unionall_t *jl_densearray_type; +extern JL_DLLEXPORT jl_unionall_t *jl_array_type; extern JL_DLLEXPORT jl_typename_t *jl_array_typename; extern JL_DLLEXPORT jl_datatype_t *jl_weakref_type; extern JL_DLLEXPORT jl_datatype_t *jl_abstractstring_type; @@ -552,11 +555,12 @@ extern JL_DLLEXPORT jl_datatype_t *jl_float64_type; extern JL_DLLEXPORT jl_datatype_t *jl_floatingpoint_type; extern JL_DLLEXPORT jl_datatype_t *jl_number_type; extern JL_DLLEXPORT jl_datatype_t *jl_void_type; -extern JL_DLLEXPORT jl_datatype_t *jl_complex_type; +extern JL_DLLEXPORT jl_unionall_t *jl_complex_type; extern JL_DLLEXPORT jl_datatype_t *jl_signed_type; extern JL_DLLEXPORT jl_datatype_t *jl_voidpointer_type; -extern JL_DLLEXPORT jl_datatype_t *jl_pointer_type; -extern JL_DLLEXPORT jl_datatype_t *jl_ref_type; +extern JL_DLLEXPORT jl_unionall_t *jl_pointer_type; +extern JL_DLLEXPORT jl_unionall_t *jl_ref_type; +extern JL_DLLEXPORT jl_typename_t *jl_pointer_typename; extern JL_DLLEXPORT jl_value_t *jl_array_uint8_type; extern JL_DLLEXPORT jl_value_t *jl_array_any_type; @@ -839,8 +843,7 @@ static inline uint32_t jl_fielddesc_size(int8_t fielddesc_type) #define jl_is_immutable_datatype(t) (jl_is_datatype(t) && (!((jl_datatype_t*)t)->mutabl)) #define jl_is_uniontype(v) jl_typeis(v,jl_uniontype_type) #define jl_is_typevar(v) jl_typeis(v,jl_tvar_type) -#define jl_is_typector(v) jl_typeis(v,jl_typector_type) -#define jl_is_TypeConstructor(v) jl_typeis(v,jl_typector_type) +#define jl_is_unionall(v) jl_typeis(v,jl_unionall_type) #define jl_is_typename(v) jl_typeis(v,jl_typename_type) #define jl_is_int8(v) jl_typeis(v,jl_int8_type) #define jl_is_int16(v) jl_typeis(v,jl_int16_type) @@ -850,8 +853,8 @@ static inline uint32_t jl_fielddesc_size(int8_t fielddesc_type) #define jl_is_uint16(v) jl_typeis(v,jl_uint16_type) #define jl_is_uint32(v) jl_typeis(v,jl_uint32_type) #define jl_is_uint64(v) jl_typeis(v,jl_uint64_type) -#define jl_is_float(v) jl_subtype(v,(jl_value_t*)jl_floatingpoint_type,1) -#define jl_is_floattype(v) jl_subtype(v,(jl_value_t*)jl_floatingpoint_type,0) +#define jl_is_float(v) jl_isa(v,(jl_value_t*)jl_floatingpoint_type) +#define jl_is_floattype(v) jl_subtype(v,(jl_value_t*)jl_floatingpoint_type) #define jl_is_float32(v) jl_typeis(v,jl_float32_type) #define jl_is_float64(v) jl_typeis(v,jl_float64_type) #define jl_is_bool(v) jl_typeis(v,jl_bool_type) @@ -875,6 +878,15 @@ static inline uint32_t jl_fielddesc_size(int8_t fielddesc_type) #define jl_is_cpointer(v) jl_is_cpointer_type(jl_typeof(v)) #define jl_is_pointer(v) jl_is_cpointer_type(jl_typeof(v)) +JL_DLLEXPORT int jl_subtype(jl_value_t *a, jl_value_t *b); + +STATIC_INLINE int jl_is_type(jl_value_t *v) +{ + jl_value_t *t = jl_typeof(v); + return (t == (jl_value_t*)jl_datatype_type || t == (jl_value_t*)jl_uniontype_type || + t == (jl_value_t*)jl_unionall_type || v == jl_bottom_type); +} + STATIC_INLINE int jl_is_bitstype(void *v) { return (jl_is_datatype(v) && jl_is_immutable(v) && @@ -928,25 +940,19 @@ STATIC_INLINE int jl_is_array(void *v) STATIC_INLINE int jl_is_cpointer_type(jl_value_t *t) { return (jl_is_datatype(t) && - ((jl_datatype_t*)(t))->name == jl_pointer_type->name); + ((jl_datatype_t*)(t))->name == ((jl_datatype_t*)jl_pointer_type->body)->name); } STATIC_INLINE int jl_is_abstract_ref_type(jl_value_t *t) { return (jl_is_datatype(t) && - ((jl_datatype_t*)(t))->name == jl_ref_type->name); + ((jl_datatype_t*)(t))->name == ((jl_datatype_t*)jl_ref_type->body)->name); } -STATIC_INLINE jl_value_t *jl_is_ref_type(jl_value_t *t) +STATIC_INLINE int jl_is_ref_type(jl_value_t *t) { if (!jl_is_datatype(t)) return 0; - jl_datatype_t *dt = (jl_datatype_t*)t; - while (dt != jl_any_type && dt->name != dt->super->name) { - if (dt->name == jl_ref_type->name) - return (jl_value_t*)dt; - dt = dt->super; - } - return 0; + return jl_subtype(t, (jl_value_t*)jl_ref_type); } STATIC_INLINE int jl_is_tuple_type(void *t) @@ -964,7 +970,7 @@ STATIC_INLINE int jl_is_vecelement_type(jl_value_t* t) STATIC_INLINE int jl_is_type_type(jl_value_t *v) { return (jl_is_datatype(v) && - ((jl_datatype_t*)(v))->name == jl_type_type->name); + ((jl_datatype_t*)(v))->name == ((jl_datatype_t*)jl_type_type->body)->name); } // object identity @@ -973,15 +979,19 @@ JL_DLLEXPORT uintptr_t jl_object_id(jl_value_t *v); // type predicates and basic operations JL_DLLEXPORT int jl_is_leaf_type(jl_value_t *v); -JL_DLLEXPORT int jl_has_typevars(jl_value_t *v); -JL_DLLEXPORT int jl_subtype(jl_value_t *a, jl_value_t *b, int ta); +JL_DLLEXPORT int jl_has_free_typevars(jl_value_t *v); +JL_DLLEXPORT int jl_has_typevar(jl_value_t *t, jl_tvar_t *v); +JL_DLLEXPORT int jl_subtype_env_size(jl_value_t *t); +JL_DLLEXPORT int jl_subtype_env(jl_value_t *x, jl_value_t *y, jl_value_t **env, int envsz); +JL_DLLEXPORT int jl_isa(jl_value_t *a, jl_value_t *t); JL_DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b); -JL_DLLEXPORT jl_value_t *jl_type_union(jl_svec_t *types); +JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n); JL_DLLEXPORT jl_value_t *jl_type_intersection(jl_value_t *a, jl_value_t *b); -JL_DLLEXPORT int jl_args_morespecific(jl_value_t *a, jl_value_t *b); JL_DLLEXPORT const char *jl_typename_str(jl_value_t *v); JL_DLLEXPORT const char *jl_typeof_str(jl_value_t *v); JL_DLLEXPORT int jl_type_morespecific(jl_value_t *a, jl_value_t *b); +jl_value_t *jl_unwrap_unionall(jl_value_t *v); +jl_value_t *jl_rewrap_unionall(jl_value_t *t, jl_value_t *u); #ifdef NDEBUG STATIC_INLINE int jl_is_leaf_type_(jl_value_t *v) @@ -993,8 +1003,12 @@ STATIC_INLINE int jl_is_leaf_type_(jl_value_t *v) // type constructors JL_DLLEXPORT jl_typename_t *jl_new_typename(jl_sym_t *name); -JL_DLLEXPORT jl_tvar_t *jl_new_typevar(jl_sym_t *name,jl_value_t *lb,jl_value_t *ub); -JL_DLLEXPORT jl_value_t *jl_apply_type(jl_value_t *tc, jl_svec_t *params); +JL_DLLEXPORT jl_tvar_t *jl_new_typevar(jl_sym_t *name, jl_value_t *lb, jl_value_t *ub); +JL_DLLEXPORT jl_unionall_t *jl_new_unionall_type(jl_tvar_t *v, jl_value_t *body); +JL_DLLEXPORT jl_value_t *jl_instantiate_unionall(jl_unionall_t *u, jl_value_t *p); +JL_DLLEXPORT jl_value_t *jl_apply_type(jl_value_t *tc, jl_value_t **params, size_t n); +JL_DLLEXPORT jl_value_t *jl_apply_type1(jl_value_t *tc, jl_value_t *p1); +JL_DLLEXPORT jl_value_t *jl_apply_type2(jl_value_t *tc, jl_value_t *p1, jl_value_t *p2); JL_DLLEXPORT jl_tupletype_t *jl_apply_tuple_type(jl_svec_t *params); JL_DLLEXPORT jl_tupletype_t *jl_apply_tuple_type_v(jl_value_t **p, size_t np); JL_DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super, @@ -1097,19 +1111,35 @@ typedef enum { STATIC_INLINE int jl_is_vararg_type(jl_value_t *v) { + v = jl_unwrap_unionall(v); return (jl_is_datatype(v) && - ((jl_datatype_t*)(v))->name == jl_vararg_type->name); + ((jl_datatype_t*)(v))->name == jl_vararg_typename); +} + +STATIC_INLINE jl_value_t *jl_unwrap_vararg(jl_value_t *v) +{ + return jl_tparam0(jl_unwrap_unionall(v)); } STATIC_INLINE jl_vararg_kind_t jl_vararg_kind(jl_value_t *v) { if (!jl_is_vararg_type(v)) return JL_VARARG_NONE; + jl_tvar_t *v1=NULL, *v2=NULL; + if (jl_is_unionall(v)) { + v1 = ((jl_unionall_t*)v)->var; + v = ((jl_unionall_t*)v)->body; + if (jl_is_unionall(v)) { + v2 = ((jl_unionall_t*)v)->var; + v = ((jl_unionall_t*)v)->body; + } + } + assert(jl_is_datatype(v)); jl_value_t *lenv = jl_tparam1(v); if (jl_is_long(lenv)) return JL_VARARG_INT; - if (jl_is_typevar(lenv)) - return ((jl_tvar_t*)lenv)->bound ? JL_VARARG_BOUND : JL_VARARG_UNBOUND; + if (jl_is_typevar(lenv) && lenv != (jl_value_t*)v1 && lenv != (jl_value_t*)v2) + return JL_VARARG_BOUND; return JL_VARARG_UNBOUND; } @@ -1122,6 +1152,7 @@ STATIC_INLINE int jl_is_va_tuple(jl_datatype_t *t) STATIC_INLINE jl_vararg_kind_t jl_va_tuple_kind(jl_datatype_t *t) { + t = (jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)t); assert(jl_is_tuple_type(t)); size_t l = jl_svec_len(t->parameters); if (l == 0) @@ -1169,7 +1200,7 @@ JL_DLLEXPORT void jl_array_del_beg(jl_array_t *a, size_t dec); JL_DLLEXPORT void jl_array_sizehint(jl_array_t *a, size_t sz); JL_DLLEXPORT void jl_array_ptr_1d_push(jl_array_t *a, jl_value_t *item); JL_DLLEXPORT void jl_array_ptr_1d_push2(jl_array_t *a, jl_value_t *b, jl_value_t *c); -JL_DLLEXPORT jl_value_t *jl_apply_array_type(jl_datatype_t *type, size_t dim); +JL_DLLEXPORT jl_value_t *jl_apply_array_type(jl_value_t *type, size_t dim); // property access JL_DLLEXPORT void *jl_array_ptr(jl_array_t *a); JL_DLLEXPORT void *jl_array_eltype(jl_value_t *a); diff --git a/src/julia_internal.h b/src/julia_internal.h index 741d5c7c31155..9beadd31caf99 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -320,33 +320,25 @@ JL_DLLEXPORT void jl_uv_associate_julia_struct(uv_handle_t *handle, jl_value_t *data); JL_DLLEXPORT int jl_uv_fs_result(uv_fs_t *f); -int jl_tuple_subtype(jl_value_t **child, size_t cl, jl_datatype_t *pdt, int ta); +int jl_tuple_isa(jl_value_t **child, size_t cl, jl_datatype_t *pdt); int jl_subtype_invariant(jl_value_t *a, jl_value_t *b, int ta); jl_value_t *jl_type_match(jl_value_t *a, jl_value_t *b); -extern int type_match_invariance_mask; jl_value_t *jl_type_match_morespecific(jl_value_t *a, jl_value_t *b); -int jl_types_equal_generic(jl_value_t *a, jl_value_t *b, int useenv); jl_datatype_t *jl_inst_concrete_tupletype_v(jl_value_t **p, size_t np); jl_datatype_t *jl_inst_concrete_tupletype(jl_svec_t *p); JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method, jl_tupletype_t *simpletype); void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_t fptr); -STATIC_INLINE int jl_is_type(jl_value_t *v) -{ - jl_value_t *t = jl_typeof(v); - return (t == (jl_value_t*)jl_datatype_type || t == (jl_value_t*)jl_uniontype_type || - t == (jl_value_t*)jl_typector_type); -} jl_value_t *jl_type_intersection_matching(jl_value_t *a, jl_value_t *b, jl_svec_t **penv, jl_svec_t *tvars); -jl_value_t *jl_apply_type_(jl_value_t *tc, jl_value_t **params, size_t n); jl_value_t *jl_instantiate_type_with(jl_value_t *t, jl_value_t **env, size_t n); +jl_value_t *jl_substitute_var(jl_value_t *t, jl_tvar_t *var, jl_value_t *val); jl_datatype_t *jl_new_uninitialized_datatype(void); jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_datatype_t *super, jl_svec_t *parameters); void jl_precompute_memoized_dt(jl_datatype_t *dt); jl_datatype_t *jl_wrap_Type(jl_value_t *t); // x -> Type{x} -jl_datatype_t *jl_wrap_vararg(jl_value_t *t, jl_value_t *n); +jl_value_t *jl_wrap_vararg(jl_value_t *t, jl_value_t *n); void jl_assign_bits(void *dest, jl_value_t *bits); jl_expr_t *jl_exprn(jl_sym_t *head, size_t n); jl_function_t *jl_new_generic_function(jl_sym_t *name, jl_module_t *module); @@ -375,7 +367,7 @@ jl_value_t *jl_gf_invoke(jl_tupletype_t *types, jl_value_t **args, size_t nargs) JL_DLLEXPORT jl_datatype_t *jl_first_argument_datatype(jl_value_t *argtypes); int jl_has_intrinsics(jl_method_instance_t *li, jl_value_t *v, jl_module_t *m); -jl_value_t *jl_nth_slot_type(jl_tupletype_t *sig, size_t i); +jl_value_t *jl_nth_slot_type(jl_value_t *sig, size_t i); void jl_compute_field_offsets(jl_datatype_t *st); jl_array_t *jl_new_array_for_deserialization(jl_value_t *atype, uint32_t ndims, size_t *dims, int isunboxed, int elsz); @@ -486,9 +478,9 @@ JL_DLLEXPORT jl_array_t *jl_idtable_rehash(jl_array_t *a, size_t newsz); JL_DLLEXPORT jl_methtable_t *jl_new_method_table(jl_sym_t *name, jl_module_t *module); jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types, size_t world); JL_DLLEXPORT int jl_has_call_ambiguities(jl_tupletype_t *types, jl_method_t *m); -jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_tupletype_t *types, jl_svec_t *sp); +jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_value_t *types, jl_svec_t *sp); JL_DLLEXPORT jl_value_t *jl_methtable_lookup(jl_methtable_t *mt, jl_tupletype_t *type, size_t world); -JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m, jl_tupletype_t *type, jl_svec_t *sparams, size_t world); +JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m, jl_value_t *type, jl_svec_t *sparams, size_t world); JL_DLLEXPORT void jl_method_instance_add_backedge(jl_method_instance_t *callee, jl_method_instance_t *caller); JL_DLLEXPORT void jl_method_table_add_backedge(jl_methtable_t *mt, jl_value_t *typ, jl_value_t *caller); @@ -756,7 +748,8 @@ STATIC_INLINE int is_kind(jl_value_t *v) { return (v==(jl_value_t*)jl_uniontype_type || v==(jl_value_t*)jl_datatype_type || - v==(jl_value_t*)jl_typector_type); + v==(jl_value_t*)jl_unionall_type || + v==(jl_value_t*)jl_bottomtype_type); } // a descriptor of a jl_typemap_t that gets diff --git a/src/runtime_intrinsics.c b/src/runtime_intrinsics.c index 338ac0d5993b8..628220785b17f 100644 --- a/src/runtime_intrinsics.c +++ b/src/runtime_intrinsics.c @@ -81,7 +81,7 @@ JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty) JL_TYPECHK(cglobal, type, ty); jl_value_t *rt = v == (jl_value_t*)jl_void_type ? (jl_value_t*)jl_voidpointer_type : // a common case - (jl_value_t*)jl_apply_type_((jl_value_t*)jl_pointer_type, &ty, 1); + (jl_value_t*)jl_apply_type1((jl_value_t*)jl_pointer_type, ty); if (!jl_is_leaf_type(rt)) jl_error("cglobal: type argument not a leaftype"); diff --git a/src/stackwalk.c b/src/stackwalk.c index bba8635f086aa..2b2526a5e852e 100644 --- a/src/stackwalk.c +++ b/src/stackwalk.c @@ -88,13 +88,11 @@ size_t rec_backtrace(uintptr_t *data, size_t maxsize) static jl_value_t *array_ptr_void_type = NULL; JL_DLLEXPORT jl_value_t *jl_backtrace_from_here(int returnsp) { - jl_svec_t *tp = NULL; jl_array_t *ip = NULL; jl_array_t *sp = NULL; - JL_GC_PUSH3(&tp, &ip, &sp); + JL_GC_PUSH2(&ip, &sp); if (array_ptr_void_type == NULL) { - tp = jl_svec2(jl_voidpointer_type, jl_box_long(1)); - array_ptr_void_type = jl_apply_type((jl_value_t*)jl_array_type, tp); + array_ptr_void_type = jl_apply_type2((jl_value_t*)jl_array_type, jl_voidpointer_type, jl_box_long(1)); } ip = jl_alloc_array_1d(array_ptr_void_type, 0); sp = returnsp ? jl_alloc_array_1d(array_ptr_void_type, 0) : NULL; @@ -123,12 +121,10 @@ JL_DLLEXPORT jl_value_t *jl_backtrace_from_here(int returnsp) JL_DLLEXPORT jl_value_t *jl_get_backtrace(void) { jl_ptls_t ptls = jl_get_ptls_states(); - jl_svec_t *tp = NULL; jl_array_t *bt = NULL; - JL_GC_PUSH2(&tp, &bt); + JL_GC_PUSH1(&bt); if (array_ptr_void_type == NULL) { - tp = jl_svec2(jl_voidpointer_type, jl_box_long(1)); - array_ptr_void_type = jl_apply_type((jl_value_t*)jl_array_type, tp); + array_ptr_void_type = jl_apply_type2((jl_value_t*)jl_array_type, jl_voidpointer_type, jl_box_long(1)); } bt = jl_alloc_array_1d(array_ptr_void_type, ptls->bt_size); memcpy(bt->data, ptls->bt_data, ptls->bt_size * sizeof(void*)); diff --git a/src/subtype.c b/src/subtype.c new file mode 100644 index 0000000000000..9004075864a7d --- /dev/null +++ b/src/subtype.c @@ -0,0 +1,1582 @@ +// This file is a part of Julia. License is MIT: http://julialang.org/license + +/* + subtyping predicate + + Uses the algorithm described in section 4.2.2 of https://github.com/JeffBezanson/phdthesis/ + This code adds the following features to the core algorithm: + + - Type variables can be restricted to range over only concrete types. + This is done by returning false if such a variable's lower bound is not concrete. + - Diagonal rule: a type variable is concrete if it occurs more than once in + covariant position, and never in invariant position. This sounds like a syntactic + property, but actually isn't since it depends on which occurrences of a type + variable the algorithm actually uses. + - Unconstrained type vars (Bottom<:T<:Any) can match non-type values. + - Vararg types have an int-valued length parameter N (in `Vararg{T,N}`). + - Type{T}<:S if isa(T,S). Existing code assumes this, but it's not strictly + correct since a type can equal `T` without having the same representation. + - Free type variables are tolerated. This can hopefully be removed after a + deprecation period. +*/ +#include +#include +#include +#ifdef _OS_WINDOWS_ +#include +#endif +#include "julia.h" +#include "julia_internal.h" + +// stack of bits to keep track of which combination of Union components we are +// looking at (0 for Union.a, 1 for Union.b). forall_exists_subtype and +// exists_subtype loop over all combinations by updating a binary count in +// this structure. +// Union type decision points are discovered while the algorithm works. +// If a new Union decision is encountered, the `more` flag is set to tell +// the forall/exists loop to grow the stack. +typedef struct { + int depth; + int8_t more; + int stacksize; + uint32_t stack[10]; // stack of bits represented as a bit vector +} jl_unionstate_t; + +// Linked list storing the type variable environment. A new jl_varbinding_t +// is pushed for each UnionAll type we encounter. `lb` and `ub` are updated +// during the computation. +// Most of the complexity is due to the "diagonal rule", requiring us to +// identify which type vars range over only concrete types. +typedef struct _varbinding { + jl_tvar_t *var; + jl_value_t *lb; + jl_value_t *ub; + int8_t right; // whether this variable came from the right side of `A <: B` + // if another var that this one depends on is found to be concrete, store it + // here for reference in case that var is popped from the environment before this one. + // TODO: generalize this to multiple variables + jl_tvar_t *concretevar; + int8_t occurs_inv; // occurs in invariant position + int8_t occurs_cov; // # of occurrences in covariant position + int8_t concrete; // 1 if another variable has a constraint forcing this one to be concrete + // in covariant position, we need to try constraining a variable in different ways: + // 0 - unconstrained + // 1 - less than + // 2 - greater than + // 3 - inexpressible - occurs when the var has non-trivial overlap with another type, + // and we would need to return `intersect(var,other)`. in this case + // we choose to over-estimate the intersection by returning the var. + int8_t constraintkind; + int depth0; // # of invariant constructors nested around the UnionAll type for this var + // when this variable's integer value is compared to that of another, + // it equals `other + offset`. used by vararg length parameters. + int offset; + struct _varbinding *prev; +} jl_varbinding_t; + +// subtype algorithm state +typedef struct { + jl_varbinding_t *vars; // type variable environment + jl_unionstate_t Lunions; // union state for unions on the left of A <: B + jl_unionstate_t Runions; // union state for unions on the right + jl_value_t **envout; // for passing caller the computed bounds of right-side variables + int envsz; // length of envout + int envidx; // current index in envout + int invdepth; // current number of invariant constructors we're nested in + int ignore_free; + int intersection; +} jl_stenv_t; + +// state manipulation utilities + +// look up a type variable in an environment +static jl_varbinding_t *lookup(jl_stenv_t *e, jl_tvar_t *v) +{ + jl_varbinding_t *b = e->vars; + while (b != NULL) { + if (b->var == v) return b; + b = b->prev; + } + return b; +} + +static int statestack_get(jl_unionstate_t *st, int i) +{ + assert(i < st->stacksize); + // get the `i`th bit in an array of 32-bit words + return (st->stack[i>>5] & (1<<(i&31))) != 0; +} + +static void statestack_set(jl_unionstate_t *st, int i, int val) +{ + assert(i < st->stacksize); + if (val) + st->stack[i>>5] |= (1<<(i&31)); + else + st->stack[i>>5] &= ~(1<<(i&31)); +} + +static void statestack_push(jl_unionstate_t *st, int val) +{ + st->stacksize++; + assert(st->stacksize <= sizeof(st->stack)*8); + statestack_set(st, st->stacksize-1, val); +} + +static void statestack_pop(jl_unionstate_t *st) +{ + assert(st->stacksize > 0); + st->stacksize--; +} + +static void save_env(jl_stenv_t *e, jl_value_t **root, int8_t **buf) +{ + jl_varbinding_t *v = e->vars; + int len=0; + while (v != NULL) { + len++; + v = v->prev; + } + *root = (jl_value_t*)jl_alloc_svec(len*2); + *buf = (int8_t*)malloc(len*2 + sizeof(int)); + int i=0; v = e->vars; + while (v != NULL) { + jl_svecset(*root, i, v->lb); (*buf)[i] = v->occurs_inv; + i++; + jl_svecset(*root, i, v->ub); (*buf)[i] = v->occurs_cov; + i++; + v = v->prev; + } + *(int*)(&(*buf)[i]) = e->Runions.depth; +} + +static void restore_env(jl_stenv_t *e, jl_value_t *root, int8_t *buf) +{ + jl_varbinding_t *v = e->vars; + int i = 0; + while (v != NULL) { + if (root) v->lb = jl_svecref(root, i); + v->occurs_inv = buf[i]; + i++; + if (root) v->ub = jl_svecref(root, i); + v->occurs_cov = buf[i]; + i++; + v = v->prev; + } + e->Runions.depth = *(int*)(&buf[i]); +} + +// type utilities + +// quickly test that two types are identical +static int obviously_egal(jl_value_t *a, jl_value_t *b) +{ + if (a == b) return 1; + if (jl_typeof(a) != jl_typeof(b)) return 0; + if (jl_is_datatype(a)) { + jl_datatype_t *ad = (jl_datatype_t*)a, *bd = (jl_datatype_t*)b; + if (ad->name != bd->name) return 0; + size_t i, np = jl_nparams(ad); + if (np != jl_nparams(bd)) return 0; + for(i=0; i < np; i++) { + if (!obviously_egal(jl_tparam(ad,i), jl_tparam(bd,i))) + return 0; + } + return 1; + } + if (jl_is_uniontype(a)) { + return obviously_egal(((jl_uniontype_t*)a)->a, ((jl_uniontype_t*)b)->a) && + obviously_egal(((jl_uniontype_t*)a)->b, ((jl_uniontype_t*)b)->b); + } + /* // not clear whether this helps at all + if (jl_is_unionall(a)) { + return ((jl_unionall_t*)a)->var == ((jl_unionall_t*)b)->var && + obviously_egal(((jl_unionall_t*)a)->body, ((jl_unionall_t*)b)->body); + } + */ + if (jl_is_typevar(a)) return 0; + return !jl_is_type(a) && jl_egal(a,b); +} + +static int in_union(jl_value_t *u, jl_value_t *x) +{ + if (u == x) return 1; + if (!jl_is_uniontype(u)) return 0; + return in_union(((jl_uniontype_t*)u)->a, x) || in_union(((jl_uniontype_t*)u)->b, x); +} + +// compute a least upper bound of `a` and `b` +static jl_value_t *simple_join(jl_value_t *a, jl_value_t *b) +{ + if (a == jl_bottom_type || b == (jl_value_t*)jl_any_type || obviously_egal(a,b)) + return b; + if (b == jl_bottom_type || a == (jl_value_t*)jl_any_type) + return a; + if (!(jl_is_type(a) || jl_is_typevar(a)) || !(jl_is_type(b) || jl_is_typevar(b))) + return (jl_value_t*)jl_any_type; + if (jl_is_uniontype(a) && in_union(a, b)) + return a; + if (jl_is_uniontype(b) && in_union(b, a)) + return b; + return jl_new_struct(jl_uniontype_type, a, b); +} + +static jl_unionall_t *rename_unionall(jl_unionall_t *u) +{ + jl_tvar_t *v = jl_new_typevar(u->var->name, u->var->lb, u->var->ub); + jl_value_t *t = NULL; + JL_GC_PUSH2(&v, &t); + t = jl_instantiate_unionall(u, (jl_value_t*)v); + t = jl_new_struct(jl_unionall_type, v, t); + JL_GC_POP(); + return (jl_unionall_t*)t; +} + +// main subtyping algorithm + +static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param); + +// compare the current component of `u` to `t`. `R==1` means `u` came from the right side. +static int subtype_union(jl_value_t *t, jl_uniontype_t *u, jl_stenv_t *e, int8_t R, int param) +{ + jl_unionstate_t *state = R ? &e->Runions : &e->Lunions; + if (state->depth >= state->stacksize) { + state->more = 1; + return 1; + } + int ui = statestack_get(state, state->depth); + state->depth++; + jl_value_t *choice = ui==0 ? u->a : u->b; + return R ? subtype(t, choice, e, param) : subtype(choice, t, e, param); +} + +// subtype(), but taking apart unions before handling vars +static int subtype_ufirst(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) +{ + if (jl_is_uniontype(x) && jl_is_typevar(y)) + return subtype_union(y, (jl_uniontype_t*)x, e, 0, 0); + if (jl_is_typevar(x) && jl_is_uniontype(y)) + return (x == ((jl_uniontype_t*)y)->a || x == ((jl_uniontype_t*)y)->b || + subtype_union(x, (jl_uniontype_t*)y, e, 1, 0)); + return subtype(x, y, e, 0); +} + +// use the current context to record where a variable occurred, for the purpose +// of determining whether the variable is concrete. +static void record_var_occurrence(jl_varbinding_t *vb, jl_stenv_t *e, int param) +{ + if (vb != NULL && param) { + if (param == 2 && e->invdepth > vb->depth0) + vb->occurs_inv++; + else + vb->occurs_cov++; + } +} + +// is var x's quantifier outside y's in nesting order +static int var_outside(jl_stenv_t *e, jl_tvar_t *x, jl_tvar_t *y) +{ + jl_varbinding_t *btemp = e->vars; + while (btemp != NULL) { + if (btemp->var == x) return 0; + if (btemp->var == y) return 1; + btemp = btemp->prev; + } + return 0; +} + +static jl_value_t *intersect_ufirst(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int depth); + +// check that type var `b` is <: `a`, and update b's upper bound. +static int var_lt(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int param) +{ + jl_varbinding_t *bb = lookup(e, b); + if (bb == NULL) + return e->ignore_free || subtype_ufirst(b->ub, a, e); + record_var_occurrence(bb, e, param); + if (!bb->right) // check ∀b . b<:a + return subtype_ufirst(bb->ub, a, e); + if (!((bb->lb == jl_bottom_type && !jl_is_type(a) && !jl_is_typevar(a)) || subtype_ufirst(bb->lb, a, e))) + return 0; + // for contravariance we would need to compute a meet here, but + // because of invariance bb.ub ⊓ a == a here always. however for this + // to work we need to compute issub(left,right) before issub(right,left), + // since otherwise the issub(a, bb.ub) check in var_gt becomes vacuous. + if (e->intersection) + bb->ub = intersect_ufirst(bb->ub, a, e, bb->depth0); + else + bb->ub = a; // meet(bb->ub, a) + if (jl_is_typevar(a)) { + jl_varbinding_t *aa = lookup(e, (jl_tvar_t*)a); + if (aa && !aa->right && in_union(bb->lb, a) && bb->depth0 != aa->depth0 && var_outside(e, b, (jl_tvar_t*)a)) { + // an "exists" var cannot equal a "forall" var inside it unless the forall + // var has equal bounds. + return subtype_ufirst(aa->ub, aa->lb, e); + } + } + return 1; +} + +// check that type var `b` is >: `a`, and update b's lower bound. +static int var_gt(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int param) +{ + jl_varbinding_t *bb = lookup(e, b); + if (bb == NULL) + return e->ignore_free || subtype_ufirst(a, b->lb, e); + record_var_occurrence(bb, e, param); + if (!bb->right) // check ∀b . b>:a + return subtype_ufirst(a, bb->lb, e); + if (!((bb->ub == (jl_value_t*)jl_any_type && !jl_is_type(a) && !jl_is_typevar(a)) || subtype_ufirst(a, bb->ub, e))) + return 0; + bb->lb = simple_join(bb->lb, a); + return 1; +} + +// check that a type is concrete. this is used to check concrete typevars; +// issubtype is false if the lower bound of a concrete type var is not concrete. +static int is_leaf_bound(jl_value_t *v) +{ + if (v == jl_bottom_type) return 1; + if (jl_is_datatype(v)) { + if (((jl_datatype_t*)v)->isleaftype) return 1; + if (((jl_datatype_t*)v)->abstract) { + if (jl_is_type_type(v)) + return 1;//!jl_has_free_typevars(jl_tparam0(v)); + return 0; + } + jl_svec_t *t = ((jl_datatype_t*)v)->parameters; + size_t l = jl_svec_len(t); + if (((jl_datatype_t*)v)->name == jl_tuple_typename) { + for(int i=0; i < l; i++) { + if (!is_leaf_bound(jl_svecref(t,i))) + return 0; + } + } + return 1; + } + return 0; +} + +// compare UnionAll type `u` to `t`. `R==1` if `u` came from the right side of A <: B. +static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8_t R, int param) +{ + jl_varbinding_t *btemp = e->vars; + // if the var for this unionall (based on identity) already appears somewhere + // in the environment, rename to get a fresh var. + while (btemp != NULL) { + if (btemp->var == u->var || jl_has_typevar(btemp->lb, u->var) || + jl_has_typevar(btemp->ub, u->var)) { + u = rename_unionall(u); + break; + } + btemp = btemp->prev; + } + jl_varbinding_t vb = { u->var, u->var->lb, u->var->ub, R, NULL, 0, 0, 0, 0, e->invdepth, 0, e->vars }; + JL_GC_PUSH2(&u, &vb.lb); + e->vars = &vb; + int ans; + if (R) { + e->envidx++; + ans = subtype(t, u->body, e, param); + e->envidx--; + // fill variable values into `envout` up to `envsz` + if (e->envidx < e->envsz) { + jl_value_t *val; + if (vb.lb == vb.ub) + val = vb.lb; + else if (vb.lb != jl_bottom_type) + // TODO: for now return the least solution, which is what + // method parameters expect. + val = vb.lb; + else if (vb.lb == u->var->lb && vb.ub == u->var->ub) + val = (jl_value_t*)u->var; + else + val = (jl_value_t*)jl_new_typevar(u->var->name, vb.lb, vb.ub); + e->envout[e->envidx] = val; + } + } + else { + ans = subtype(u->body, t, e, param); + } + + // handle the "diagonal dispatch" rule, which says that a type var occurring more + // than once, and only in covariant position, is constrained to concrete types. E.g. + // ( Tuple{Int, Int} <: Tuple{T, T} where T) but + // !( Tuple{Int, String} <: Tuple{T, T} where T) + // Then check concreteness by checking that the lower bound is not an abstract type. + if (ans && (vb.concrete || (!vb.occurs_inv && vb.occurs_cov > 1))) { + if (jl_is_typevar(vb.lb)) { + // TODO test case that demonstrates the need for this? + /* + jl_tvar_t *v = (jl_tvar_t*)vb.lb; + jl_varbinding_t *vlb = lookup(e, v); + if (vlb) + vlb->concrete = 1; + else // TODO handle multiple variables in vb.concretevar + ans = (v == vb.concretevar); + */ + } + else if (!is_leaf_bound(vb.lb)) { + ans = 0; + } + if (ans) { + // if we occur as another var's lower bound, record the fact that we + // were concrete so that subtype can return true for that var. + /* + btemp = vb.prev; + while (btemp != NULL) { + if (btemp->lb == (jl_value_t*)u->var) + btemp->concretevar = u->var; + btemp = btemp->prev; + } + */ + } + } + + e->vars = vb.prev; + JL_GC_POP(); + return ans; +} + +// unwrap <=2 layers of UnionAlls, leaving the vars in *p1 and *p2 and returning the body +static jl_value_t *unwrap_2_unionall(jl_value_t *t, jl_tvar_t **p1, jl_tvar_t **p2) +{ + if (jl_is_unionall(t)) { + *p1 = ((jl_unionall_t*)t)->var; + t = ((jl_unionall_t*)t)->body; + if (jl_is_unionall(t)) { + *p2 = ((jl_unionall_t*)t)->var; + t = ((jl_unionall_t*)t)->body; + } + } + return t; +} + +// check n <: (length of vararg type v) +static int check_vararg_length(jl_value_t *v, ssize_t n, jl_stenv_t *e) +{ + jl_tvar_t *va_p1=NULL, *va_p2=NULL; + jl_value_t *tail = unwrap_2_unionall(v, &va_p1, &va_p2); + assert(jl_is_datatype(tail)); + jl_value_t *N = jl_tparam1(tail); + // only do the check if N is free in the tuple type's last parameter + if (N != (jl_value_t*)va_p1 && N != (jl_value_t*)va_p2) { + if (!subtype(jl_box_long(n), N, e, 2)) + return 0; + } + return 1; +} + +static int subtype_tuple(jl_datatype_t *xd, jl_datatype_t *yd, jl_stenv_t *e, int param) +{ + size_t lx = jl_nparams(xd), ly = jl_nparams(yd); + if (lx == 0 && ly == 0) + return 1; + if (ly == 0) + return 0; + size_t i=0, j=0; + int vx=0, vy=0; + param = (param == 0 ? 1 : param); + while (i < lx) { + if (j >= ly) return 0; + jl_value_t *xi = jl_tparam(xd, i), *yi = jl_tparam(yd, j); + if (jl_is_vararg_type(xi)) vx = 1; + if (jl_is_vararg_type(yi)) vy = 1; + if (vx && !vy) + return 0; + if (!vx && vy) { + if (!subtype(xi, jl_unwrap_vararg(yi), e, param)) + return 0; + } + else { + if (!subtype(xi, yi, e, param)) + return 0; + } + i++; + if (j < ly-1 || !vy) + j++; + } + // TODO: handle Vararg with explicit integer length parameter + vy = vy || (j < ly && jl_is_vararg_type(jl_tparam(yd,j))); + if (vy && !vx && lx+1 >= ly) { + // in Tuple{...,tn} <: Tuple{...,Vararg{T,N}}, check (lx+1-ly) <: N + if (!check_vararg_length(jl_tparam(yd,ly-1), lx+1-ly, e)) + return 0; + } + return (lx==ly && vx==vy) || (vy && (lx >= (vx ? ly : (ly-1)))); +} + +// `param` means we are currently looking at a parameter of a type constructor +// (as opposed to being outside any type constructor, or comparing variable bounds). +// this is used to record the positions where type variables occur for the +// diagonal rule (record_var_occurrence). +static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param) +{ + if (x == jl_ANY_flag) x = (jl_value_t*)jl_any_type; + if (y == jl_ANY_flag) y = (jl_value_t*)jl_any_type; + if (jl_is_typevar(x)) { + if (jl_is_typevar(y)) { + if (x == y) return 1; + jl_varbinding_t *xx = lookup(e, (jl_tvar_t*)x); + jl_varbinding_t *yy = lookup(e, (jl_tvar_t*)y); + int xr = xx && xx->right; // treat free variables as "forall" (left) + int yr = yy && yy->right; + if (xr) { + if (yy) record_var_occurrence(yy, e, param); + if (yr) { + if (xx) record_var_occurrence(xx, e, param); + return subtype(xx->lb, yy->ub, e, 0); + } + return var_lt((jl_tvar_t*)x, y, e, param); + } + else if (yr) { + if (xx) record_var_occurrence(xx, e, param); + return var_gt((jl_tvar_t*)y, x, e, param); + } + jl_value_t *xub = xx ? xx->ub : ((jl_tvar_t*)x)->ub; + jl_value_t *ylb = yy ? yy->lb : ((jl_tvar_t*)y)->lb; + // check ∀x,y . x<:y + // the bounds of left-side variables never change, and can only lead + // to other left-side variables, so using || here is safe. + return subtype(xub, y, e, param) || subtype(x, ylb, e, param); + } + return var_lt((jl_tvar_t*)x, y, e, param); + } + if (jl_is_typevar(y)) + return var_gt((jl_tvar_t*)y, x, e, param); + if (jl_is_uniontype(x)) { + if (x == y) return 1; + if (param == 2) { + // in invariant context both parts must match in the same environment. + // TODO: don't double-count `y` with `param` + return subtype(((jl_uniontype_t*)x)->a, y, e, param) && + subtype(((jl_uniontype_t*)x)->b, y, e, param); + } + return subtype_union(y, (jl_uniontype_t*)x, e, 0, param); + } + if (jl_is_uniontype(y)) { + if (x == ((jl_uniontype_t*)y)->a || x == ((jl_uniontype_t*)y)->b) + return 1; + if (jl_is_unionall(x)) + return subtype_unionall(y, (jl_unionall_t*)x, e, 0, param); + return subtype_union(x, (jl_uniontype_t*)y, e, 1, param); + } + // handle forall ("left") vars first + if (jl_is_unionall(x)) { + if (x == y && !(e->envidx < e->envsz)) + return 1; + return subtype_unionall(y, (jl_unionall_t*)x, e, 0, param); + } + if (jl_is_unionall(y)) + return subtype_unionall(x, (jl_unionall_t*)y, e, 1, param); + if (jl_is_datatype(x) && jl_is_datatype(y)) { + if (x == y) return 1; + if (y == (jl_value_t*)jl_any_type) return 1; + jl_datatype_t *xd = (jl_datatype_t*)x, *yd = (jl_datatype_t*)y; + if (jl_is_type_type(x) && !jl_is_type_type(y)) { + if (!jl_is_typevar(jl_tparam0(xd))) { + // TODO this is not strictly correct, but we don't yet have any other way for + // e.g. the argument `Int` to match a `::DataType` slot. Most correct would be: + // Int isa DataType, Int isa Type{Int}, Type{Int} more specific than DataType, + // !(Type{Int} <: DataType), !isleaftype(Type{Int}), because non-DataTypes can + // be type-equal to `Int`. + return jl_typeof(jl_tparam0(xd)) == (jl_value_t*)yd; + } + return 0; + } + if (jl_is_type_type(y) && !jl_is_type_type(x)) { + if (!jl_is_typevar(jl_tparam0(yd))) + return 0; + if (!is_kind(x)) return 0; + e->invdepth++; + int ans = subtype(x, jl_tparam0(yd), e, 2) && subtype(jl_tparam0(yd), x, e, 0); + e->invdepth--; + return ans; + } + while (xd != jl_any_type && xd->name != yd->name) + xd = xd->super; + if (xd == jl_any_type) return 0; + if (jl_is_tuple_type(xd)) + return subtype_tuple(xd, yd, e, param); + if (jl_is_vararg_type((jl_value_t*)xd)) { + // Vararg: covariant in first parameter, invariant in second + jl_value_t *xp1=jl_tparam0(xd), *xp2=jl_tparam1(xd), *yp1=jl_tparam0(yd), *yp2=jl_tparam1(yd); + // in Vararg{T1} <: Vararg{T2}, need to check subtype twice to + // simulate the possibility of multiple arguments, which is needed + // to implement the diagonal rule correctly. + if (!subtype(xp1, yp1, e, 1)) return 0; + if (!subtype(xp1, yp1, e, 1)) return 0; + // Vararg{T,N} <: Vararg{T2,N2}; equate N and N2 + e->invdepth++; + int ans = subtype(xp2, yp2, e, 2) && subtype(yp2, xp2, e, 0); + e->invdepth--; + return ans; + } + size_t i, np = jl_nparams(xd); + int ans = 1; + e->invdepth++; + for (i=0; i < np; i++) { + jl_value_t *xi = jl_tparam(xd, i), *yi = jl_tparam(yd, i); + if (!(xi == yi || (subtype(xi, yi, e, 2) && subtype(yi, xi, e, 0)))) { + ans = 0; break; + } + } + e->invdepth--; + return ans; + } + if (jl_is_type(y)) + return x == jl_bottom_type; + return x == y || jl_egal(x, y); +} + +static int exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int8_t anyunions, jl_value_t *saved, int8_t *buf) +{ + int exists; + for (exists=0; exists <= anyunions; exists++) { + if (e->Runions.stacksize > 0) + statestack_set(&e->Runions, e->Runions.stacksize-1, exists); + e->Lunions.depth = e->Runions.depth = 0; + e->Lunions.more = e->Runions.more = 0; + int found = subtype(x, y, e, 0); + if (e->Lunions.more) { + // If another "forall" decision is found while inside the "exists" + // loop, return up to forall_exists_subtype to add it to the "forall" + // loop. This gives the recursion the following shape, instead of + // simply nesting on each new decision point: + // ∀₁ ∀₁ + // ∃₁ => ∀₂ + // ... + // ∃₁ + // ∃₂ + return 1; + } + if (e->Runions.more) { + statestack_push(&e->Runions, 0); + found = exists_subtype(x, y, e, 1, saved, buf); + statestack_pop(&e->Runions); + } + else { + if (!found) restore_env(e, saved, buf); + } + if (found) return 1; + } + return 0; +} + +static int forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int8_t anyunions) +{ + jl_value_t *saved=NULL; int8_t *buf; + JL_GC_PUSH1(&saved); + int forall; + for (forall=0; forall <= anyunions; forall++) { + if (e->Lunions.stacksize > 0) + statestack_set(&e->Lunions, e->Lunions.stacksize-1, forall); + save_env(e, &saved, &buf); + if (!exists_subtype(x, y, e, 0, saved, buf)) { + free(buf); + JL_GC_POP(); + return 0; + } + if (e->Lunions.more) { + restore_env(e, saved, buf); + statestack_push(&e->Lunions, 0); + int sub = forall_exists_subtype(x, y, e, 1); + statestack_pop(&e->Lunions); + if (!sub) { + free(buf); + JL_GC_POP(); + return 0; + } + } + free(buf); + } + JL_GC_POP(); + return 1; +} + +static void init_stenv(jl_stenv_t *e, jl_value_t **env, int envsz) +{ + e->vars = NULL; + assert(env != NULL || envsz == 0); + e->envsz = envsz; + e->envout = env; + e->envidx = 0; + e->invdepth = 0; + e->ignore_free = 0; + e->intersection = 0; + e->Lunions.depth = 0; e->Runions.depth = 0; + e->Lunions.more = 0; e->Runions.more = 0; + e->Lunions.stacksize = 0; e->Runions.stacksize = 0; +} + +// subtyping entry points + +JL_DLLEXPORT int jl_subtype_env_size(jl_value_t *t) +{ + int sz = 0; + while (jl_is_unionall(t)) { + sz++; + t = ((jl_unionall_t*)t)->body; + } + return sz; +} + +// `env` is NULL if no typevar information is requested, or otherwise +// points to a rooted array of length `jl_subtype_env_size(y)`. +// This will be populated with the values of variables from unionall +// types at the outer level of `y`. +JL_DLLEXPORT int jl_subtype_env(jl_value_t *x, jl_value_t *y, jl_value_t **env, int envsz) +{ + jl_stenv_t e; + init_stenv(&e, env, envsz); + return forall_exists_subtype(x, y, &e, 0); +} + +static int subtype_in_env(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) +{ + jl_stenv_t e2; + init_stenv(&e2, NULL, 0); + e2.vars = e->vars; + e2.intersection = e->intersection; + e2.ignore_free = e->ignore_free; + e2.envsz = e->envsz; + e2.envout = e->envout; + return forall_exists_subtype(x, y, &e2, 0); +} + +JL_DLLEXPORT int jl_subtype(jl_value_t *x, jl_value_t *y) +{ + if (y == (jl_value_t*)jl_any_type || x == jl_bottom_type || x == y) + return 1; + return jl_subtype_env(x, y, NULL, 0); +} + +JL_DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b) +{ + if (obviously_egal(a, b)) + return 1; + return jl_subtype(a, b) && jl_subtype(b, a); +} + +int jl_tuple_isa(jl_value_t **child, size_t cl, jl_datatype_t *pdt) +{ + // TODO jb/subtype avoid allocation + jl_value_t *tu = (jl_value_t*)arg_type_tuple(child, cl); + int ans; + JL_GC_PUSH1(&tu); + ans = jl_subtype(tu, (jl_value_t*)pdt); + JL_GC_POP(); + return ans; +} + +JL_DLLEXPORT int jl_isa(jl_value_t *x, jl_value_t *t) +{ + if (jl_typeis(x,t) || t == (jl_value_t*)jl_any_type) + return 1; + if (jl_is_type(x)) { + if (t == (jl_value_t*)jl_type_type) + return 1; + if (jl_is_leaf_type(t)) { + if (jl_is_type_type(t)) + return jl_types_equal(x, jl_tparam0(t)); + return 0; + } + JL_GC_PUSH1(&x); + x = (jl_value_t*)jl_wrap_Type(x); + int ans = jl_subtype(x, t); + JL_GC_POP(); + return ans; + } + if (jl_is_leaf_type(t)) + return 0; + return jl_subtype(jl_typeof(x), t); +} + +// type intersection + +static jl_value_t *intersect(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param); + +static jl_value_t *intersect_union(jl_value_t *x, jl_uniontype_t *u, jl_stenv_t *e, int8_t R, int param) +{ + if (param == 2) { + jl_value_t *a=NULL, *b=NULL, *save=NULL; int8_t *buf; + JL_GC_PUSH3(&a, &b, &save); + save_env(e, &save, &buf); + a = R ? intersect(x, u->a, e, param) : intersect(u->a, x, e, param); + restore_env(e, NULL, buf); + b = R ? intersect(x, u->b, e, param) : intersect(u->b, x, e, param); + free(buf); + jl_value_t *i = simple_join(a,b); + JL_GC_POP(); + return i; + } + jl_unionstate_t *state = &e->Runions; + if (state->depth >= state->stacksize) { + state->more = 1; + return jl_bottom_type; + } + int ui = statestack_get(state, state->depth); + state->depth++; + jl_value_t *choice = ui==0 ? u->a : u->b; + // try all possible choices in covariant position; union them all together at the top level + return R ? intersect(x, choice, e, param) : intersect(choice, x, e, param); +} + +static jl_value_t *intersect_ufirst(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int depth) +{ + jl_value_t *res; + int savedepth = e->invdepth; + e->invdepth = depth; + if (jl_is_uniontype(x) && jl_is_typevar(y)) + res = intersect_union(y, (jl_uniontype_t*)x, e, 0, 0); + else if (jl_is_typevar(x) && jl_is_uniontype(y)) + res = intersect_union(x, (jl_uniontype_t*)y, e, 1, 0); + else + res = intersect(x, y, e, 0); + e->invdepth = savedepth; + return res; +} + +// set a variable to a non-type constant +static jl_value_t *set_var_to_const(jl_varbinding_t *bb, jl_value_t *v, jl_varbinding_t *othervar) +{ + int offset = bb->offset; + if (othervar && offset == 0) + offset = -othervar->offset; + assert(!othervar || othervar->offset == -offset); + if (bb->lb == jl_bottom_type && bb->ub == (jl_value_t*)jl_any_type) { + if (jl_is_long(v)) + v = jl_box_long(jl_unbox_long(v) + offset); + bb->lb = bb->ub = v; + } + else if (jl_is_long(v) && jl_is_long(bb->lb)) { + if (jl_unbox_long(v) + offset != jl_unbox_long(bb->lb)) + return jl_bottom_type; + } + else if (!jl_egal(v, bb->lb)) { + return jl_bottom_type; + } + return v; +} + +static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int8_t R, int param) +{ + jl_varbinding_t *bb = lookup(e, b); + if (bb == NULL) + return R ? intersect_ufirst(a, b->ub, e, 0) : intersect_ufirst(b->ub, a, e, 0); + if (!jl_is_type(a) && !jl_is_typevar(a)) + return set_var_to_const(bb, a, NULL); + int d = bb->depth0; + if (param == 2) { + if (bb->lb == bb->ub && jl_is_typevar(bb->lb)) + return intersect(a, bb->ub, e, param); + jl_value_t *ub = R ? intersect_ufirst(a, bb->ub, e, d) : intersect_ufirst(bb->ub, a, e, d); + if (!subtype_in_env(bb->lb, a, e)) + return jl_bottom_type; + if (ub != (jl_value_t*)b) { + bb->ub = ub; + bb->lb = ub; + } + return ub; + } + else if (bb->constraintkind == 0) { + return R ? intersect_ufirst(a, bb->ub, e, d) : intersect_ufirst(bb->ub, a, e, d); + } + else if (bb->concrete || bb->constraintkind == 1) { + jl_value_t *ub = R ? intersect_ufirst(a, bb->ub, e, d) : intersect_ufirst(bb->ub, a, e, d); + if (ub == jl_bottom_type || !subtype_in_env(bb->lb, a, e)) + return jl_bottom_type; + if (ub != (jl_value_t*)b) + bb->ub = ub; + return (jl_value_t*)b; + } + else if (bb->constraintkind == 2) { + if (!subtype_in_env(a, bb->ub, e)) + return jl_bottom_type; + bb->lb = simple_join(bb->lb, a); + return a; + } + assert(bb->constraintkind == 3); + jl_value_t *ub = R ? intersect_ufirst(a, bb->ub, e, d) : intersect_ufirst(bb->ub, a, e, d); + if (ub == jl_bottom_type) + return jl_bottom_type; + if (jl_is_typevar(a)) + return (jl_value_t*)b; + jl_value_t *root; int8_t *buf; + JL_GC_PUSH2(&root, &ub); + save_env(e, &root, &buf); + jl_value_t *ii = R ? intersect_ufirst(a, bb->lb, e, d) : intersect_ufirst(bb->lb, a, e, d); + if (ii == jl_bottom_type) { + restore_env(e, root, buf); + ii = (jl_value_t*)b; + if (ub != (jl_value_t*)b) + bb->ub = ub; + } + free(buf); + JL_GC_POP(); + return ii; +} + +static int var_occurs_invariant(jl_value_t *v, jl_tvar_t *var, int inv) +{ + if (v == (jl_value_t*)var) { + return inv; + } + else if (jl_is_uniontype(v)) { + return var_occurs_invariant(((jl_uniontype_t*)v)->a, var, inv) || + var_occurs_invariant(((jl_uniontype_t*)v)->b, var, inv); + } + else if (jl_is_unionall(v)) { + jl_unionall_t *ua = (jl_unionall_t*)v; + if (ua->var == var) + return 0; + if (var_occurs_invariant(ua->var->lb, var, inv) || var_occurs_invariant(ua->var->ub, var, inv)) + return 1; + return var_occurs_invariant(ua->body, var, inv); + } + else if (jl_is_datatype(v)) { + size_t i; + int invar = inv || !jl_is_tuple_type(v); + for (i=0; i < jl_nparams(v); i++) { + if (var_occurs_invariant(jl_tparam(v,i), var, invar)) + return 1; + } + } + return 0; +} + +static jl_value_t *finish_unionall(jl_value_t *res, jl_varbinding_t *vb, jl_stenv_t *e) +{ + jl_value_t *varval = NULL, *root = NULL; + JL_GC_PUSH2(&res, &root); + // try to reduce var to a single value + if (obviously_egal(vb->lb, vb->ub)) { + // given x<:T<:x, substitute x for T + varval = vb->ub; + } + else if (!var_occurs_invariant(res, vb->var, 0) && is_leaf_bound(vb->ub)) { + // replace T<:x with x in covariant position when possible + varval = vb->ub; + } + + // remove/replace/rewrap free occurrences of this var in the environment + jl_varbinding_t *btemp = e->vars; + while (btemp != NULL) { + if (jl_has_typevar(btemp->lb, vb->var)) { + if (varval) + btemp->lb = jl_substitute_var(btemp->lb, vb->var, varval); + else if (btemp->lb == (jl_value_t*)vb->var) + btemp->lb = vb->lb; + else + btemp->lb = jl_new_struct(jl_unionall_type, vb->var, btemp->lb); + assert((jl_value_t*)btemp->var != btemp->lb); + } + if (jl_has_typevar(btemp->ub, vb->var)) { + if (varval) + btemp->ub = jl_substitute_var(btemp->ub, vb->var, varval); + else if (btemp->ub == (jl_value_t*)vb->var) + btemp->ub = vb->ub; + else + btemp->ub = jl_new_struct(jl_unionall_type, vb->var, btemp->ub); + assert((jl_value_t*)btemp->var != btemp->ub); + } + btemp = btemp->prev; + } + + // if `v` still occurs, re-wrap body in `UnionAll v` or eliminate the UnionAll + if (jl_has_typevar(res, vb->var)) { + res = jl_new_struct(jl_unionall_type, vb->var, res); + if (varval) { + res = jl_instantiate_unionall((jl_unionall_t*)res, varval); + } + else { + root = (jl_value_t*)jl_new_typevar(vb->var->name, vb->lb, vb->ub); + res = jl_instantiate_unionall((jl_unionall_t*)res, root); + res = jl_new_struct(jl_unionall_type, (jl_tvar_t*)root, res); + } + } + JL_GC_POP(); + return res; +} + +static jl_value_t *intersect_unionall_(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8_t R, int param, jl_varbinding_t *vb) +{ + jl_varbinding_t *btemp = e->vars; + // if the var for this unionall (based on identity) already appears somewhere + // in the environment, rename to get a fresh var. + // TODO: might need to look inside types in btemp->lb and btemp->ub + while (btemp != NULL) { + if (btemp->var == u->var || btemp->lb == (jl_value_t*)u->var || + btemp->ub == (jl_value_t*)u->var) { + u = rename_unionall(u); + break; + } + btemp = btemp->prev; + } + vb->var = u->var; + e->vars = vb; + jl_value_t *res = R ? intersect(t, u->body, e, param) : intersect(u->body, t, e, param); + vb->concrete |= (!vb->occurs_inv && vb->occurs_cov > 1); + /* + if (R) { + e->envidx++; + ans = subtype(t, u->body, e, param); + e->envidx--; + // fill variable values into `envout` up to `envsz` + if (e->envidx < e->envsz) { + jl_value_t *val; + if (vb->lb == vb->ub) + val = vb->lb; + else if (vb->lb != jl_bottom_type) + // TODO: for now return the least solution, which is what + // method parameters expect. + val = vb->lb; + else if (vb->lb == u->var->lb && vb->ub == u->var->ub) + val = (jl_value_t*)u->var; + else + val = (jl_value_t*)jl_new_typevar(u->var->name, vb->lb, vb->ub); + e->envout[e->envidx] = val; + } + } + else { + ans = subtype(u->body, t, e, param); + } + */ + + // handle the "diagonal dispatch" rule, which says that a type var occurring more + // than once, and only in covariant position, is constrained to concrete types. E.g. + // ( Tuple{Int, Int} <: Tuple{T, T} where T) but + // !( Tuple{Int, String} <: Tuple{T, T} where T) + // Then check concreteness by checking that the lower bound is not an abstract type. + if (res != jl_bottom_type && (vb->concrete || (!vb->occurs_inv && vb->occurs_cov > 1))) { + if (jl_is_typevar(vb->lb)) { + } + else if (!is_leaf_bound(vb->lb)) { + res = jl_bottom_type; + } + } + + e->vars = vb->prev; + + if (res != jl_bottom_type) { + // fail on circular constraints + if (jl_has_typevar(vb->lb, u->var) || jl_has_typevar(vb->ub, u->var)) + res = jl_bottom_type; + // T=Bottom in covariant position + if (vb->ub == jl_bottom_type && vb->occurs_cov) + res = jl_bottom_type; + } + if (res != jl_bottom_type) + res = finish_unionall(res, vb, e); + + return res; +} + +static jl_value_t *intersect_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8_t R, int param) +{ + jl_value_t *res=NULL, *res2=NULL, *save=NULL, *save2=NULL; + int8_t *buf=NULL, *buf2=NULL; + jl_varbinding_t vb = { u->var, u->var->lb, u->var->ub, R, NULL, 0, 0, 0, 0, e->invdepth, 0, e->vars }; + JL_GC_PUSH5(&res, &save2, &vb.lb, &vb.ub, &save); + save_env(e, &save, &buf); + res = intersect_unionall_(t, u, e, R, param, &vb); + if (res != jl_bottom_type && !e->Runions.more) { + if (vb.concrete || vb.occurs_inv>1 || (vb.occurs_inv && vb.occurs_cov)) { + restore_env(e, NULL, buf); + vb.occurs_cov = vb.occurs_inv = 0; + vb.constraintkind = 3; + res = intersect_unionall_(t, u, e, R, param, &vb); + } + else if (vb.occurs_cov) { + save_env(e, &save2, &buf2); + restore_env(e, save, buf); + vb.occurs_cov = vb.occurs_inv = 0; + vb.lb = u->var->lb; vb.ub = u->var->ub; + vb.constraintkind = 2; + res2 = intersect_unionall_(t, u, e, R, param, &vb); + if (res2 == jl_bottom_type && !e->Runions.more) { + restore_env(e, save, buf); + vb.occurs_cov = vb.occurs_inv = 0; + vb.lb = u->var->lb; vb.ub = u->var->ub; + vb.constraintkind = 1; + res2 = intersect_unionall_(t, u, e, R, param, &vb); + if (res2 == jl_bottom_type) + restore_env(e, save2, buf2); + } + if (res2 != jl_bottom_type) + res = res2; + free(buf2); + } + } + free(buf); + JL_GC_POP(); + return res; +} + +// check n = (length of vararg type v) +static int intersect_vararg_length(jl_value_t *v, ssize_t n, jl_stenv_t *e, int8_t R) +{ + jl_tvar_t *va_p1=NULL, *va_p2=NULL; + jl_value_t *tail = unwrap_2_unionall(v, &va_p1, &va_p2); + assert(jl_is_datatype(tail)); + jl_value_t *N = jl_tparam1(tail); + // only do the check if N is free in the tuple type's last parameter + if (jl_is_typevar(N) && N != (jl_value_t*)va_p1 && N != (jl_value_t*)va_p2) { + jl_value_t *len = jl_box_long(n); + jl_value_t *il = R ? intersect(len, N, e, 2) : intersect(N, len, e, 2); + if (il == jl_bottom_type) + return 0; + } + return 1; +} + +static jl_value_t *intersect_tuple(jl_datatype_t *xd, jl_datatype_t *yd, jl_stenv_t *e, int param) +{ + size_t lx = jl_nparams(xd), ly = jl_nparams(yd); + if (lx == 0 && ly == 0) + return (jl_value_t*)yd; + jl_svec_t *params = jl_alloc_svec(lx > ly ? lx : ly); + jl_value_t *res=NULL; + JL_GC_PUSH1(¶ms); + size_t i=0, j=0; + int vx=0, vy=0; + jl_value_t *xi, *yi; + while (1) { + xi = i < lx ? jl_tparam(xd, i) : NULL; + yi = j < ly ? jl_tparam(yd, j) : NULL; + if (xi == NULL && yi == NULL) { + assert(i == j && i == jl_svec_len(params)); + break; + } + if (xi && jl_is_vararg_type(xi)) vx = 1; + if (yi && jl_is_vararg_type(yi)) vy = 1; + if (xi == NULL || yi == NULL) { + res = jl_bottom_type; + if (vx && intersect_vararg_length(xi, ly+1-lx, e, 0)) + res = (jl_value_t*)jl_apply_tuple_type_v(jl_svec_data(params), j); + if (vy && intersect_vararg_length(yi, lx+1-ly, e, 1)) + res = (jl_value_t*)jl_apply_tuple_type_v(jl_svec_data(params), i); + break; + } + if (vx && !vy) + xi = jl_unwrap_vararg(xi); + if (vy && !vx) + yi = jl_unwrap_vararg(yi); + jl_varbinding_t *xb=NULL, *yb=NULL; + if (vx && vy && lx != ly) { + // {A^n...,Vararg{T,N}} ∩ {Vararg{S,M}} = {(A∩S)^n...,Vararg{T∩S,N}} plus N = M-n + jl_value_t *xlen = jl_tparam1(jl_unwrap_unionall(xi)); + if (jl_is_typevar(xlen)) { + xb = lookup(e, (jl_tvar_t*)xlen); + if (xb) + xb->offset = ly-lx; + } + jl_value_t *ylen = jl_tparam1(jl_unwrap_unionall(yi)); + if (jl_is_typevar(ylen)) { + yb = lookup(e, (jl_tvar_t*)ylen); + if (yb) + yb->offset = lx-ly; + } + } + jl_value_t *ii = intersect(xi, yi, e, param == 0 ? 1 : param); + if (xb) xb->offset = 0; + if (yb) yb->offset = 0; + if (ii == jl_bottom_type) { + if (vx && vy) { + int len = i > j ? i : j; + if ((xb && jl_is_long(xb->lb) && lx-1+jl_unbox_long(xb->lb) > len) || + (yb && jl_is_long(yb->lb) && ly-1+jl_unbox_long(yb->lb) > len)) + res = jl_bottom_type; + else + res = (jl_value_t*)jl_apply_tuple_type_v(jl_svec_data(params), len); + } + else { + res = jl_bottom_type; + } + break; + } + jl_svecset(params, (i > j ? i : j), ii); + if (vx && vy) + break; + if (i < lx-1 || !vx) i++; + if (j < ly-1 || !vy) j++; + } + // TODO: handle Vararg with explicit integer length parameter + if (res == NULL) + res = (jl_value_t*)jl_apply_tuple_type(params); + JL_GC_POP(); + return res; +} + +static void flip_vars(jl_stenv_t *e) +{ + jl_varbinding_t *btemp = e->vars; + while (btemp != NULL) { + btemp->right = !btemp->right; + btemp = btemp->prev; + } +} + +// intersection where xd nominally inherits from yd +static jl_value_t *intersect_sub_datatype(jl_datatype_t *xd, jl_datatype_t *yd, jl_stenv_t *e, int R, int param) +{ + jl_value_t *isuper = R ? intersect((jl_value_t*)yd, (jl_value_t*)xd->super, e, param) : + intersect((jl_value_t*)xd->super, (jl_value_t*)yd, e, param); + if (isuper == jl_bottom_type) return jl_bottom_type; + if (jl_nparams(xd) == 0 || jl_nparams(xd->super) == 0) + return (jl_value_t*)xd; + jl_value_t *super_pattern=NULL; + JL_GC_PUSH2(&isuper, &super_pattern); + jl_value_t *wrapper = xd->name->wrapper; + super_pattern = jl_rewrap_unionall((jl_value_t*)((jl_datatype_t*)jl_unwrap_unionall(wrapper))->super, + wrapper); + int envsz = jl_subtype_env_size(super_pattern); + jl_value_t **env = (jl_value_t**)alloca(envsz * sizeof(jl_value_t*)); // TODO root this + jl_value_t *ii; + jl_stenv_t tempe; + init_stenv(&tempe, env, envsz); + tempe.ignore_free = 1; + if (!subtype_in_env(isuper, super_pattern, &tempe)) + ii = jl_bottom_type; + else + ii = jl_apply_type(wrapper, env, envsz); + JL_GC_POP(); + return ii; +} + +static jl_value_t *intersect_invariant(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) +{ + if (!jl_has_free_typevars(x) && !jl_has_free_typevars(y)) { + return (jl_subtype(x,y) && jl_subtype(y,x)) ? y : NULL; + } + e->invdepth++; + jl_value_t *ii = intersect(x, y, e, 2); + e->invdepth--; + if (jl_is_typevar(x) && jl_is_typevar(y) && (jl_is_typevar(ii) || !jl_is_type(ii))) + return ii; + if (e->Runions.more) + return NULL; + if (ii == jl_bottom_type) { + if (!subtype_in_env(x, ii, e)) + return NULL; + flip_vars(e); + if (!subtype_in_env(y, ii, e)) + ii = NULL; + flip_vars(e); + return ii; + } + jl_value_t *root=NULL; + int8_t *buf; + JL_GC_PUSH2(&ii, &root); + save_env(e, &root, &buf); + if (!subtype_in_env(x, y, e)) { + ii = NULL; + } + else { + flip_vars(e); + if (!subtype_in_env(y, x, e)) + ii = NULL; + flip_vars(e); + } + restore_env(e, root, buf); + free(buf); + JL_GC_POP(); + return ii; +} + +// intersection where x == Type{...} and y is not +static jl_value_t *intersect_type_type(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int8_t R) +{ + jl_value_t *p0 = jl_tparam0(x); + if (!jl_is_typevar(p0)) + return (jl_typeof(p0) == y) ? x : jl_bottom_type; + if (!is_kind(y)) return jl_bottom_type; + jl_value_t *ii = R ? intersect_invariant(y, jl_tparam0(x), e) : intersect_invariant(jl_tparam0(x), y, e); + // NOTE: we cannot express e.g. DataType ∩ (UnionAll T<:Integer Type{T}), so returning `x` + // here is a conservative over-estimate. + if (ii == NULL) return x; + if (ii == y) return ii; + return (jl_value_t*)jl_wrap_Type(ii); +} + +// `param` means we are currently looking at a parameter of a type constructor +// (as opposed to being outside any type constructor, or comparing variable bounds). +// this is used to record the positions where type variables occur for the +// diagonal rule (record_var_occurrence). +static jl_value_t *intersect(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param) +{ + if (x == y) return y; + if (x == jl_ANY_flag) x = (jl_value_t*)jl_any_type; + if (y == jl_ANY_flag) y = (jl_value_t*)jl_any_type; + if (jl_is_typevar(x)) { + if (jl_is_typevar(y)) { + jl_varbinding_t *xx = lookup(e, (jl_tvar_t*)x); + jl_varbinding_t *yy = lookup(e, (jl_tvar_t*)y); + int R = 0; + if (xx && yy && var_outside(e, (jl_tvar_t*)x, (jl_tvar_t*)y)) { + // to preserve variable identities correctly, always accumulate bounds + // on the outer variable, return the outer variable, and set the inner + // variable equal to the outer variable. + jl_value_t *temp; jl_varbinding_t *tvb; + temp = x; x = y; y = temp; + tvb = xx; xx = yy; yy = tvb; + R = 1; + } + if (param == 2) { + jl_value_t *xlb = xx ? xx->lb : ((jl_tvar_t*)x)->lb; + jl_value_t *xub = xx ? xx->ub : ((jl_tvar_t*)x)->ub; + jl_value_t *ylb = yy ? yy->lb : ((jl_tvar_t*)y)->lb; + jl_value_t *yub = yy ? yy->ub : ((jl_tvar_t*)y)->ub; + record_var_occurrence(xx, e, param); + if (xx && yy && xx->depth0 != yy->depth0) { + record_var_occurrence(yy, e, param); + return subtype_in_env(yy->ub, yy->lb, e) ? y : jl_bottom_type; + } + if (xub == xlb && jl_is_typevar(xub)) { + if (y == xub) { + record_var_occurrence(yy, e, param); + return y; + } + return intersect(y, xub, e, param); + } + record_var_occurrence(yy, e, param); + if (!jl_is_type(ylb) && !jl_is_typevar(ylb)) { + if (xx) + return set_var_to_const(xx, ylb, yy); + if ((xlb == jl_bottom_type && xub == (jl_value_t*)jl_any_type) || jl_egal(xlb, ylb)) + return ylb; + return jl_bottom_type; + } + if (!jl_is_type(xlb) && !jl_is_typevar(xlb)) { + if (yy) + return set_var_to_const(yy, xlb, xx); + if (ylb == jl_bottom_type && yub == (jl_value_t*)jl_any_type) + return xlb; + return jl_bottom_type; + } + if (!(subtype_in_env(xlb, yub, e) && subtype_in_env(ylb, xub, e))) + return jl_bottom_type; + jl_value_t *ub=NULL, *lb=NULL; + JL_GC_PUSH2(&lb, &ub); + ub = intersect_ufirst(xub, yub, e, xx->depth0); + lb = simple_join(xlb, ylb); + assert(yy); + yy->lb = lb; + yy->ub = ub; + xx->lb = y; + xx->ub = y; + assert(yy->ub != y); + assert(xx->ub != x); + JL_GC_POP(); + return y; + } + record_var_occurrence(xx, e, param); + record_var_occurrence(yy, e, param); + if (xx->concrete && !yy->concrete) { + return intersect_var((jl_tvar_t*)x, y, e, R, param); + } + return intersect_var((jl_tvar_t*)y, x, e, !R, param); + } + record_var_occurrence(lookup(e, (jl_tvar_t*)x), e, param); + return intersect_var((jl_tvar_t*)x, y, e, 0, param); + } + if (jl_is_typevar(y)) { + record_var_occurrence(lookup(e, (jl_tvar_t*)y), e, param); + return intersect_var((jl_tvar_t*)y, x, e, 1, param); + } + if (!jl_has_free_typevars(x) && !jl_has_free_typevars(y)) { + if (jl_subtype(x, y)) + return x; + if (jl_subtype(y, x)) + return y; + } + if (jl_is_uniontype(x)) { + if (y == ((jl_uniontype_t*)x)->a || y == ((jl_uniontype_t*)x)->b) + return y; + return intersect_union(y, (jl_uniontype_t*)x, e, 0, param); + } + if (jl_is_uniontype(y)) { + if (x == ((jl_uniontype_t*)y)->a || x == ((jl_uniontype_t*)y)->b) + return x; + if (jl_is_unionall(x)) + return intersect_unionall(y, (jl_unionall_t*)x, e, 0, param); + return intersect_union(x, (jl_uniontype_t*)y, e, 1, param); + } + if (jl_is_unionall(x)) { + if (jl_is_unionall(y)) { + jl_value_t *a=NULL, *b=jl_bottom_type, *res=NULL; + JL_GC_PUSH2(&a,&b); + jl_value_t *unused; int8_t *buf; + save_env(e, &unused, &buf); + a = intersect_unionall(y, (jl_unionall_t*)x, e, 0, param); + if (jl_is_unionall(a)) { + jl_unionall_t *ua = (jl_unionall_t*)a; + if (jl_is_unionall(ua->body)) { + jl_unionall_t *ub = (jl_unionall_t*)ua->body; + if (jl_has_typevar(ub->var->ub, ua->var) || + jl_has_typevar(ub->var->lb, ua->var)) { + restore_env(e, NULL, buf); // restore counts + b = intersect_unionall(x, (jl_unionall_t*)y, e, 1, param); + } + } + } + free(buf); + if (!jl_has_free_typevars(a) && !jl_has_free_typevars(b)) { + if (jl_subtype(a, b)) + res = b; + else if (jl_subtype(b, a)) + res = a; + } + if (!res) res = simple_join(a, b); + JL_GC_POP(); + return res; + } + return intersect_unionall(y, (jl_unionall_t*)x, e, 0, param); + } + if (jl_is_unionall(y)) + return intersect_unionall(x, (jl_unionall_t*)y, e, 1, param); + if (jl_is_datatype(x) && jl_is_datatype(y)) { + jl_datatype_t *xd = (jl_datatype_t*)x, *yd = (jl_datatype_t*)y; + if (param < 2) { + if (x == (jl_value_t*)jl_any_type) return y; + if (y == (jl_value_t*)jl_any_type) return x; + if (jl_is_type_type(x)) { + if (!jl_is_type_type(y)) + return intersect_type_type(x, y, e, 0); + } + else if (jl_is_type_type(y)) { + return intersect_type_type(y, x, e, 1); + } + } + if (xd->name == yd->name) { + if (jl_is_tuple_type(xd)) + return intersect_tuple(xd, yd, e, param); + if (jl_is_vararg_type(x)) { + // Vararg: covariant in first parameter, invariant in second + jl_value_t *xp1=jl_tparam0(xd), *xp2=jl_tparam1(xd), *yp1=jl_tparam0(yd), *yp2=jl_tparam1(yd); + // in Vararg{T1} <: Vararg{T2}, need to check subtype twice to + // simulate the possibility of multiple arguments, which is needed + // to implement the diagonal rule correctly. + if (intersect(xp1, yp1, e, param==0 ? 1 : param) == jl_bottom_type) + return jl_bottom_type; + jl_value_t *i2=NULL, *ii = intersect(xp1, yp1, e, 1); + if (ii == jl_bottom_type) return jl_bottom_type; + JL_GC_PUSH2(&ii, &i2); + // Vararg{T,N} <: Vararg{T2,N2}; equate N and N2 + i2 = intersect_invariant(xp2, yp2, e); + if (i2 == NULL) + ii = jl_bottom_type; + else + ii = jl_apply_type2((jl_value_t*)jl_vararg_type, ii, i2); + JL_GC_POP(); + return ii; + } + size_t i, np = jl_nparams(xd); + jl_value_t **newparams; + JL_GC_PUSHARGS(newparams, np); + for (i=0; i < np; i++) { + jl_value_t *xi = jl_tparam(xd, i), *yi = jl_tparam(yd, i); + jl_value_t *ii = intersect_invariant(xi, yi, e); + if (ii == NULL) + break; + newparams[i] = ii; + } + jl_value_t *res; + if (i < np) + res = jl_bottom_type; + else + res = jl_apply_type(xd->name->wrapper, newparams, np); + JL_GC_POP(); + return res; + } + if (param == 2) return jl_bottom_type; + while (xd != jl_any_type && xd->name != yd->name) + xd = xd->super; + if (xd == jl_any_type) { + xd = (jl_datatype_t*)x; + while (yd != jl_any_type && yd->name != xd->name) + yd = yd->super; + if (yd == jl_any_type) + return jl_bottom_type; + return intersect_sub_datatype((jl_datatype_t*)y, xd, e, 1, param); + } + return intersect_sub_datatype((jl_datatype_t*)x, yd, e, 0, param); + } + if (jl_egal(x, y)) return y; + return jl_bottom_type; +} + +static jl_value_t *intersect_all(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int8_t anyunions) +{ + int i; + jl_value_t *is[2] = {jl_bottom_type,jl_bottom_type}; + JL_GC_PUSH2(&is[0], &is[1]); + for (i=0; i <= anyunions; i++) { + if (e->Runions.stacksize > 0) + statestack_set(&e->Runions, e->Runions.stacksize-1, i); + e->Runions.depth = 0; + e->Runions.more = 0; + jl_value_t *ii = intersect(x, y, e, 0); + if (e->Runions.more) { + statestack_push(&e->Runions, 0); + ii = intersect_all(x, y, e, 1); + statestack_pop(&e->Runions); + } + is[i] = ii; + } + jl_value_t *res = jl_type_union(is, 2); + JL_GC_POP(); + return res; +} + +// type intersection entry points + +JL_DLLEXPORT jl_value_t *jl_intersect_types(jl_value_t *x, jl_value_t *y) +{ + jl_stenv_t e; + init_stenv(&e, NULL, 0); + e.intersection = 1; + return intersect_all(x, y, &e, 0); +} + +jl_value_t *jl_type_intersection_matching(jl_value_t *a, jl_value_t *b, + jl_svec_t **penv, jl_svec_t *tvars) +{ + int sza = jl_subtype_env_size(a); + int szb = jl_subtype_env_size(b); + int sz = 0, i = 0; + jl_value_t **env = (jl_value_t**)alloca((sza>szb?sza:szb)*sizeof(jl_value_t*)); + jl_value_t *ans = b; + if (jl_subtype_env(a, b, env, szb)) { + ans = a; + sz = szb; + } + else if (jl_subtype(b, a)) { + } + else if (jl_is_leaf_type(a) || jl_is_leaf_type(b)) { + return jl_bottom_type; + } + if (sz == 0) { + sz = szb; + while (jl_is_unionall(b)) { + env[i++] = (jl_value_t*)((jl_unionall_t*)b)->var; + b = ((jl_unionall_t*)b)->body; + } + } + jl_svec_t *e = jl_alloc_svec(sz); + *penv = e; + for(i=0; i < sz; i++) + jl_svecset(e, i, env[i]); + return ans; +} + +JL_DLLEXPORT jl_value_t *jl_type_intersection(jl_value_t *a, jl_value_t *b) +{ + if (jl_subtype(a, b)) + return a; + if (jl_subtype(b, a)) + return b; + if (jl_is_leaf_type(a) || jl_is_leaf_type(b)) + return jl_bottom_type; + return b; +} diff --git a/src/task.c b/src/task.c index c89fbaca3983a..7b2ce67637292 100644 --- a/src/task.c +++ b/src/task.c @@ -659,32 +659,33 @@ jl_function_t *jl_unprotect_stack_func; void jl_init_tasks(void) { _probe_arch(); - jl_task_type = jl_new_datatype(jl_symbol("Task"), - jl_any_type, - jl_emptysvec, - jl_svec(13, - jl_symbol("parent"), - jl_symbol("storage"), - jl_symbol("state"), - jl_symbol("consumers"), - jl_symbol("donenotify"), - jl_symbol("result"), - jl_symbol("exception"), - jl_symbol("backtrace"), - jl_symbol("code"), - jl_symbol("ctx"), - jl_symbol("bufsz"), - jl_symbol("stkbuf"), - jl_symbol("ssize")), - jl_svec(13, - jl_any_type, - jl_any_type, jl_sym_type, - jl_any_type, jl_any_type, - jl_any_type, jl_any_type, - jl_any_type, jl_any_type, - jl_tupletype_fill(sizeof(jl_jmp_buf), (jl_value_t*)jl_uint8_type), - jl_long_type, jl_voidpointer_type, jl_long_type), - 0, 1, 8); + jl_task_type = (jl_datatype_t*) + jl_new_datatype(jl_symbol("Task"), + jl_any_type, + jl_emptysvec, + jl_svec(13, + jl_symbol("parent"), + jl_symbol("storage"), + jl_symbol("state"), + jl_symbol("consumers"), + jl_symbol("donenotify"), + jl_symbol("result"), + jl_symbol("exception"), + jl_symbol("backtrace"), + jl_symbol("code"), + jl_symbol("ctx"), + jl_symbol("bufsz"), + jl_symbol("stkbuf"), + jl_symbol("ssize")), + jl_svec(13, + jl_any_type, + jl_any_type, jl_sym_type, + jl_any_type, jl_any_type, + jl_any_type, jl_any_type, + jl_any_type, jl_any_type, + jl_tupletype_fill(sizeof(jl_jmp_buf), (jl_value_t*)jl_uint8_type), + jl_long_type, jl_voidpointer_type, jl_long_type), + 0, 1, 8); jl_svecset(jl_task_type->types, 0, (jl_value_t*)jl_task_type); done_sym = jl_symbol("done"); diff --git a/src/toplevel.c b/src/toplevel.c index 301b8ba8fe38a..1f3d44a02f557 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -686,29 +686,6 @@ JL_DLLEXPORT jl_value_t *jl_load_(jl_value_t *str) extern int jl_boot_file_loaded; -static int type_contains(jl_value_t *ty, jl_value_t *x); -static int svec_contains(jl_svec_t *svec, jl_value_t *x) -{ - assert(jl_is_svec(svec)); - size_t i, l=jl_svec_len(svec); - for(i=0; i < l; i++) { - jl_value_t *e = jl_svecref(svec, i); - if (e==x || type_contains(e, x)) - return 1; - } - return 0; -} - -static int type_contains(jl_value_t *ty, jl_value_t *x) -{ - if (ty == x) return 1; - if (jl_is_uniontype(ty)) - return svec_contains((jl_svec_t*)jl_fieldref(ty,0), x); - if (jl_is_datatype(ty)) - return svec_contains(((jl_datatype_t*)ty)->parameters, x); - return 0; -} - void print_func_loc(JL_STREAM *s, jl_method_t *m); void jl_check_static_parameter_conflicts(jl_method_t *m, jl_svec_t *t) @@ -776,21 +753,17 @@ static jl_datatype_t *first_arg_datatype(jl_value_t *a, int got_tuple1) else if (jl_is_typevar(a)) { return first_arg_datatype(((jl_tvar_t*)a)->ub, got_tuple1); } - else if (jl_is_typector(a)) { - return first_arg_datatype(((jl_typector_t*)a)->body, got_tuple1); + else if (jl_is_unionall(a)) { + return first_arg_datatype(((jl_unionall_t*)a)->body, got_tuple1); } else if (jl_is_uniontype(a)) { - jl_svec_t *ts = ((jl_uniontype_t*)a)->types; - if (jl_svec_len(ts) == 0) return NULL; - jl_datatype_t *dt = first_arg_datatype(jl_svecref(ts,0), got_tuple1); - if (dt == NULL) return NULL; - int i; - for(i=1; i < jl_svec_len(ts); i++) { - jl_datatype_t *ti = first_arg_datatype(jl_svecref(ts,i), got_tuple1); - if (ti==NULL || ti->name != dt->name) - return NULL; - } - return dt; + jl_uniontype_t *u = (jl_uniontype_t*)a; + jl_datatype_t *d1 = first_arg_datatype(u->a, got_tuple1); + if (d1 == NULL) return NULL; + jl_datatype_t *d2 = first_arg_datatype(u->b, got_tuple1); + if (d2 == NULL || d1->name != d2->name) + return NULL; + return d1; } return NULL; } @@ -840,7 +813,7 @@ JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, mt = ftype->name->mt; name = mt->name; - if (jl_subtype((jl_value_t*)ftype, (jl_value_t*)jl_builtin_type, 0)) + if (jl_subtype((jl_value_t*)ftype, (jl_value_t*)jl_builtin_type)) jl_error("cannot add methods to a builtin function"); m = jl_new_method(f, name, argtype, nargs, isva, tvars, isstaged == jl_true); @@ -873,7 +846,7 @@ JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_value_t *tv = jl_svecref(tvars,i); if (!jl_is_typevar(tv)) jl_type_error_rt(jl_symbol_name(name), "method definition", (jl_value_t*)jl_tvar_type, tv); - if (!ishidden && !type_contains((jl_value_t*)argtype, tv)) { + if (!ishidden && !jl_has_typevar((jl_value_t*)argtype, (jl_tvar_t*)tv)) { jl_printf(JL_STDERR, "WARNING: static parameter %s does not occur in signature for %s", jl_symbol_name(((jl_tvar_t*)tv)->name), jl_symbol_name(name)); diff --git a/src/typemap.c b/src/typemap.c index e4d911c1881a8..c280e0ac21d1e 100644 --- a/src/typemap.c +++ b/src/typemap.c @@ -19,10 +19,13 @@ extern "C" { // compute whether the specificity of this type is equivalent to Any in the sort order static int jl_is_any(jl_value_t *t1) { - return (t1 == (jl_value_t*)jl_any_type || + return (t1 == (jl_value_t*)jl_any_type || t1 == jl_ANY_flag); + // TODO jb/subtype + /* (jl_is_typevar(t1) && ((jl_tvar_t*)t1)->ub == (jl_value_t*)jl_any_type && !((jl_tvar_t*)t1)->bound)); + */ } // ----- Type Signature Subtype Testing ----- // @@ -57,7 +60,7 @@ static int sig_match_by_type_simple(jl_value_t **types, size_t n, jl_tupletype_t // analogous to the situation with tuples. } else if (jl_is_typevar(tp0)) { - if (!jl_subtype(jl_tparam0(a), ((jl_tvar_t*)tp0)->ub, 0)) + if (!jl_subtype(jl_tparam0(a), ((jl_tvar_t*)tp0)->ub)) return 0; } else { @@ -72,7 +75,7 @@ static int sig_match_by_type_simple(jl_value_t **types, size_t n, jl_tupletype_t return 0; } } - else if (decl == (jl_value_t*)jl_any_type) { + else if (decl == (jl_value_t*)jl_any_type || decl == jl_ANY_flag) { } else { if (jl_is_type_type(a)) // decl is not Type, because it would be caught above @@ -82,14 +85,14 @@ static int sig_match_by_type_simple(jl_value_t **types, size_t n, jl_tupletype_t } } if (va) { - jl_value_t *decl = jl_field_type(sig, i); + jl_value_t *decl = jl_unwrap_unionall(jl_field_type(sig, i)); if (jl_vararg_kind(decl) == JL_VARARG_INT) { if (n-i != jl_unbox_long(jl_tparam1(decl))) return 0; } jl_value_t *t = jl_tparam0(decl); for(; i < n; i++) { - if (!jl_subtype(types[i], t, 0)) + if (!jl_subtype(types[i], t)) return 0; } return 1; @@ -124,7 +127,7 @@ static inline int sig_match_simple(jl_value_t **args, size_t n, jl_value_t **sig for (i = 0; i < lensig; i++) { jl_value_t *decl = sig[i]; jl_value_t *a = args[i]; - if (decl == (jl_value_t*)jl_any_type) { + if (decl == (jl_value_t*)jl_any_type || decl == jl_ANY_flag) { } else if ((jl_value_t*)jl_typeof(a) == decl) { /* @@ -140,7 +143,7 @@ static inline int sig_match_simple(jl_value_t **args, size_t n, jl_value_t **sig // analogous to the situation with tuples. } else if (jl_is_typevar(tp0)) { - if (!jl_subtype(a, ((jl_tvar_t*)tp0)->ub, 0)) + if (!jl_subtype(a, ((jl_tvar_t*)tp0)->ub)) return 0; } else { @@ -158,9 +161,9 @@ static inline int sig_match_simple(jl_value_t **args, size_t n, jl_value_t **sig if (n-i != jl_unbox_long(jl_tparam1(decl))) return 0; } - jl_value_t *t = jl_tparam0(decl); + jl_value_t *t = jl_unwrap_vararg(decl); for(; i < n; i++) { - if (!jl_subtype(args[i], t, 1)) + if (!jl_isa(args[i], t)) return 0; } return 1; @@ -220,14 +223,14 @@ static jl_array_t *jl_alloc_int_1d(size_t np, size_t len) else if (np < 0xFFFF) { static jl_value_t *int16 = NULL; if (int16 == NULL) - int16 = jl_apply_array_type(jl_uint16_type, 1); + int16 = jl_apply_array_type((jl_value_t*)jl_uint16_type, 1); ty = int16; } else { assert(np < 0x7FFFFFFF); static jl_value_t *int32 = NULL; if (int32 == NULL) - int32 = jl_apply_array_type(jl_uint32_type, 1); + int32 = jl_apply_array_type((jl_value_t*)jl_uint32_type, 1); ty = int32; } jl_array_t *a = jl_alloc_array_1d(ty, len); @@ -254,7 +257,7 @@ union jl_typemap_t mtcache_hash_lookup(const struct jl_ordereddict_t *a, jl_valu } else { assert(jl_typeof(ml.unknown) == (jl_value_t*)jl_typemap_entry_type); - t = jl_field_type(ml.leaf->sig, offs); + t = jl_field_type(jl_unwrap_unionall(ml.leaf->sig), offs); if (tparam) t = jl_tparam0(t); } @@ -279,7 +282,7 @@ static void mtcache_rehash(struct jl_ordereddict_t *pa, size_t newlen, jl_value_ } else { assert(jl_typeof(ml.unknown) == (jl_value_t*)jl_typemap_entry_type); - t = jl_field_type(ml.leaf->sig, offs); + t = jl_field_type(jl_unwrap_unionall(ml.leaf->sig), offs); if (tparam) t = jl_tparam0(t); } @@ -327,7 +330,7 @@ static union jl_typemap_t *mtcache_hash_bp(struct jl_ordereddict_t *pa, jl_value { if (jl_is_datatype(ty)) { uintptr_t uid = ((jl_datatype_t*)ty)->uid; - if (!uid || is_kind(ty) || jl_has_typevars(ty)) + if (!uid || is_kind(ty) || jl_has_free_typevars(ty)) // be careful not to put non-leaf types or DataType/TypeConstructor in the cache here, // since they should have a lower priority and need to go into the sorted list return NULL; @@ -357,7 +360,7 @@ static union jl_typemap_t *mtcache_hash_bp(struct jl_ordereddict_t *pa, jl_value } else { assert(jl_typeof(pml->unknown) == (jl_value_t*)jl_typemap_entry_type); - t = jl_field_type(pml->leaf->sig, offs); + t = jl_field_type(jl_unwrap_unionall(pml->leaf->sig), offs); if (tparam) t = jl_tparam0(t); } @@ -390,7 +393,7 @@ jl_value_t *jl_lookup_match(jl_value_t *a, jl_value_t *b, jl_svec_t **penv, jl_s issue #5254 */ if (val == (jl_value_t*)jl_bottom_type) { - if (!jl_subtype(a, ti, 0)) { + if (!jl_subtype(a, ti)) { JL_GC_POP(); return (jl_value_t*)jl_bottom_type; } @@ -461,7 +464,7 @@ static int jl_typemap_intersection_array_visitor(struct jl_ordereddict_t *a, jl_ t = ml.node->key; } else { - t = jl_field_type(ml.leaf->sig, offs); + t = jl_field_type(jl_unwrap_unionall(ml.leaf->sig), offs); if (tparam) t = jl_tparam0(t); } @@ -469,10 +472,8 @@ static int jl_typemap_intersection_array_visitor(struct jl_ordereddict_t *a, jl_ (tparam ? // need to compute `ty <: Type{t}` (jl_is_uniontype(ty) || // punt on Union{...} right now jl_typeof(t) == ty || // deal with kinds (e.g. ty == DataType && t == Type{t}) - (jl_is_type_type(ty) && (jl_is_typevar(jl_tparam0(ty)) ? - jl_subtype(t, ((jl_tvar_t*)jl_tparam0(ty))->ub, 0) : // deal with ty == Type{<:T} - jl_subtype(t, jl_tparam0(ty), 0)))) // deal with ty == Type{T{#<:T}} - : jl_subtype(t, ty, 0))) // `t` is a leaftype, so intersection test becomes subtype + jl_isa(t, ty)) // deal with ty == Type{T} + : jl_subtype(t, ty))) // `t` is a leaftype, so intersection test becomes subtype if (!jl_typemap_intersection_visitor(ml, offs+1, closure)) return 0; } @@ -526,17 +527,18 @@ int jl_typemap_intersection_visitor(union jl_typemap_t map, int offs, if (jl_typeof(map.unknown) == (jl_value_t*)jl_typemap_level_type) { jl_typemap_level_t *cache = map.node; jl_value_t *ty = NULL; - size_t l = jl_field_count(closure->type); + jl_value_t *ttypes = jl_unwrap_unionall(closure->type); + size_t l = jl_field_count(ttypes); if (closure->va && l <= offs + 1) { ty = closure->va; } else if (l > offs) { - ty = jl_tparam(closure->type, offs); + ty = jl_tparam(ttypes, offs); } if (ty) { if (cache->targ.values != (void*)jl_nothing) { jl_value_t *typetype = jl_is_type_type(ty) ? jl_tparam0(ty) : NULL; - if (typetype && !jl_has_typevars(typetype)) { + if (typetype && !jl_has_free_typevars(typetype)) { if (is_cache_leaf(typetype)) { // direct lookup of leaf types union jl_typemap_t ml = mtcache_hash_lookup(&cache->targ, typetype, 1, offs); @@ -580,10 +582,7 @@ int sigs_eq(jl_value_t *a, jl_value_t *b, int useenv) // useenv == 0 : subtyping + ensure typevars correspond // useenv == 1 : subtyping + ensure typevars correspond + fail if bound != bound in some typevar match // useenv == 2 : ignore typevars (because UnionAll getting lost in intersection can cause jl_types_equal to fail in the wrong direction for some purposes) - if (useenv != 2 && (jl_has_typevars(a) || jl_has_typevars(b))) { - return jl_types_equal_generic(a, b, useenv); - } - return jl_subtype(a, b, 0) && jl_subtype(b, a, 0); + return jl_types_equal(a, b); } /* @@ -604,7 +603,7 @@ static jl_typemap_entry_t *jl_typemap_assoc_by_type_(jl_typemap_entry_t *ml, jl_ for (; ml != (void*)jl_nothing; ml = ml->next) { if (world < ml->min_world || world > ml->max_world) continue; // ignore replaced methods - size_t lensig = jl_field_count(ml->sig); + size_t lensig = jl_field_count(jl_unwrap_unionall(ml->sig)); if (lensig == n || (ml->va && lensig <= n+1)) { int resetenv = 0, ismatch = 1; if (ml->simplesig != (void*)jl_nothing) { @@ -625,11 +624,8 @@ static jl_typemap_entry_t *jl_typemap_assoc_by_type_(jl_typemap_entry_t *ml, jl_ else if (ml->issimplesig && !typesisva) ismatch = sig_match_by_type_simple(jl_svec_data(types->parameters), n, ml->sig, lensig, ml->va); - else if (ml->tvars == jl_emptysvec) - ismatch = jl_tuple_subtype(jl_svec_data(types->parameters), n, ml->sig, 0); - else if (penv == NULL) { - ismatch = jl_type_match((jl_value_t*)types, (jl_value_t*)ml->sig) != (jl_value_t*)jl_false; - } + else if (ml->tvars == jl_emptysvec || penv == NULL) + ismatch = jl_subtype((jl_value_t*)types, (jl_value_t*)ml->sig); else { // TODO: this is missing the actual subtype test, // which works currently because types is typically a leaf tt, @@ -673,7 +669,7 @@ static jl_typemap_entry_t *jl_typemap_assoc_by_type_(jl_typemap_entry_t *ml, jl_ size_t i, l; for (i = 0, l = jl_svec_len(ml->guardsigs); i < l; i++) { // see corresponding code in jl_typemap_assoc_exact - if (jl_subtype((jl_value_t*)types, jl_svecref(ml->guardsigs, i), 0)) { + if (jl_subtype((jl_value_t*)types, jl_svecref(ml->guardsigs, i))) { ismatch = 0; break; } @@ -711,13 +707,14 @@ jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_ jl_typemap_level_t *cache = ml_or_cache.node; // called object is the primary key for constructors, otherwise first argument jl_value_t *ty = NULL; - size_t l = jl_field_count(types); + jl_value_t *ttypes = jl_unwrap_unionall(types); + size_t l = jl_field_count(ttypes); int isva = 0; // compute the type at offset `offs` into `types`, which may be a Vararg if (l <= offs + 1) { - ty = jl_tparam(types, l - 1); + ty = jl_tparam(ttypes, l - 1); if (jl_is_vararg_type(ty)) { - ty = jl_tparam0(ty); + ty = jl_unwrap_vararg(ty); isva = 1; } else if (l <= offs) { @@ -725,7 +722,7 @@ jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_ } } else if (l > offs) { - ty = jl_tparam(types, offs); + ty = jl_tparam(ttypes, offs); } // If there is a type at offs, look in the optimized caches if (!subtype) { @@ -829,7 +826,7 @@ jl_typemap_entry_t *jl_typemap_entry_assoc_exact(jl_typemap_entry_t *ml, jl_valu continue; } else { - if (!jl_tuple_subtype(args, n, ml->sig, 1)) + if (!jl_tuple_isa(args, n, ml->sig)) continue; } @@ -839,7 +836,7 @@ jl_typemap_entry_t *jl_typemap_entry_assoc_exact(jl_typemap_entry_t *ml, jl_valu // checking guard entries require a more // expensive subtype check, since guard entries added for ANY might be // abstract. this fixed issue #12967. - if (jl_tuple_subtype(args, n, (jl_tupletype_t*)jl_svecref(ml->guardsigs, i), 1)) { + if (jl_tuple_isa(args, n, (jl_tupletype_t*)jl_svecref(ml->guardsigs, i))) { goto nomatch; } } @@ -974,22 +971,23 @@ static int jl_typemap_array_insert_(struct jl_ordereddict_t *cache, jl_value_t * static void jl_typemap_level_insert_(jl_typemap_level_t *cache, jl_typemap_entry_t *newrec, int8_t offs, const struct jl_typemap_info *tparams) { - size_t l = jl_field_count(newrec->sig); + jl_value_t *ttypes = jl_unwrap_unionall(newrec->sig); + size_t l = jl_field_count(ttypes); // compute the type at offset `offs` into `sig`, which may be a Vararg jl_value_t *t1 = NULL; int isva = 0; if (l <= offs + 1) { - t1 = jl_tparam(newrec->sig, l - 1); + t1 = jl_tparam(ttypes, l - 1); if (jl_is_vararg_type(t1)) { isva = 1; - t1 = jl_tparam0(t1); + t1 = jl_unwrap_vararg(t1); } else if (l <= offs) { t1 = NULL; } } else if (l > offs) { - t1 = jl_tparam(newrec->sig, offs); + t1 = jl_tparam(ttypes, offs); } // If the type at `offs` is Any, put it in the Any list if (t1 && jl_is_any(t1)) @@ -1020,10 +1018,9 @@ jl_typemap_entry_t *jl_typemap_insert(union jl_typemap_t *cache, jl_value_t *par { jl_ptls_t ptls = jl_get_ptls_states(); assert(min_world > 0 && max_world > 0); - assert(jl_is_tuple_type(type)); - if (!simpletype) { + if (!simpletype) simpletype = (jl_tupletype_t*)jl_nothing; - } + jl_value_t *ttype = jl_unwrap_unionall(type); if ((jl_value_t*)simpletype == jl_nothing) { jl_typemap_entry_t *ml = jl_typemap_assoc_by_type(*cache, type, NULL, 1, 0, offs, min_world); @@ -1050,17 +1047,18 @@ jl_typemap_entry_t *jl_typemap_insert(union jl_typemap_t *cache, jl_value_t *par newrec->min_world = min_world; newrec->max_world = max_world; // compute the complexity of this type signature - newrec->va = jl_is_va_tuple(type); + newrec->va = jl_is_va_tuple(ttype); newrec->issimplesig = (tvars == jl_emptysvec); // a TypeVar environment needs an complex matching test newrec->isleafsig = newrec->issimplesig && !newrec->va; // entirely leaf types don't need to be sorted JL_GC_PUSH1(&newrec); + assert(jl_is_tuple_type(ttype)); size_t i, l; - for (i = 0, l = jl_field_count(type); i < l && newrec->issimplesig; i++) { - jl_value_t *decl = jl_field_type(type, i); + for (i = 0, l = jl_field_count(ttype); i < l && newrec->issimplesig; i++) { + jl_value_t *decl = jl_field_type(ttype, i); if (decl == (jl_value_t*)jl_datatype_type) newrec->isleafsig = 0; // Type{} may have a higher priority than DataType - else if (decl == (jl_value_t*)jl_typector_type) - newrec->isleafsig = 0; // Type{} may have a higher priority than TypeConstructor + else if (decl == (jl_value_t*)jl_unionall_type) + newrec->isleafsig = 0; // Type{} may have a higher priority than UnionAll else if (jl_is_type_type(decl)) newrec->isleafsig = 0; // Type{} may need special processing to compute the match else if (jl_is_vararg_type(decl)) @@ -1076,13 +1074,14 @@ jl_typemap_entry_t *jl_typemap_insert(union jl_typemap_t *cache, jl_value_t *par return newrec; } -static int has_unions(jl_tupletype_t *type) +static int has_unions(jl_value_t *type) { + type = jl_unwrap_unionall(type); int i; for (i = 0; i < jl_nparams(type); i++) { jl_value_t *t = jl_tparam(type, i); if (jl_is_uniontype(t) || - (jl_is_vararg_type(t) && jl_is_uniontype(jl_tparam0(t)))) + (jl_is_vararg_type(t) && jl_is_uniontype(jl_unwrap_vararg(t)))) return 1; } return 0; @@ -1098,7 +1097,7 @@ static void jl_typemap_list_insert_sorted(jl_typemap_entry_t **pml, jl_value_t * jl_value_t *pa = parent; while (l != (void*)jl_nothing) { if (!l->isleafsig) { // quickly ignore all of the leafsig entries (these were handled by caller) - if (jl_args_morespecific((jl_value_t*)newrec->sig, (jl_value_t*)l->sig)) { + if (jl_type_morespecific((jl_value_t*)newrec->sig, (jl_value_t*)l->sig)) { if (l->simplesig == (void*)jl_nothing || newrec->simplesig != (void*)jl_nothing || !sigs_eq((jl_value_t*)l->sig, (jl_value_t*)newrec->sig, 1)) { // might need to insert multiple entries for a lookup differing only by their simplesig @@ -1133,8 +1132,7 @@ static void jl_typemap_list_insert_sorted(jl_typemap_entry_t **pml, jl_value_t * pnext = &item->next; next_parent = (jl_value_t*)item; while (l != newrec->next) { - if (jl_args_morespecific((jl_value_t*)item->sig, - (jl_value_t*)l->sig)) { + if (jl_type_morespecific((jl_value_t*)item->sig, (jl_value_t*)l->sig)) { // reinsert item earlier in the list *pitem = next; jl_gc_wb(item_parent, next); diff --git a/test/subtype.jl b/test/subtype.jl index 30fea1e52837e..7468d189b0e27 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -10,6 +10,8 @@ issub_strict(x::ANY,y::ANY) = issub(x,y) && !issub(y,x) isequal_type(x::ANY,y::ANY) = issub(x,y) && issub(y,x) notequal_type(x::ANY,y::ANY) = !isequal_type(x, y) +_type_intersect(x::ANY, y::ANY) = ccall(:jl_intersect_types, Any, (Any, Any), x, y) + # level 1: no varags, union, UnionAll function test_1() @test issub_strict(Int, Integer) @@ -52,6 +54,15 @@ function test_2() @test !issub(Tuple{Int, Tuple{Real, Integer}}, Tuple{Vararg{Int}}) @test isequal_type(Tuple{Int,Int}, Tuple{Vararg{Int,2}}) + + @test Tuple{Int,Vararg{Int,2}} == Tuple{Int,Int,Int} + @test Tuple{Int,Vararg{Int,2}} === Tuple{Int,Int,Int} + @test Tuple{Any, Any} === Tuple{Vararg{Any,2}} + @test Tuple{Int,Vararg{Int,2}} == Tuple{Int,Int,Vararg{Int,1}} + @test Tuple{Int,Vararg{Int,2}} == Tuple{Int,Int,Int,Vararg{Int,0}} + @test !(Tuple{Int,Vararg{Int,2}} <: Tuple{Int,Int,Int,Vararg{Int,1}}) + @test Tuple{Int,Vararg{Int}} == Tuple{Int,Vararg{Int}} + @test (@UnionAll N Tuple{Int,Vararg{Int,N}}) == (@UnionAll N Tuple{Int,Vararg{Int,N}}) end function test_diagonal() @@ -202,6 +213,29 @@ function test_3() (@UnionAll T @UnionAll T<:S<:T Tuple{Ref{T},S})) @test issub_strict((@UnionAll T Tuple{Ref{T}, T}), (@UnionAll T @UnionAll S>:T Tuple{Ref{T}, S})) + + A = @UnionAll T Tuple{T,Ptr{T}} + B = @UnionAll T Tuple{Ptr{T},T} + + C = @UnionAll T>:Ptr @UnionAll S>:Ptr Tuple{Ptr{T},Ptr{S}} + D = @UnionAll T>:Ptr @UnionAll S>:Ptr{T} Tuple{Ptr{T},Ptr{S}} + E = @UnionAll T>:Ptr @UnionAll S>:Ptr{T} Tuple{Ptr{S},Ptr{T}} + + @test !issub(A, B) + @test !issub(B, A) + @test issub_strict(C, A) + @test issub_strict(C, B) + @test issub_strict(C, D) + @test issub_strict(Union{D,E}, A) + @test issub_strict(Union{D,E}, B) + @test issub_strict((@UnionAll T>:Ptr @UnionAll Ptr<:S<:Ptr Tuple{Ptr{T},Ptr{S}}), + (@UnionAll T>:Ptr @UnionAll S>:Ptr{T} Tuple{Ptr{T},Ptr{S}})) + @test !issub((@UnionAll T>:Ptr @UnionAll S>:Ptr Tuple{Ptr{T},Ptr{S}}), + (@UnionAll T>:Ptr @UnionAll Ptr{T}<:S<:Ptr Tuple{Ptr{T},Ptr{S}})) + + @test !issub((@UnionAll T>:Integer @UnionAll S>:Ptr Tuple{Ptr{T},Ptr{S}}), B) + + @test issub((@UnionAll T>:Ptr @UnionAll S>:Integer Tuple{Ptr{T},Ptr{S}}), B) end # level 4: Union @@ -291,6 +325,10 @@ function test_5() # required changing priority of unions and vars @test issub(Tuple{Array{u,1},Int}, @UnionAll T Tuple{Array{T,1}, T}) @test issub(Tuple{Array{u,1},Int}, @UnionAll T @UnionAll S<:T Tuple{Array{T,1}, S}) + + @test !issub(Ref{Union{Ref{Int},Ref{Int8}}}, @UnionAll T Ref{Ref{T}}) + @test issub(Tuple{Union{Ref{Int},Ref{Int8}}}, @UnionAll T Tuple{Ref{T}}) + @test !issub(Ref{Union{Ref{Int},Ref{Int8}}}, Union{Ref{Ref{Int}}, Ref{Ref{Int8}}}) end # tricky type variable lower bounds @@ -343,6 +381,7 @@ function test_6() # (@UnionAll x<:T<:x Q{T}) == Q{x} @test isequal_type(Ref{Ref{i}}, Ref{@UnionAll i<:T<:i Ref{T}}) + @test isequal_type(Ref{Ref{i}}, @UnionAll i<:T<:i Ref{Ref{T}}) @test isequal_type((@UnionAll i<:T<:i Ref{Ref{T}}), Ref{@UnionAll i<:T<:i Ref{T}}) @test !issub((@UnionAll i<:T<:i Ref{Ref{T}}), Ref{@UnionAll T<:i Ref{T}}) @@ -358,6 +397,71 @@ function test_6() @test issub(Ref{B}, @UnionAll BB<:U<:B Ref{U}) end +function test_Type() + @test issub_strict(DataType, Type) + @test issub_strict(Union, Type) + @test issub_strict(UnionAll, Type) + @test issub_strict(typeof(Bottom), Type) + @test !issub(TypeVar, Type) + @test !issub(Type, TypeVar) + @test !issub(DataType, @UnionAll T<:Number Type{T}) + @test issub_strict(Type{Int}, DataType) + @test !issub((@UnionAll T<:Integer Type{T}), DataType) + @test isequal_type(Type{AbstractArray}, Type{AbstractArray}) + @test !issub(Type{Int}, Type{Integer}) + @test issub((@UnionAll T<:Integer Type{T}), (@UnionAll T<:Number Type{T})) + @test isa(Int, @UnionAll T<:Number Type{T}) + @test !isa(DataType, @UnionAll T<:Number Type{T}) + + @test DataType <: (@UnionAll T<:Type Type{T}) + @test isa(Tuple{},Type{Tuple{}}) + @test !(Tuple{Int,} <: (@UnionAll T<:Tuple Type{T})) + @test isa(Tuple{Int}, (@UnionAll T<:Tuple Type{T})) +end + +# old subtyping tests from test/core.jl +function test_old() + @test Int8 <: Integer + @test Int32 <: Integer + @test Tuple{Int8,Int8} <: Tuple{Integer,Integer} + @test !(AbstractArray{Float64,2} <: AbstractArray{Number,2}) + @test !(AbstractArray{Float64,1} <: AbstractArray{Float64,2}) + @test Tuple{Integer,Vararg{Integer}} <: Tuple{Integer,Vararg{Real}} + @test Tuple{Integer,Float64,Vararg{Integer}} <: Tuple{Integer,Vararg{Number}} + @test Tuple{Integer,Float64} <: Tuple{Integer,Vararg{Number}} + @test Tuple{Int32,} <: Tuple{Vararg{Number}} + @test Tuple{} <: Tuple{Vararg{Number}} + @test !(Tuple{Vararg{Int32}} <: Tuple{Int32,}) + @test !(Tuple{Vararg{Int32}} <: Tuple{Number,Integer}) + @test !(Tuple{Vararg{Integer}} <: Tuple{Integer,Integer,Vararg{Integer}}) + @test !(Array{Int8,1} <: Array{Any,1}) + @test !(Array{Any,1} <: Array{Int8,1}) + @test Array{Int8,1} <: Array{Int8,1} + @test !(Type{Bottom} <: Type{Int32}) + @test !(Vector{Float64} <: Vector{Union{Float64,Float32}}) + + @test !isa(Array,Type{Any}) + @test Type{Complex} <: UnionAll + @test isa(Complex,Type{Complex}) + @test !(Type{Ptr{Bottom}} <: Type{Ptr}) + @test !(Type{Rational{Int}} <: Type{Rational}) + @test Tuple{} <: Tuple{Vararg} + @test Tuple{} <: @UnionAll N NTuple{N} + @test !(Type{Tuple{}} <: Type{Tuple{Vararg}}) + @test !(Type{Tuple{}} <: (@UnionAll N Type{NTuple{N}})) + + @test !(Type{Array{Integer}} <: Type{AbstractArray{Integer}}) + @test !(Type{Array{Integer}} <: Type{@UnionAll T<:Integer Array{T}}) + + # issue #6561 + # TODO: note that NTuple now means "tuples of all the same type" + #@test issubtype(Array{Tuple}, Array{NTuple}) + @test issub_strict(NTuple, Tuple) + #@test issubtype(Array{Tuple{Vararg{Any}}}, Array{NTuple}) + #@test issubtype(Array{Tuple{Vararg}}, Array{NTuple}) + @test !issubtype(Type{Tuple{Void}}, Tuple{Type{Void}}) +end + const menagerie = Any[Bottom, Any, Int, Int8, Integer, Real, Array{Int,1}, AbstractArray{Int,1}, @@ -447,8 +551,6 @@ function test_properties() end end -_type_intersect(x::ANY, y::ANY) = ccall(:jl_intersect_types, Any, (Any, Any), x, y) - macro testintersect(a, b, result) if isa(result,Expr) && result.head === :call && length(result.args)==2 && result.args[1] === :! result = result.args[2] @@ -502,21 +604,37 @@ function test_intersection() @testintersect((@UnionAll T Tuple{T, AbstractArray{T}}), Tuple{Int, Array{Number,1}}, Tuple{Int, Array{Number,1}}) + @testintersect((@UnionAll S Tuple{S,Vector{S}}), (@UnionAll T<:Real Tuple{T,AbstractVector{T}}), + (@UnionAll S<:Real Tuple{S,Vector{S}})) + + # typevar corresponding to a type it will end up being neither greater than nor + # less than + @testintersect((@UnionAll T Tuple{T, Ref{T}}), Tuple{Array{Int}, Ref{AbstractVector}}, + Tuple{Array{Int,1}, Ref{AbstractVector}}) + @testintersect((@UnionAll T Tuple{T, AbstractArray{T}}), Tuple{Any, Array{Number,1}}, Tuple{Number, Array{Number,1}}) @testintersect((@UnionAll T Tuple{Array{T}, Array{T}}), Tuple{Array, Array{Any}}, !Bottom) + @testintersect((@UnionAll T Tuple{T,T}), Tuple{Real, Real}, (@UnionAll T<:Real Tuple{T,T})) + @testintersect((@UnionAll T Tuple{T}), Tuple{Real}, Tuple{Real}) @testintersect((@UnionAll T Tuple{T,T}), Tuple{Union{Float64,Int64},Int64}, Tuple{Int64,Int64}) @testintersect((@UnionAll T Tuple{T,T}), Tuple{Int64,Union{Float64,Int64}}, Tuple{Int64,Int64}) + @testintersect((@UnionAll Z Tuple{Z,Z}), (@UnionAll T<:Integer @UnionAll S<:Number Tuple{T,S}), + @UnionAll Z<:Integer Tuple{Z,Z}) + @testintersect((@UnionAll Z Pair{Z,Z}), (@UnionAll T<:Integer @UnionAll S<:Number Pair{T,S}), + @UnionAll Z<:Integer Pair{Z,Z}) @testintersect((@UnionAll T<:Vector Type{T}), (@UnionAll N Type{@UnionAll S<:Number Array{S,N}}), Type{@UnionAll S<:Number Array{S,1}}) @testintersect((@UnionAll T Tuple{Type{Array{T,1}},Array{T,1}}), Tuple{Type{AbstractVector},Vector{Int}}, Bottom) + @testintersect(Tuple{Type{Vector{Complex128}}, AbstractVector}, (@UnionAll T @UnionAll S @UnionAll N Tuple{Type{Array{T,N}}, Array{S,N}}), Tuple{Type{Vector{Complex128}},Vector}) + @testintersect(Tuple{Type{Vector{Complex128}}, AbstractArray}, (@UnionAll T @UnionAll S @UnionAll N Tuple{Type{Array{T,N}}, Array{S,N}}), Tuple{Type{Vector{Complex128}},Vector}) @@ -530,7 +648,9 @@ function test_intersection() @testintersect((@UnionAll T Tuple{Rational{T},T}), Tuple{Rational{Integer},Int}, Tuple{Rational{Integer},Int}) @testintersect((@UnionAll T Pair{T,Ptr{T}}), (@UnionAll S Pair{Ptr{S},S}), Bottom) - @testintersect((@UnionAll T Tuple{T,Ptr{T}}), (@UnionAll S Tuple{Ptr{S},S}), Bottom) + @testintersect((@UnionAll T Tuple{T,Ptr{T}}), (@UnionAll S Tuple{Ptr{S},S}), + Union{(@UnionAll T>:Ptr @UnionAll S>:Ptr{T} Tuple{Ptr{T},Ptr{S}}), + (@UnionAll T>:Ptr @UnionAll S>:Ptr{T} Tuple{Ptr{S},Ptr{T}})}) @testintersect((@UnionAll N Tuple{NTuple{N,Integer},NTuple{N,Integer}}), Tuple{Tuple{Integer,Integer}, Tuple{Vararg{Integer}}}, @@ -580,16 +700,18 @@ function test_intersection() @testintersect((@UnionAll T<:Union{Float64,Array{Float64,1}} T), Real, Float64) + # issue #4805 @testintersect((@UnionAll T<:Int Type{IT4805{1,T}}), (@UnionAll S<:(@UnionAll N IT4805{N,Int}) Type{S}), !Bottom) + # issue #8851 @testintersect((@UnionAll T AbstractThing{T,2}), ConcreteThing, (@UnionAll T<:AbstractFloat ConcreteThing{T,2})) + # issue #11136 and #11367 @testintersect((@UnionAll T Tuple{T, T}), (@UnionAll TB<:B11136 Tuple{A11136, TB}), Bottom) - @testintersect((@UnionAll T Tuple{T, T}), (@UnionAll T2<:Foo11367 Tuple{Type{BigInt}, T2}), Bottom) @testintersect((@UnionAll N NTuple{N,Int}), (@UnionAll N NTuple{N,Float64}), Tuple{}) @@ -598,15 +720,35 @@ function test_intersection() @testintersect((@UnionAll T T), Type{Int8}, Type{Int8}) @testintersect((@UnionAll T Tuple{T}), Tuple{Type{Int8}}, Tuple{Type{Int8}}) + + @testintersect((@UnionAll T Tuple{Union{Int,T}, Union{Vector{T},Vector{String}}}), + Tuple{Integer, Vector{Int8}}, + Tuple{Union{Int,Int8}, Vector{Int8}}) + @testintersect((@UnionAll T Tuple{Union{Int,T}, Union{Vector{T},Vector{String}}}), + Tuple{Int8, Vector{String}}, + Tuple{Int8, Vector{String}}) + @testintersect((@UnionAll T Tuple{Union{Int,T}, Union{Vector{T},Vector{String}}}), + Tuple{Int, Vector{Int8}}, + Tuple{Int, Vector{Int8}}) + @testintersect(( Tuple{Union{Int,String}, Union{Ref{Int}, Ref{String}}}), + (@UnionAll T Tuple{T, Union{Ref{T}, Ref{String}}}), + Union{Tuple{Int, Union{Ref{Int},Ref{String}}}, + Tuple{String, Ref{String}}}) + + @testintersect((@UnionAll Z<:(@UnionAll T @UnionAll S Tuple{T,S}) Ref{Z}), + (@UnionAll X<:(@UnionAll T Tuple{T,T}) Ref{X}), + (@UnionAll X<:(@UnionAll T Tuple{T,T}) Ref{X})) + @testintersect(Ref{@UnionAll T @UnionAll S Tuple{T,S}}, + Ref{@UnionAll T Tuple{T,T}}, Bottom) end function test_intersection_properties() for T in menagerie for S in menagerie I = _type_intersect(T,S) - @test isequal_type(I, _type_intersect(S,T)) - @test issub(I, T) - @test issub(I, S) + I2 = _type_intersect(S,T) + @test isequal_type(I, I2) + @test issub(I, T) && issub(I, S) if issub(T, S) @test isequal_type(I, T) end @@ -621,6 +763,8 @@ test_3() test_4() test_5() test_6() +test_Type() +test_old() test_intersection() test_properties() test_intersection_properties()