Skip to content

Commit bc371ac

Browse files
authored
Merge pull request #40 from chengchingwen/master
handle world ages for julia v1.10
2 parents 019aeb9 + fb26718 commit bc371ac

File tree

2 files changed

+50
-28
lines changed

2 files changed

+50
-28
lines changed

src/Tricks.jl

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -69,22 +69,33 @@ end
6969
7070
Like `methods` but runs at compile-time (and does not accept a worldage argument).
7171
"""
72-
const static_methods = if VERSION >= v"1.10.0-DEV.609"
73-
# feature is now built in
74-
methods
72+
static_methods(@nospecialize(f)) = static_methods(f, Tuple{Vararg{Any}})
73+
if VERSION >= v"1.10.0-DEV.609"
74+
function __static_methods(world, source, T, self, f, _T)
75+
list_of_methods = _methods(f, T, nothing, world)
76+
ci = create_codeinfo_with_returnvalue([Symbol("#self#"), :f, :_T], [:T], (:T,), :($list_of_methods))
77+
78+
# Now we add the edges so if a method is defined this recompiles
79+
ci.edges = _method_table_all_edges_all_methods(f, T, world)
80+
return ci
81+
end
82+
@eval function static_methods(@nospecialize(f) , @nospecialize(_T::Type{T})) where {T <: Tuple}
83+
$(Expr(:meta, :generated, __static_methods))
84+
$(Expr(:meta, :generated_only))
85+
end
7586
else
76-
_static_methods(@nospecialize(f)) = static_methods(f, Tuple{Vararg{Any}})
77-
@generated function _static_methods(@nospecialize(f) , @nospecialize(_T::Type{T})) where {T <: Tuple}
78-
list_of_methods = _methods(f, T)
87+
@generated function static_methods(@nospecialize(f) , @nospecialize(_T::Type{T})) where {T <: Tuple}
88+
world = typemax(UInt)
89+
list_of_methods = _methods(f, T, nothing, world)
7990
ci = create_codeinfo_with_returnvalue([Symbol("#self#"), :f, :_T], [:T], (:T,), :($list_of_methods))
8091

8192
# Now we add the edges so if a method is defined this recompiles
82-
ci.edges = _method_table_all_edges_all_methods(f, T)
93+
ci.edges = _method_table_all_edges_all_methods(f, T, world)
8394
return ci
8495
end
8596
end
8697

87-
function _method_table_all_edges_all_methods(f, T)
98+
function _method_table_all_edges_all_methods(f, T, world = Base.get_world_counter())
8899
mt = f.name.mt
89100

90101
# We add an edge to the MethodTable itself so that when any new methods
@@ -93,8 +104,7 @@ function _method_table_all_edges_all_methods(f, T)
93104

94105
# We want to add an edge to _every existing method instance_, so that
95106
# the deletion of any one of them will trigger recompilation of the function.
96-
world = typemax(UInt)
97-
method_insts = _method_instances(f, T)
107+
method_insts = _method_instances(f, T, world)
98108
covering_method_insts = method_insts
99109

100110
return vcat(mt_edges, covering_method_insts)
@@ -107,17 +117,26 @@ Returns `length(methods(f, tt))` but runs at compile-time (and does not accept a
107117
"""
108118
static_method_count(@nospecialize(f)) = static_method_count(f, Tuple{Vararg{Any}})
109119
if VERSION >= v"1.10.0-DEV.609"
110-
# feature is now built in
111-
function static_method_count(@nospecialize(f) , @nospecialize(_T::Type{T})) where {T <: Tuple}
112-
return length(methods(f, _T))
120+
function __static_method_count(world, source, T, self, f, _T)
121+
method_count = length(_methods(f, T, nothing, world))
122+
ci = create_codeinfo_with_returnvalue([Symbol("#self#"), :f, :_T], [:T], (:T,), :($method_count))
123+
124+
# Now we add the edges so if a method is defined this recompiles
125+
ci.edges = _method_table_all_edges_all_methods(f, T, world)
126+
return ci
127+
end
128+
@eval function static_method_count(@nospecialize(f) , @nospecialize(_T::Type{T})) where {T <: Tuple}
129+
$(Expr(:meta, :generated, __static_method_count))
130+
$(Expr(:meta, :generated_only))
113131
end
114132
else
115133
@generated function static_method_count(@nospecialize(f) , @nospecialize(_T::Type{T})) where {T <: Tuple}
116-
method_count = length(_methods(f, T))
134+
world = typemax(UInt)
135+
method_count = length(_methods(f, T, nothing, world))
117136
ci = create_codeinfo_with_returnvalue([Symbol("#self#"), :f, :_T], [:T], (:T,), :($method_count))
118137

119138
# Now we add the edges so if a method is defined this recompiles
120-
ci.edges = _method_table_all_edges_all_methods(f, T)
139+
ci.edges = _method_table_all_edges_all_methods(f, T, world)
121140
return ci
122141
end
123142
end
@@ -139,19 +158,28 @@ Base.@pure static_fieldcount(t::Type) = Base.fieldcount(t)
139158
# - https://github.com/JuliaLang/julia/blob/4931faa34a8a1c98b39fb52ed4eb277729120128/base/reflection.jl#L1047-L1055
140159
# Like Base.methods, but accepts f as a _type_ instead of an instance.
141160
function _methods(@nospecialize(f_type), @nospecialize(t_type),
142-
mod::Union{Tuple{Module},AbstractArray{Module},Nothing}=nothing)
161+
mod::Union{Tuple{Module},AbstractArray{Module},Nothing}=nothing, world = Base.get_world_counter())
143162
tt = _combine_signature_type(f_type, t_type)
144-
lim, world = -1, typemax(UInt)
163+
lim = -1
145164
mft = Core.Compiler._methods_by_ftype(tt, lim, world)
146-
ms = Base.Method[_get_method(m) for m in mft if (mod === nothing || m.method.module mod)]
165+
if mft === nothing
166+
ms = Base.Method[]
167+
else
168+
ms = Base.Method[_get_method(m) for m in mft if (mod === nothing || m.method.module mod)]
169+
end
147170
return Base.MethodList(ms, f_type.name.mt)
148171
end
172+
149173
# Like Core.Compiler.method_instances, but accepts f as a _type_ instead of an instance.
150-
function _method_instances(@nospecialize(f_type), @nospecialize(t_type))
174+
function _method_instances(@nospecialize(f_type), @nospecialize(t_type), world = Base.get_world_counter())
151175
tt = _combine_signature_type(f_type, t_type)
152-
lim, world = -1, typemax(UInt)
176+
lim = -1
153177
mft = Core.Compiler._methods_by_ftype(tt, lim, world)
154-
return Core.MethodInstance[_specialize_method(match) for match in mft]
178+
if mft === nothing
179+
return Core.MethodInstance[]
180+
else
181+
return Core.MethodInstance[_specialize_method(match) for match in mft]
182+
end
155183
end
156184
# Like Base.signature_type, but starts with a type for f_type already.
157185
function _combine_signature_type(@nospecialize(f_type::Type), @nospecialize(args::Type))

test/runtests.jl

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -189,13 +189,7 @@ VERSION >= v"1.3" && @testset "static_method_count" begin
189189
# Code Generation
190190
code_typed = (@code_typed static_method_count(f))
191191
@test code_typed[2] === Int # return type
192-
193-
if VERSION < v"1.10.0-DEV.609"
194-
@test has_no_calls(code_typed[1].code)
195-
else
196-
# Actually does have calls on new version, because `methods` isn't constant folded right now
197-
@test_broken has_no_calls(code_typed[1].code)
198-
end
192+
@test has_no_calls(code_typed[1].code)
199193

200194
@testset "delete method" begin
201195
i(::Int) = 1

0 commit comments

Comments
 (0)