Skip to content

Commit e5e3164

Browse files
committed
Add a few new reflection methods
This is informed by attempting to port some packages to the new type system. I have abstracted out the functionality required by those packages into documented/tested functions. The hope is to avoid introducing too many implementation details to packages. These functions can also be implemented in Compat for older julia versions, such that packages can immediate replace their use of internal APIs with these functions.
1 parent c9103ad commit e5e3164

File tree

3 files changed

+71
-2
lines changed

3 files changed

+71
-2
lines changed

base/exports.jl

+1
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,7 @@ export
10021002
fieldoffset,
10031003
fieldname,
10041004
fieldnames,
1005+
isabstract,
10051006
isleaftype,
10061007
oftype,
10071008
promote,

base/reflection.jl

+52-2
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,12 @@ fieldnames(t::UnionAll) = fieldnames(unwrap_unionall(t))
144144
fieldnames{T<:Tuple}(t::Type{T}) = Int[n for n in 1:nfields(t)]
145145

146146
"""
147-
Base.datatype_name(t::DataType) -> Symbol
147+
Base.datatype_name(t) -> Symbol
148148
149-
Get the name of a `DataType` (without its parent module) as a symbol.
149+
Get the name of a (potentially UnionAll-wrapped) `DataType` (without its parent module) as a symbol.
150150
"""
151151
datatype_name(t::DataType) = t.name.name
152+
datatype_name(t::UnionAll) = datatype_name(unwrap_unionall(t))
152153

153154
"""
154155
Base.datatype_module(t::DataType) -> Module
@@ -232,6 +233,55 @@ are itself and `Union{}` (but `T` itself is not `Union{}`).
232233
"""
233234
isleaftype(t::ANY) = (@_pure_meta; (isa(t, DataType) && t.isleaftype) || t === Union{})
234235

236+
"""
237+
isabstract(T)
238+
239+
Determine whether `T` was declared as an abstract type (i.e. using the
240+
`abstract` keyword).
241+
"""
242+
function isabstract(t::ANY)
243+
@_pure_meta
244+
t = unwrap_unionall(t)
245+
isa(t,DataType) && t.abstract
246+
end
247+
248+
"""
249+
Base.parameter_upper_bound(t::UnionAll, idx)
250+
251+
Determine the upper bound of a type parameter in the underlying type. E.g.:
252+
```
253+
julia> immutable Foo{T<:AbstractFloat, N}
254+
x::Tuple{T, N}
255+
end
256+
257+
julia> Base.parameter_upper_bound(Foo, 1)
258+
AbstractFloat
259+
260+
julia> parameter_upper_bound(Foo, 2)
261+
Any
262+
```
263+
"""
264+
function parameter_upper_bound(t::UnionAll, idx)
265+
@_pure_meta
266+
rewrap_unionall(unwrap_unionall(t).parameters[idx], t)
267+
end
268+
269+
"""
270+
Base.unparameterized_type(t)
271+
272+
Given a (partially) specialized type, return the unspecialized type, e.g.:
273+
```
274+
julia> immutable Foo{T}
275+
x::T
276+
end
277+
278+
julia> Base.unparameterized_type(Foo{Float64})
279+
Foo
280+
```
281+
"""
282+
unparameterized_type(t::DataType) = t.name.wrapper
283+
unparameterized_type(t::UnionAll) = unparameterized_type(unwrap_unionall(t))
284+
235285
"""
236286
typeintersect(T, S)
237287

test/reflection.jl

+18
Original file line numberDiff line numberDiff line change
@@ -610,3 +610,21 @@ end
610610
@generated f18883() = nothing
611611
@test !isempty(sprint(io->code_llvm(io, f18883, Tuple{})))
612612
@test !isempty(sprint(io->code_native(io, f18883, Tuple{})))
613+
614+
# New reflection methods in 0.6
615+
immutable ReflectionExample{T<:AbstractFloat, N}
616+
x::Tuple{T, N}
617+
end
618+
619+
@test isabstract(AbstractArray)
620+
@test !isabstract(ReflectionExample)
621+
@test !isabstract(Int)
622+
623+
@test Base.parameter_upper_bound(ReflectionExample, 1) === AbstractFloat
624+
@test Base.parameter_upper_bound(ReflectionExample, 2) === Any
625+
@test Base.parameter_upper_bound(ReflectionExample{T, N} where T where N <: Real, 2) === Real
626+
627+
@test Base.unparameterized_type(ReflectionExample{Float64, Int64}) === ReflectionExample
628+
@test Base.unparameterized_type(ReflectionExample{Float64, N} where N) === ReflectionExample
629+
@test Base.unparameterized_type(ReflectionExample{T, Int64} where T) === ReflectionExample
630+
@test Base.unparameterized_type(ReflectionExample) === ReflectionExample

0 commit comments

Comments
 (0)