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

@code_* can't handle anonymous function arguments #16326

Closed
StefanKarpinski opened this issue May 12, 2016 · 6 comments · Fixed by #17096
Closed

@code_* can't handle anonymous function arguments #16326

StefanKarpinski opened this issue May 12, 2016 · 6 comments · Fixed by #17096
Assignees
Labels
kind:regression Regression in behavior compared to a previous version
Milestone

Comments

@StefanKarpinski
Copy link
Sponsor Member

function isort!(v::Vector, lt::Function=<)
    @inbounds for i = 2:length(v)
        j = i
        x = v[i]
        while j > 1
            if lt(x, v[j-1])
                v[j] = v[j-1]
                j -= 1
                continue
            end
            break
        end
        v[j] = x
    end
    return v
end
julia> @code_native isort!(a, (x,y)->abs(x)<abs(y))
ERROR: expression is not a function call, or is too complex for @code_native to analyze; break it down to simpler parts if possible
 in error(::String) at ./error.jl:21
 in eval(::Module, ::Any) at ./boot.jl:230
@JeffBezanson
Copy link
Sponsor Member

too complex

Way too complex in fact. Calling expand inside the macro was always kind of sketchy, and now it's a truly bad idea. This should be really easy for simple :call expressions with no keywords or splatting; we can just wrap the arguments with typesof with no further analysis.

@StefanKarpinski
Copy link
Sponsor Member Author

I don't really understand what you're saying here. Can you expand on that?

@JeffBezanson
Copy link
Sponsor Member

Currently this works by calling expand in almost all cases, and trying to pick apart the result. This is no longer realistic. We should just look at the un-expanded arguments to the macro. All :call expressions can be handled by even the most naive implementation AFAICT, so what we're doing now is silly. The tricky cases are things like ref for getindex, vcat, etc. but there aren't that many.

@ihnorton
Copy link
Member

ihnorton commented Jul 1, 2016

The failing test appears to have already been broken, but I made it break in a more interesting way. Will see what I can do to fix, the usage is puzzling...

@MichaelHatherly or @MikeInnes why do these tests use ::Int here? e.g. test/docs.jl line 619:

let t = @doc(DocsTest.t(::Int, ::Int))
           @test docstrings_equal(Docs.@repl(DocsTest.t(0, 0)), t)
           @test docstrings_equal(Docs.@repl(DocsTest.t(::Int, ::Int)), t)
       end

@MichaelHatherly
Copy link
Member

It looks as though _repl was expecting gen_call_with_extracted_types to fail in a specific way when it encounter any :: arguments. An explicit check for :: should perhaps be enough to fix it:

diff --git a/base/docs/utils.jl b/base/docs/utils.jl
index 0230039..0224ffd 100644
--- a/base/docs/utils.jl
+++ b/base/docs/utils.jl
@@ -150,12 +150,8 @@ repl(str::AbstractString) = :(apropos($str))
 repl(other) = :(@doc $(esc(other)))

 function _repl(x)
-    docs = :(@doc $(esc(x)))
-    if isexpr(x, :call)
-        # Handles function call syntax where each argument is an atom (symbol, number, etc.)
-        t = Base.gen_call_with_extracted_types(doc, x)
-        (isexpr(t, :call, 3) && t.args[1] === doc) && (docs = t)
-    end
+    docs = (isexpr(x, :call) && !any(isexpr(x, :(::)) for x in x.args)) ?
+        Base.gen_call_with_extracted_types(doc, x) : :(@doc $(esc(x)))
     if isfield(x)
         quote
             if isa($(esc(x.args[1])), DataType)

(The :: syntax is used to return only docs for methods that match a specific signature.)

ihnorton added a commit to ihnorton/julia that referenced this issue Jul 2, 2016
Update docs/utils.jl to pass test (h/t MichaelHatherly).
@ihnorton
Copy link
Member

ihnorton commented Jul 2, 2016

Thanks. That "works" in the sense that it doesn't error out, but I'm still rather puzzled.

(The :: syntax is used to return only docs for methods that match a specific signature.)

When this is spliced, the expander returns a (quoted) syntax error. So gen_call_with_extracted_types doesn't actually give a useful result, which I assume means that the doc won't be associated with the correct method.

ihnorton added a commit that referenced this issue Jul 2, 2016
Fix #16326: use typesof in code_* for all :call expressions
mfasi pushed a commit to mfasi/julia that referenced this issue Sep 5, 2016
Update docs/utils.jl to pass test (h/t MichaelHatherly).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:regression Regression in behavior compared to a previous version
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants