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

RFC: Add @will_specialize macro and will_specialize function to InteractiveUtils #33146

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion stdlib/InteractiveUtils/src/InteractiveUtils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ module InteractiveUtils

export apropos, edit, less, code_warntype, code_llvm, code_native, methodswith, varinfo,
versioninfo, subtypes, @which, @edit, @less, @functionloc, @code_warntype,
@code_typed, @code_lowered, @code_llvm, @code_native, clipboard
@code_typed, @code_lowered, @code_llvm, @code_native, clipboard,
@will_specialize, will_specialize

import Base.Docs.apropos

Expand Down
13 changes: 13 additions & 0 deletions stdlib/InteractiveUtils/src/codeview.jl
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,16 @@ code_native(io::IO, @nospecialize(f), @nospecialize(types=Tuple); syntax::Symbol
code_native(@nospecialize(f), @nospecialize(types=Tuple); syntax::Symbol=:att, debuginfo::Symbol=:default) =
code_native(stdout, f, types; syntax=syntax, debuginfo=debuginfo)
code_native(::IO, ::Any, ::Symbol) = error("illegal code_native call") # resolve ambiguous call

"""
will_specialize(f, types)

Returns `true` if the specialization on this method signature will be compiled
into the cache for this method.
Copy link
Contributor

@nickrobinson251 nickrobinson251 Sep 12, 2019

Choose a reason for hiding this comment

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

Perhaps worth making even more explicit that this means "Returns true if the call will be specialized on all its arguments"?

I really like the explanation you gave in the opening post of the PR :)

Could some of the examples you give be included in the docstring (as doctests)?

"""
function will_specialize(@nospecialize(f), @nospecialize(t))
isa_compileable_sig = map(Base.method_instances(f, t)) do mi
ccall(:jl_isa_compileable_sig, Cint, (Any, Any), mi.specTypes, mi.def) != 0
end
return !isempty(isa_compileable_sig) && all(isa_compileable_sig)
end
15 changes: 15 additions & 0 deletions stdlib/InteractiveUtils/src/macros.jl
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,13 @@ macro code_lowered(ex0...)
end
end

macro will_specialize(ex0...)
thecall = gen_call_with_extracted_types_and_kwargs(__module__, :will_specialize, ex0)
quote
$thecall
end
end

"""
@functionloc

Expand Down Expand Up @@ -247,3 +254,11 @@ Set the optional keyword argument `debuginfo` by putting it before the function
`debuginfo` may be one of `:source` (default) or `:none`, to specify the verbosity of code comments.
"""
:@code_native

"""
@will_specialize

Evaluates the arguments to the function or macro call, determines their types, and calls
[`will_specialize`](@ref) on the resulting expression.
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if it is worth cross-referencing Base's at-specialize / at-nospecialize for extra context?

e.g.

Suggested change
[`will_specialize`](@ref) on the resulting expression.
[`will_specialize`](@ref) on the resulting expression.
See also: [`specialize`](@ref), [`nospecialize`](@ref)

(^ I think at-ref to Base function will "just work" but not 100% sure if this is the right suntax for it)

"""
:@will_specialize
42 changes: 42 additions & 0 deletions stdlib/InteractiveUtils/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -389,3 +389,45 @@ if Sys.iswindows() || Sys.isapple()
@test clipboard() == str
end
end

# tests for @will_specialize
let
f1(x) = typemax(x)
@test !(@will_specialize f1(Int))
@test !(@will_specialize f1(Float32))
@test !(@will_specialize f1(Float64))
f2(t::Type) = t
@test !(@will_specialize f2(Int))
@test !(@will_specialize f2(Float32))
@test !(@will_specialize f2(Float64))
@test !(@will_specialize f2(String))
function f3(t::Type)
x = ones(t, 10)
return sum(map(sin, x))
end
@test !(@will_specialize f3(Int))
@test !(@will_specialize f3(Float32))
@test !(@will_specialize f3(Float64))
g0() = 0
@test @will_specialize g0()
g1(x) = x
@test @will_specialize g1(1)
@test @will_specialize g1(1.1)
@test @will_specialize g1("foo")
g2(x, y) = x * y
@test @will_specialize g2(1, 2)
@test @will_specialize g2(1, 2.2)
@test @will_specialize g2(1.1, 2)
@test @will_specialize g2(1.1, 2.2)
@test @will_specialize g2("foo", "bar")
g3(x, y, z) = x * y * z
@test @will_specialize g3(1, 2, 3)
@test @will_specialize g3(1, 2, 3.3)
@test @will_specialize g3(1, 2.2, 3)
@test @will_specialize g3(1, 2.2, 3.3)
@test @will_specialize g3(1.1, 2, 3)
@test @will_specialize g3(1.1, 2, 3.3)
@test @will_specialize g3(1.1, 2.2, 3)
@test @will_specialize g3(1.1, 2.2, 3)
@test @will_specialize g3("foo", "bar", "baz")
end