6969
7070Like `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
7586else
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
8596end
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"""
108118static_method_count (@nospecialize (f)) = static_method_count (f, Tuple{Vararg{Any}})
109119if 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
114132else
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
123142end
@@ -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.
141160function _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)
148171end
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
155183end
156184# Like Base.signature_type, but starts with a type for f_type already.
157185function _combine_signature_type (@nospecialize (f_type:: Type ), @nospecialize (args:: Type ))
0 commit comments