Skip to content

Commit 754d8e8

Browse files
authored
Merge pull request #20307 from JuliaLang/yyc/subtypes
Allow UnionAll as input to subtypes and include UnionAll in its output
2 parents fc00ad1 + 2dd2176 commit 754d8e8

File tree

2 files changed

+42
-8
lines changed

2 files changed

+42
-8
lines changed

base/reflection.jl

+34-8
Original file line numberDiff line numberDiff line change
@@ -332,22 +332,48 @@ enumerated types (see `@enum`).
332332
function instances end
333333

334334
# subtypes
335-
function _subtypes(m::Module, x::DataType, sts=Set{DataType}(), visited=Set{Module}())
335+
function _subtypes(m::Module, x::Union{DataType,UnionAll},
336+
sts=Set{Union{DataType,UnionAll}}(), visited=Set{Module}())
336337
push!(visited, m)
338+
xt = unwrap_unionall(x)
339+
if !isa(xt, DataType)
340+
return sts
341+
end
342+
xt = xt::DataType
337343
for s in names(m, true)
338344
if isdefined(m, s) && !isdeprecated(m, s)
339345
t = getfield(m, s)
340-
if isa(t, DataType) && t.name.name == s && supertype(t).name == x.name
341-
ti = typeintersect(t, x)
342-
ti != Bottom && push!(sts, ti)
343-
elseif isa(t, Module) && !in(t, visited)
344-
_subtypes(t, x, sts, visited)
346+
if isa(t, DataType)
347+
t = t::DataType
348+
if t.name.name === s && supertype(t).name == xt.name
349+
ti = typeintersect(t, x)
350+
ti != Bottom && push!(sts, ti)
351+
end
352+
elseif isa(t, UnionAll)
353+
t = t::UnionAll
354+
tt = unwrap_unionall(t)
355+
isa(tt, DataType) || continue
356+
tt = tt::DataType
357+
if tt.name.name === s && supertype(tt).name == xt.name
358+
ti = typeintersect(t, x)
359+
ti != Bottom && push!(sts, ti)
360+
end
361+
elseif isa(t, Module)
362+
t = t::Module
363+
in(t, visited) || _subtypes(t, x, sts, visited)
345364
end
346365
end
347366
end
348367
return sts
349368
end
350-
subtypes(m::Module, x::DataType) = x.abstract ? sort!(collect(_subtypes(m, x)), by=string) : DataType[]
369+
function subtypes(m::Module, x::Union{DataType,UnionAll})
370+
if isabstract(x)
371+
sort!(collect(_subtypes(m, x)), by=string)
372+
else
373+
# Fast path
374+
Union{DataType,UnionAll}[]
375+
end
376+
end
351377

352378
"""
353379
subtypes(T::DataType)
@@ -364,7 +390,7 @@ julia> subtypes(Integer)
364390
Unsigned
365391
```
366392
"""
367-
subtypes(x::DataType) = subtypes(Main, x)
393+
subtypes(x::Union{DataType,UnionAll}) = subtypes(Main, x)
368394

369395
function to_tuple_type(t::ANY)
370396
@_pure_meta

test/reflection.jl

+8
Original file line numberDiff line numberDiff line change
@@ -638,3 +638,11 @@ let
638638
@test @inferred wrapperT(Union{ReflectionExample{Union{},1},ReflectionExample{Float64,1}}) == ReflectionExample
639639
@test_throws ErrorException Base.typename(Union{Int, Float64})
640640
end
641+
642+
# Issue #20086
643+
abstract A20086{T,N}
644+
immutable B20086{T,N} <: A20086{T,N} end
645+
@test subtypes(A20086) == [B20086]
646+
@test subtypes(A20086{Int}) == [B20086{Int}]
647+
@test subtypes(A20086{T,3} where T) == [B20086{T,3} where T]
648+
@test subtypes(A20086{Int,3}) == [B20086{Int,3}]

0 commit comments

Comments
 (0)