Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document Method reflection functions #54432

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
29 changes: 29 additions & 0 deletions base/docs/basedocs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2586,6 +2586,35 @@ See also [`setpropertyonce!`](@ref Base.setpropertyonce!) and [`setglobal!`](@re
"""
setglobalonce!


"""
`Method` represents a method definition of a function. A list of methods for a function
can be retrieved using [`Base.methods`](@ref).

To access the properties of a `Method`, use the following functions:

```
julia> m = methods(sum)[1]
sum(r::StepRangeLen{<:Any, <:Base.TwicePrecision, <:Base.TwicePrecision})
@ Base twiceprecision.jl:605

julia> nameof(m)
:sum

julia> parentmodule(m)
Base

julia> signature_type(m)
Tuple{typeof(sum), StepRangeLen{<:Any, <:Base.TwicePrecision, <:Base.TwicePrecision}}

julia> Base.method_argnames(m)
2-element Vector{Symbol}:
Symbol("#self#")
:r
```
"""
Core.Method

"""
typeof(x)

Expand Down
6 changes: 6 additions & 0 deletions base/methodshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ function argtype_decl(env, n, @nospecialize(sig::DataType), i::Int, nargs, isva:
return s, string_with_env(env, t)
end

"""
method_argnames(m::Method)

Return the argument names of a `Method` as a `Vector{Symbol}`. The first element is `Symbol("#self#")`.
The remaining elements are the argument names.
"""
function method_argnames(m::Method)
argnames = ccall(:jl_uncompress_argnames, Vector{Symbol}, (Any,), m.slot_syms)
isempty(argnames) && return argnames
Expand Down
2 changes: 2 additions & 0 deletions base/public.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ public
isexported,
ispublic,
remove_linenums!,
method_argnames,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a weird API to make public: all the declared argument names with #self prepended.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair about the #self piece, but it would be really nice to be able to get the arg names.

Do you think cut it completely or define a new function that could provide just the arg names (But then there's the issue of functions defined for callable structs where you actually do want the function "self"...)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps replace Symbol("#self#") and Symbol("#unused#") with nothing?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll give it a go!

signature_type,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do other folks think about making signature_type public?


# Opperators
operator_associativity,
Expand Down
44 changes: 41 additions & 3 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,30 @@ function signature_type(@nospecialize(f), @nospecialize(argtypes))
return rewrap_unionall(Tuple{ft, u.parameters...}, argtypes)
end

"""
signature_type(m::Method) -> Type{<:Tuple}

Retrieve the signature type of a `Method`. Returns a `Tuple` type, the first element of which is
the `typeof` the function for the method. The remaining elements are the types of the arguments.

For methods that are `OpaqueClosure`s or `Builtin`s, `Tuple{}` is returned. However, this
behavior is not stable because future improvements to the compiler may allow improved reflection for
these types.

# Examples
```jldoctest
julia> f(x::Int, y) = x + y

julia> m = methods(f)[1]

julia> signature_type(m)
Tuple{typeof(f), Int, Any}
```
"""
function signature_type(m::Method)
return m.sig
end

"""
code_lowered(f, types; generated=true, debuginfo=:default)

Expand Down Expand Up @@ -1198,14 +1222,18 @@ end

# high-level, more convenient method lookup functions

# type for reflecting and pretty-printing a subset of methods
"""
`MethodList` is a type for reflecting and pretty-printing a subset of methods. It is returned by
[`methods`](@ref).
"""
mutable struct MethodList <: AbstractArray{Method,1}
ms::Array{Method,1}
mt::Core.MethodTable
end

size(m::MethodList) = size(m.ms)
getindex(m::MethodList, i::Integer) = m.ms[i]
collect(m::MethodList) = m.ms
mrufsvold marked this conversation as resolved.
Show resolved Hide resolved

function MethodList(mt::Core.MethodTable)
ms = Method[]
Expand All @@ -1216,9 +1244,10 @@ function MethodList(mt::Core.MethodTable)
end

"""
methods(f, [types], [module])
methods(f, [types], [module]) -> AbstractVector{Method}

Return the method table for `f`.
Return a list of [`Method`](@ref)s for `f`. The returned container type is not specified.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI fails because this cross-ref is broken. Probably because the Method docstring you added is not in the manual. (You'll have to put it in one of the .md files under doc/src)

Use `collect(methods(f))` to construct a `Vector{Method}`.

If `types` is specified, return an array of methods whose types match.
If `module` is specified, return an array of methods defined in that module.
Expand Down Expand Up @@ -2314,6 +2343,15 @@ function nameof(f::Core.IntrinsicFunction)
return ccall(:jl_symbol, Ref{Symbol}, (Ptr{UInt8},), name)
end

"""
nameof(f::Method) -> Symbol

Get the name of a `Method` as a symbol.
"""
function nameof(m::Method)
return m.name
end

"""
parentmodule(f::Function) -> Module

Expand Down