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 10 commits into
base: master
Choose a base branch
from

Conversation

mrufsvold
Copy link

This PR documents Method, MethodList, and a few functions for retrieving the properties of a Method. methods is partially documented but isn't very useful outside of interactive sessions because nothing it returns is public. The docs are also currently incorrect because they claim that methods returns a MethodTable, but it actually returns a MethodList.

This partially addresses #20555, but I am intentionally keeping the surface area of this change very small so to judge the interest in this direction. To that end, I do not document MethodTable, anything to do with kwargs, nor do I define functions to access any of the more "advanced" properties of Method.

This is my first time contributing, so I don't have tooling set up to test building the docs. There is still a lot of clean up to do with regard to adding tests for the new functions, but I want an initial reaction from the maintainers about this PR before burning more time.

@LilithHafner
Copy link
Member

Thanks for jumping in to this! I'd love to have a comprehensive reflection API, and I think Julia is mature enough that we can do this without impinging much on future language development.

In general,

  • Adding accurate and helpful docstrings is always good, for public and private functionality
  • Use the public keyword to declare symbols public that were previously internal. This, rather adding docstrings, is the way we commit to keeping an API around forever. We should be careful and conservative about what we make public, but also offer enough public API that folks don't have to depend on internals.
  • All code should support public functionality. (e.g. we don't want private methods which are not called elsewhere in this codebase)
  • We should rarely link to private APIs when documenting public APIs. If it's not possible to express the public API without reference to private constructs then perhaps we should make those private constructs public.

As this applies to this PR,

  • Adding a docstring to Method should be pretty easy to review and merge. This is lovely to have and, alone, would make a quick and valuable first contribution!
  • I think nameof is a clear win and we should definitely define that method. Method is public, nameof is public, and the correct implementation of nameof(::Method) is unambiguous.
  • signature_type is currently private, so this method would only make sense to add if we made signature_type public. This is possible, but should take a slightly broader consensus than a single maintainer's go-ahead. Personally, I could go either way on signature_type, but others are likely to have stronger and better informed opinions.
  • Documenting the exact return type of methods commits us to stability in that regard. Seems like a reasonable choice, but again, I would want to hear from others first.

@mrufsvold
Copy link
Author

Thank you for all this feedback!

Just to narrow in on one point, would defining signatureof(::Method) side step the whole issue of making signature_type public? It would also have nice synergy with nameof.

@LilithHafner
Copy link
Member

It would sidestep a bit of it, but we'd still need to decide if signatureof is public API and a name we want to commit to. For example, returning nothing for builtins is an easy solution now but if in the future we are able to introspect the signature of a builtin method, it might be worth changing that.

@mrufsvold
Copy link
Author

mrufsvold commented May 10, 2024

Documenting the exact return type of methods commits us to stability in that regard. Seems like a reasonable choice, but again, I would want to hear from others first.

If people are concerned about committing to MethodList, it might be worth documenting that it returns an AbstractVector{Method}, so that iterating and indexing and expecting Methods in return is stable.

It would sidestep a bit of it, but we'd still need to decide if signatureof is public API and a name we want to commit to. For example, returning nothing for builtins is an easy solution now but if in the future we are able to introspect the signature of a builtin method, it might be worth changing that.

Ah, sorry, I left implicit my assumption that signatureof would be public. Excellent point about builtins. Does it seem reasonable to document "Methods for which the method table does not have signatures returns <either nothing or maybe Tuple depending on what we decide in this conversation>. Currently, this includes builtins and OpaqueClosures, but this is not stabilized."

Edit: Method.sig for builtins is Tuple at the moment, so we could just return that and then the function would satisfy signatureof(::Method) :: Type{<:Tuple}

@mrufsvold
Copy link
Author

I weakened the docstring for methods. I'll await feedback from others before working on any signature functions.

@LilithHafner
Copy link
Member

The new docstring for methods LGTM

@mrufsvold
Copy link
Author

Okay, I added two functions to public and tightened up the other docstrings. Ready for review!

Also, the build is failing because Documenter can't find the docstring for Core.Method, but I'm not sure why. Any pointers would be appreciated!

@@ -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.

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
Copy link
Member

Choose a reason for hiding this comment

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

This new method eliminates the copy that collect typically makes. We already have collect(::MethodList)::Vector{Method}

Suggested change
collect(m::MethodList) = m.ms

@@ -62,6 +62,8 @@ public
isexported,
ispublic,
remove_linenums!,
method_argnames,
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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants