-
Notifications
You must be signed in to change notification settings - Fork 9
/
Tricks.jl
44 lines (36 loc) · 1.67 KB
/
Tricks.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
module Tricks
using Base: rewrap_unionall, unwrap_unionall, uncompressed_ast
using Base: CodeInfo
export static_hasmethod
# This is used to create the CodeInfo returned by static_hasmethod.
_hasmethod_false(@nospecialize(f), @nospecialize(t)) = false
_hasmethod_true(@nospecialize(f), @nospecialize(t)) = true
"""
static_hasmethod(f, type_tuple::Type{<:Tuple)
Like `hasmethod` but runs at compile-time (and does not accept a worldage argument).
!!! Note
This absolutely must *not* be called dynamically. Else it will fail to update
when new methods are declared.
If you do not know how to ensure that it is not called dynamically,
do not use this.
"""
@generated function static_hasmethod(@nospecialize(f), @nospecialize(t::Type{T}),) where {T<:Tuple}
# The signature type:
world = typemax(UInt)
method_insts = Core.Compiler.method_instances(f.instance, T, world)
method_doesnot_exist = isempty(method_insts)
ret_func = method_doesnot_exist ? _hasmethod_false : _hasmethod_true
ci_orig = uncompressed_ast(typeof(ret_func).name.mt.defs.func)
ci = ccall(:jl_copy_code_info, Ref{CodeInfo}, (Any,), ci_orig)
# Now we add the edges so if a method is defined this recompiles
if method_doesnot_exist
# No method so attach to method table
mt = f.name.mt
typ = rewrap_unionall(Tuple{f, unwrap_unionall(T).parameters...}, T)
ci.edges = Core.Compiler.vect(mt, typ)
else # method exists, attach edges to all instances
ci.edges = method_insts
end
return ci
end
end