Skip to content

Commit

Permalink
Merge pull request JuliaLang#18457 from JuliaLang/jb/subtype
Browse files Browse the repository at this point in the history
type system revision and new subtype algorithm
  • Loading branch information
JeffBezanson committed Jan 16, 2017
2 parents 281e2be + 7ae0bd2 commit 35b3470
Show file tree
Hide file tree
Showing 95 changed files with 5,910 additions and 4,914 deletions.
23 changes: 23 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ Julia v0.6.0 Release Notes
New language features
---------------------

* New type system capabilities ([#8974], [#18457])
* Type parameter constraints can refer to previous parameters, e.g.
`type Foo{R<:Real, A<:AbstractArray{R}}`. Can also be used in method definitions.
* New syntax `Array{T} where T<:Integer`, indicating a union of types over all
specified values of `T` (represented by a `UnionAll` type). This provides behavior
similar to parametric methods or `typealias`, but can be used anywhere a type is
accepted. This syntax can also be used in method definitions, e.g.
`function inv(M::Matrix{T}) where T<:AbstractFloat`.
Anonymous functions can have type parameters via the syntax
`((x::Array{T}) where T<:Real) -> 2x`.
* Much more accurate subtype and type intersection algorithms. Method sorting and
identification of equivalent and ambiguous methods are improved as a result.

Language changes
----------------

Expand Down Expand Up @@ -103,6 +116,16 @@ This section lists changes that do not have deprecation warnings.
special 1×n-sized `AbstractMatrix`), not a `Matrix`, etc. In particular, for
`v::AbstractVector` we now have `(v.').' === v` and `v.' * v` is a scalar. ([#19670])

* Parametric types with "unspecified" parameters, such as `Array`, are now represented
as `UnionAll` types instead of `DataType`s ([#18457]).

* `Union` types have two fields, `a` and `b`, instead of a single `types` field.
The empty type `Union{}` is represented by a singleton of type `BottomType` ([#18457]).

* The type `NTuple{N}` now refers to tuples where every element has the same type
(since it is shorthand for `NTuple{N,T} where T`). To get the old behavior of matching
any tuple, use `NTuple{N,Any}` ([#18457]).

Library improvements
--------------------

Expand Down
5 changes: 3 additions & 2 deletions base/REPLCompletions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ function get_type(sym, fn)
end
# Method completion on function call expression that look like :(max(1))
function complete_methods(ex_org::Expr)
args_ex = DataType[]
args_ex = Any[]
func, found = get_value(ex_org.args[1], Main)
!found && return String[]
for ex in ex_org.args[2:end]
Expand All @@ -330,7 +330,8 @@ function complete_methods(ex_org::Expr)
io = IOBuffer()
for method in ml
# Check if the method's type signature intersects the input types
if typeintersect(Tuple{method.sig.parameters[1 : min(na, end)]...}, t_in) != Union{}
ms = method.sig
if typeintersect(Base.rewrap_unionall(Tuple{Base.unwrap_unionall(ms).parameters[1 : min(na, end)]...}, ms), t_in) != Union{}
show(io, method, kwtype=kwtype)
push!(out, String(take!(io)))
end
Expand Down
8 changes: 3 additions & 5 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,7 @@ julia> extrema(b)
"""
linearindices(A) = (@_inline_meta; OneTo(_length(A)))
linearindices(A::AbstractVector) = (@_inline_meta; indices1(A))
eltype{T}(::Type{AbstractArray{T}}) = T
eltype{T,N}(::Type{AbstractArray{T,N}}) = T
eltype(::Type{A}) where A<:AbstractArray{E} where E = E
elsize{T}(::AbstractArray{T}) = sizeof(T)

"""
Expand Down Expand Up @@ -204,7 +203,7 @@ julia> strides(A)
```
"""
strides(A::AbstractArray) = _strides((1,), A)
_strides{T,N}(out::NTuple{N}, A::AbstractArray{T,N}) = out
_strides{T,N}(out::NTuple{N,Any}, A::AbstractArray{T,N}) = out
function _strides{M,T,N}(out::NTuple{M}, A::AbstractArray{T,N})
@_inline_meta
_strides((out..., out[M]*size(A, M)), A)
Expand Down Expand Up @@ -267,6 +266,7 @@ should define `linearindexing` in the type-domain:
Base.linearindexing{T<:MyArray}(::Type{T}) = Base.LinearFast()
"""
linearindexing(A::AbstractArray) = linearindexing(typeof(A))
linearindexing(::Type{Union{}}) = LinearFast()
linearindexing{T<:AbstractArray}(::Type{T}) = LinearSlow()
linearindexing{T<:Array}(::Type{T}) = LinearFast()
linearindexing{T<:Range}(::Type{T}) = LinearFast()
Expand Down Expand Up @@ -997,8 +997,6 @@ promote_eltype(v1, vs...) = promote_type(eltype(v1), promote_eltype(vs...))
#TODO: ERROR CHECK
cat(catdim::Integer) = Array{Any,1}(0)

vcat() = Array{Any,1}(0)
hcat() = Array{Any,1}(0)
typed_vcat{T}(::Type{T}) = Array{T,1}(0)
typed_hcat{T}(::Type{T}) = Array{T,1}(0)

Expand Down
4 changes: 4 additions & 0 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,10 @@ end


# concatenations of homogeneous combinations of vectors, horizontal and vertical

vcat() = Array{Any,1}(0)
hcat() = Array{Any,1}(0)

function hcat{T}(V::Vector{T}...)
height = length(V[1])
for j = 2:length(V)
Expand Down
24 changes: 9 additions & 15 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
#end

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

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

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

Expand Down Expand Up @@ -120,7 +121,7 @@ import Core.Intrinsics.ccall
export
# key types
Any, DataType, Vararg, ANY, NTuple,
Tuple, Type, TypeConstructor, TypeName, TypeVar, Union, Void,
Tuple, Type, UnionAll, TypeName, TypeVar, Union, Void,
SimpleVector, AbstractArray, DenseArray,
# special objects
Function, CodeInfo, Method, MethodTable, TypeMapEntry, TypeMapLevel,
Expand Down Expand Up @@ -258,18 +259,11 @@ 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_type_unionall, Any, (Any, Any), v, t)

Void() = nothing

Expand Down
2 changes: 1 addition & 1 deletion base/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ typealias ScalarType Union{Type{Any}, Type{Nullable}}
## Broadcasting utilities ##
# fallbacks for some special cases
@inline broadcast(f, x::Number...) = f(x...)
@inline broadcast{N}(f, t::NTuple{N}, ts::Vararg{NTuple{N}}) = map(f, t, ts...)
@inline broadcast{N}(f, t::NTuple{N,Any}, ts::Vararg{NTuple{N,Any}}) = map(f, t, ts...)

# special cases for "X .= ..." (broadcast!) assignments
broadcast!(::typeof(identity), X::AbstractArray, x::Number) = fill!(X, x)
Expand Down
16 changes: 8 additions & 8 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,14 @@ end
@deprecate get_rounding rounding

#13465
@deprecate cov(x::AbstractVector; corrected=true, mean=Base.mean(x)) Base.covm(x, mean, corrected)
@deprecate cov(X::AbstractMatrix; vardim=1, corrected=true, mean=Base.mean(X, vardim)) Base.covm(X, mean, vardim, corrected)
@deprecate cov(x::AbstractVector, y::AbstractVector; corrected=true, mean=(Base.mean(x), Base.mean(y))) Base.covm(x, mean[1], y, mean[2], corrected)
#@deprecate cov(x::AbstractVector; corrected=true, mean=Base.mean(x)) Base.covm(x, mean, corrected)
#@deprecate cov(X::AbstractMatrix; vardim=1, corrected=true, mean=Base.mean(X, vardim)) Base.covm(X, mean, vardim, corrected)
#@deprecate cov(x::AbstractVector, y::AbstractVector; corrected=true, mean=(Base.mean(x), Base.mean(y))) Base.covm(x, mean[1], y, mean[2], corrected)
@deprecate cov(X::AbstractVecOrMat, Y::AbstractVecOrMat; vardim=1, corrected=true, mean=(Base.mean(X, vardim), Base.mean(Y, vardim))) Base.covm(X, mean[1], Y, mean[2], vardim, corrected)

@deprecate cor(x::AbstractVector; mean=Base.mean(x)) Base.corm(x, mean)
@deprecate cor(X::AbstractMatrix; vardim=1, mean=Base.mean(X, vardim)) Base.corm(X, mean, vardim)
@deprecate cor(x::AbstractVector, y::AbstractVector; mean=(Base.mean(x), Base.mean(y))) Base.corm(x, mean[1], y, mean[2])
#@deprecate cor(x::AbstractVector; mean=Base.mean(x)) Base.corm(x, mean)
#@deprecate cor(X::AbstractMatrix; vardim=1, mean=Base.mean(X, vardim)) Base.corm(X, mean, vardim)
#@deprecate cor(x::AbstractVector, y::AbstractVector; mean=(Base.mean(x), Base.mean(y))) Base.corm(x, mean[1], y, mean[2])
@deprecate cor(X::AbstractVecOrMat, Y::AbstractVecOrMat; vardim=1, mean=(Base.mean(X, vardim), Base.mean(Y, vardim))) Base.corm(X, mean[1], Y, mean[2], vardim)

@deprecate_binding SparseMatrix SparseArrays
Expand Down Expand Up @@ -315,8 +315,8 @@ for (Fun, func) in [(:IdFun, :identity),
(::Type{typeof($(func))})() = $(func)
end
end
@deprecate_binding CentralizedAbs2Fun typeof(centralizedabs2fun(0)).name.primary
(::Type{typeof(centralizedabs2fun(0)).name.primary})(m::Number) = centralizedabs2fun(m)
@deprecate_binding CentralizedAbs2Fun typeof(centralizedabs2fun(0)).name.wrapper
(::Type{typeof(centralizedabs2fun(0)).name.wrapper})(m::Number) = centralizedabs2fun(m)
@deprecate specialized_unary(f::Function) f
@deprecate specialized_binary(f::Function) f
@deprecate specialized_bitwise_unary(f::Function) f
Expand Down
25 changes: 12 additions & 13 deletions base/dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -137,15 +137,14 @@ const AnyDict = Dict{Any,Any}

Dict{K,V}(ps::Pair{K,V}...) = Dict{K,V}(ps)
Dict{K }(ps::Pair{K}...,) = Dict{K,Any}(ps)
Dict{V }(ps::Pair{TypeVar(:K),V}...,) = Dict{Any,V}(ps)
Dict{V }(ps::(Pair{K,V} where K)...,) = Dict{Any,V}(ps)
Dict( ps::Pair...) = Dict{Any,Any}(ps)

function Dict(kv)
try
Base.associative_with_eltype(Dict, kv, eltype(kv))
associative_with_eltype((K, V) -> Dict{K, V}, kv, eltype(kv))
catch e
if any(x->isempty(methods(x, (typeof(kv),))), [start, next, done]) ||
!all(x->isa(x,Union{Tuple,Pair}),kv)
if !applicable(start, kv) || !all(x->isa(x,Union{Tuple,Pair}),kv)
throw(ArgumentError("Dict(kv): kv needs to be an iterator of tuples or pairs"))
else
rethrow(e)
Expand All @@ -155,17 +154,17 @@ end

typealias TP{K,V} Union{Type{Tuple{K,V}},Type{Pair{K,V}}}

associative_with_eltype{K,V}(DT, kv, ::TP{K,V}) = DT{K,V}(kv)
associative_with_eltype{K,V}(DT, kv::Generator, ::TP{K,V}) = DT{K,V}(kv)
associative_with_eltype{K,V}(DT, ::Type{Pair{K,V}}) = DT{K,V}()
associative_with_eltype(DT, ::Type) = DT()
associative_with_eltype(DT, kv, t) = grow_to!(associative_with_eltype(DT, _default_eltype(typeof(kv))), kv)
function associative_with_eltype(DT, kv::Generator, t)
associative_with_eltype{K,V}(DT_apply, kv, ::TP{K,V}) = DT_apply(K, V)(kv)
associative_with_eltype{K,V}(DT_apply, kv::Generator, ::TP{K,V}) = DT_apply(K, V)(kv)
associative_with_eltype{K,V}(DT_apply, ::Type{Pair{K,V}}) = DT_apply(K, V)()
associative_with_eltype(DT_apply, ::Type) = DT_apply(Any, Any)()
associative_with_eltype{F}(DT_apply::F, kv, t) = grow_to!(associative_with_eltype(DT_apply, _default_eltype(typeof(kv))), kv)
function associative_with_eltype{F}(DT_apply::F, kv::Generator, t)
T = _default_eltype(typeof(kv))
if T <: Union{Pair,NTuple{2}} && isleaftype(T)
return associative_with_eltype(DT, kv, T)
if T <: Union{Pair, Tuple{Any, Any}} && isleaftype(T)
return associative_with_eltype(DT_apply, kv, T)
end
return grow_to!(associative_with_eltype(DT, T), kv)
return grow_to!(associative_with_eltype(DT_apply, T), kv)
end

# this is a special case due to (1) allowing both Pairs and Tuples as elements,
Expand Down
12 changes: 7 additions & 5 deletions base/docs/Docs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@ function signature(expr::Expr)
end
push!(sig.args[end].args, argtype(arg))
end
Expr(:let, Expr(:block, sig), typevars(expr)...)
tv = typevars(expr)
for i = length(tv):-1:1
sig = Expr(:where, sig, tv[i])
end
sig
else
signature(expr.args[1])
end
Expand All @@ -103,14 +107,11 @@ end
argtype(other) = :Any

function typevars(expr::Expr)
isexpr(expr, :curly) && return [tvar(x) for x in expr.args[2:end]]
isexpr(expr, :curly) && return expr.args[2:end]
typevars(expr.args[1])
end
typevars(::Symbol) = []

tvar(x::Expr) = :($(x.args[1]) = TypeVar($(quot(x.args[1])), $(x.args[2]), true))
tvar(s::Symbol) = :($(s) = TypeVar($(quot(s)), Any, true))

# Docsystem types.
# ================

Expand Down Expand Up @@ -283,6 +284,7 @@ function doc(binding::Binding, sig::Type = Union{})
end

# Some additional convenience `doc` methods that take objects rather than `Binding`s.
doc(obj::UnionAll) = doc(Base.unwrap_unionall(obj))
doc(object, sig::Type = Union{}) = doc(aliasof(object, typeof(object)), sig)
doc(object, sig...) = doc(object, Tuple{sig...})

Expand Down
33 changes: 28 additions & 5 deletions base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

using Core: CodeInfo

typealias Callable Union{Function,DataType}
typealias Callable Union{Function,Type}

const Bottom = Union{}

Expand Down Expand Up @@ -47,13 +47,13 @@ end
argtail(x, rest...) = rest
tail(x::Tuple) = argtail(x...)

tuple_type_head(T::TypeConstructor) = tuple_type_head(T.body)
tuple_type_head(T::UnionAll) = tuple_type_head(T.body)
function tuple_type_head(T::DataType)
@_pure_meta
T.name === Tuple.name || throw(MethodError(tuple_type_head, (T,)))
return T.parameters[1]
end
tuple_type_tail(T::TypeConstructor) = tuple_type_tail(T.body)
tuple_type_tail(T::UnionAll) = tuple_type_tail(T.body)
function tuple_type_tail(T::DataType)
@_pure_meta
T.name === Tuple.name || throw(MethodError(tuple_type_tail, (T,)))
Expand All @@ -69,9 +69,31 @@ 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

function rewrap_unionall(t::ANY, u::ANY)
if !isa(u, UnionAll)
return t
end
return UnionAll(u.var, rewrap_unionall(t, u.body))
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)
t2 = unwrap_unionall(t)
isvarargtype(t2) ? t2.parameters[1] : t
end

convert{T<:Tuple{Any,Vararg{Any}}}(::Type{T}, x::Tuple{Any, Vararg{Any}}) =
tuple(convert(tuple_type_head(T),x[1]), convert(tuple_type_tail(T), tail(x))...)
Expand All @@ -90,6 +112,7 @@ ptr_arg_unsafe_convert(::Type{Ptr{Void}}, x) = x
cconvert(T::Type, x) = convert(T, x) # do the conversion eagerly in most cases
cconvert{P<:Ptr}(::Type{P}, x) = x # but defer the conversion to Ptr to unsafe_convert
unsafe_convert{T}(::Type{T}, x::T) = x # unsafe_convert (like convert) defaults to assuming the convert occurred
unsafe_convert{T<:Ptr}(::Type{T}, x::T) = x # to resolve ambiguity with the next method
unsafe_convert{P<:Ptr}(::Type{P}, x::Ptr) = convert(P, x)

reinterpret{T}(::Type{T}, x) = box(T, x)
Expand Down
1 change: 1 addition & 0 deletions base/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ for t1 in (Float32,Float64)
end
end
end
convert(::Type{Integer}, x::Float16) = convert(Integer, Float32(x))
convert{T<:Integer}(::Type{T}, x::Float16) = convert(T, Float32(x))


Expand Down
Loading

0 comments on commit 35b3470

Please sign in to comment.