Skip to content

Commit

Permalink
Merge pull request #20307 from JuliaLang/yyc/subtypes
Browse files Browse the repository at this point in the history
Allow UnionAll as input to subtypes and include UnionAll in its output
  • Loading branch information
yuyichao authored Feb 3, 2017
2 parents fc00ad1 + 2dd2176 commit 754d8e8
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 8 deletions.
42 changes: 34 additions & 8 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -332,22 +332,48 @@ enumerated types (see `@enum`).
function instances end

# subtypes
function _subtypes(m::Module, x::DataType, sts=Set{DataType}(), visited=Set{Module}())
function _subtypes(m::Module, x::Union{DataType,UnionAll},
sts=Set{Union{DataType,UnionAll}}(), visited=Set{Module}())
push!(visited, m)
xt = unwrap_unionall(x)
if !isa(xt, DataType)
return sts
end
xt = xt::DataType
for s in names(m, true)
if isdefined(m, s) && !isdeprecated(m, s)
t = getfield(m, s)
if isa(t, DataType) && t.name.name == s && supertype(t).name == x.name
ti = typeintersect(t, x)
ti != Bottom && push!(sts, ti)
elseif isa(t, Module) && !in(t, visited)
_subtypes(t, x, sts, visited)
if isa(t, DataType)
t = t::DataType
if t.name.name === s && supertype(t).name == xt.name
ti = typeintersect(t, x)
ti != Bottom && push!(sts, ti)
end
elseif isa(t, UnionAll)
t = t::UnionAll
tt = unwrap_unionall(t)
isa(tt, DataType) || continue
tt = tt::DataType
if tt.name.name === s && supertype(tt).name == xt.name
ti = typeintersect(t, x)
ti != Bottom && push!(sts, ti)
end
elseif isa(t, Module)
t = t::Module
in(t, visited) || _subtypes(t, x, sts, visited)
end
end
end
return sts
end
subtypes(m::Module, x::DataType) = x.abstract ? sort!(collect(_subtypes(m, x)), by=string) : DataType[]
function subtypes(m::Module, x::Union{DataType,UnionAll})
if isabstract(x)
sort!(collect(_subtypes(m, x)), by=string)
else
# Fast path
Union{DataType,UnionAll}[]
end
end

"""
subtypes(T::DataType)
Expand All @@ -364,7 +390,7 @@ julia> subtypes(Integer)
Unsigned
```
"""
subtypes(x::DataType) = subtypes(Main, x)
subtypes(x::Union{DataType,UnionAll}) = subtypes(Main, x)

function to_tuple_type(t::ANY)
@_pure_meta
Expand Down
8 changes: 8 additions & 0 deletions test/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -638,3 +638,11 @@ let
@test @inferred wrapperT(Union{ReflectionExample{Union{},1},ReflectionExample{Float64,1}}) == ReflectionExample
@test_throws ErrorException Base.typename(Union{Int, Float64})
end

# Issue #20086
abstract A20086{T,N}
immutable B20086{T,N} <: A20086{T,N} end
@test subtypes(A20086) == [B20086]
@test subtypes(A20086{Int}) == [B20086{Int}]
@test subtypes(A20086{T,3} where T) == [B20086{T,3} where T]
@test subtypes(A20086{Int,3}) == [B20086{Int,3}]

0 comments on commit 754d8e8

Please sign in to comment.