FluxML / MacroTools.jl

MacroTools provides a library of tools for working with Julia code and expressions.
https://fluxml.ai/MacroTools.jl/stable/
Other
310 stars 79 forks source link

splitdef and gatherwheres incorrectly handle return type annotations #184

Closed julbinb closed 2 years ago

julbinb commented 2 years ago

https://github.com/FluxML/MacroTools.jl/blob/639d1a62c3d6bc37325cddbaa13d4c993d1448fb/src/utils.jl#L266-L325

If a function definition has both where and return type annotation, the annotation is bundled into a where clause instead of the :rtype part of the splitdef dictionary:

julia> splitdef( :(f(x) :: Int = 0 ))
Dict{Symbol, Any} with 6 entries:
  :name        => :f
  :args        => Any[:x]
  :kwargs      => Any[]
  :body        => quote…
  :rtype       => :Int
  :whereparams => ()

julia> splitdef( :(f(x::T) where T :: Int = 0 ))
Dict{Symbol, Any} with 5 entries:
  :name        => :f
  :args        => Any[:(x::T)]
  :kwargs      => Any[]
  :body        => quote…
  :whereparams => (:(T::Int),)

It seems the solution would be to look inside the outermost where-clause of gatherwheres, extract the return type, and then reconstruct the function definition with this return type.

cstjean commented 2 years ago

I've only skimmed the issue, but isn't it bad syntax?

julia> f(x::T) where T :: Int = 0
ERROR: syntax: invalid variable expression in "where" around REPL[2]:1
Stacktrace:
 [1] top-level scope
   @ REPL[2]:1

I think you want

julia> (f(x::T)::Int) where T = 0
f (generic function with 1 method)

The parentheses are important because of Julia's parsing it as ::(Int where T) otherwise. Does that help?

julbinb commented 2 years ago

Oh shoot, that feeling when you haven't tested the test... My bad, thank you! Closing.