# Make `Type{}` "covariant"

#1

This is probably a stupid question: couldn’t `Type` behave covariantly? So, e.g. `Type{Int}<:Type{Integer}`. As `Type` can never be instantiated, the usual road-blocks for covariance do not apply. Also `Type` is pretty special already, so being more special shouldn’t come as too much of a surprise.

Then this would work:

``````f{T}(::Type{AbstractArray{T,1}}) = T
f(Range{Int}) # -> Int
``````

instead of the parameter juggle needed currently (this gets better with the type-overhaul but above would still be useful).

#2

This doesn’t sound right `T1 <: T2` means that if `isa(v1, T1)` then `isa(v1, T2)` However, `isa(Int, Type{Int})` but `!isa(Int, Type{Integer})`.

#3

Yes, to make `isa(Int, Type{Integer})==true` is the essence of the proposal.

#4

This will be a major breaking change since then `f(::Type{Integer})` will have the same meaning as `f{T<:Integer}(::Type{T})` and being able to distinguish the two is a important reason why `Type` is useful.

#5

Yes, it would be breaking for sure. Note though that with the current dispatch rules your latter function would win over the former when called with `f(Int)`, thus the distinction could still be made. Here the not quite analogous example with `Tuple`:

``````julia> f(::Tuple{Integer}) = 1
f (generic function with 1 method)

julia> f{T<:Integer}(::Tuple{T}) = 2
f (generic function with 2 methods)

julia> f((3,))
2
``````

#6

I believe that behavior is a bug.

#7

And just to prove the point, this behavior is fixed on the jb/subtype branch and the two methods are treated as the same one and overwrites each other.

``````               _
_       _ _(_)_     |  A fresh approach to technical computing
(_)     | (_) (_)    |  Documentation: http://docs.julialang.org
_ _   _| |_  __ _   |  Type "?help" for help.
| | | | | | |/ _` |  |
| | |_| | | | (_| |  |  Version 0.6.0-dev.1562 (2016-12-12 21:00 UTC)
_/ |\__'_|_|_|\__'_|  |  jb/subtype/d514ed4* (fork: 18 commits, 1 day)
|__/                   |  x86_64-pc-linux-gnu

julia> f(::Integer) = 1
f (generic function with 1 method)

julia> f{T<:Integer}(::T) = 2
WARNING: Method definition f(T) in module Main at REPL[1]:1 overwritten at REPL[2]:1.
f (generic function with 1 method)

julia> f2(::Tuple{Integer}) = 1
f2 (generic function with 1 method)

julia> f2{T<:Integer}(::Tuple{T}) = 2
WARNING: Method definition f2(Tuple{T}) in module Main at REPL[3]:1 overwritten at REPL[4]:1.
f2 (generic function with 1 method)
``````

#8

Yep, that kills it. Thanks @yuyichao for your time to discuss this.