Skip to content

Commit 1735d8f

Browse files
authored
make just one MethodTable (#58131)
Instead of hiding the fragments of the method table in each TypeName, make one variable `Core.GlobalMethods` with access to all methods. The need to split them early for performance apparently had been long past since kwargs and constructors were already using a single table and cache anyways. Some new concepts introduced here: - A single Method can now be added to multiple functions. So instead of using eval in a for loop, we could define it just once (see example below). - Several fields (`max_args`, `name`, and `backedges`) were moved from MethodTable to their TypeName. - TypeName currently has a (user-modifiable) field called `singletonname`. If set to something other than `name`, it may be used for pretty printing of a singleton object using its "canonical" (unmangled) name, particularly for `function`. - `Core.Builtin` method table entries are even more normal now, with valid `sig` fields, and special logic to specifically prevent adding methods which would become ambiguous with them (as that would violate the tfuncs we have for them). - `Core.GlobalMethods` is a `Base.Experimental.@MethodTable GlobalMethods`. - Each `MethodTable` contains a separate `MethodCache` object for managing fast dispatch lookups. We may want to use this for the `Method` field containing the `invokes` list so that lookups there get more of the same optimizations as global calls. - Methods could be put into any number of different MethodTables (or none). The `Method.primary_world` field is intended to reflect whether it is currently put into the GlobalMethods table, and what world to use in the GlobalMethods table for running its generator, and otherwise is meaningless. - The lock for TypeName backedges is a single global lock now, in `Core.GlobalMethods.mc`. - The `backedges` in TypeName are stored on the "top-most" typename in the hierarchy, to enable efficient lookup (although we might want to consider replacing this entirely with a TypeMap). The "top-most" typename is the typename of the type closest to Any, after union-splitting, which doesn't have an intersection with Builtin (so Function and Any by implication continue to not require scanning for missing backedges since it is not permitted to add a Method applicable to all functions). - Support for having backedges from experimental method tables was removed since it was unsound and had been already replaced with staticdata.jl several months ago. - Documentation lookup for `IncludeInto` is fixed (previously attached only to `Main.include` instead of all `include` functions). Example: given this existing code in base/operators: for op in (:+, :*, :&, :|, :xor, :min, :max, :kron) @eval begin ($op)(a, b, c, xs...) = (@inline; afoldl($op, ($op)(($op)(a,b),c), xs...)) end end It could now instead be equivalently written as: let ops = Union{typeof(+), typeof(*), typeof(&), typeof(|), typeof(xor), typeof(min), typeof(max), typeof(kron)} (op::ops)(a, b, c, xs...) = (@inline; afoldl(op, (op)((op)(a,b),c), xs...)) end Fixes #57560
1 parent 8ac9291 commit 1735d8f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+982
-1010
lines changed

Compiler/src/Compiler.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ else
3838
using Core.Intrinsics, Core.IR
3939

4040
using Core: ABIOverride, Builtin, CodeInstance, IntrinsicFunction, MethodInstance, MethodMatch,
41-
MethodTable, PartialOpaque, SimpleVector, TypeofVararg,
41+
MethodTable, MethodCache, PartialOpaque, SimpleVector, TypeofVararg,
4242
_apply_iterate, apply_type, compilerbarrier, donotdelete, memoryref_isassigned,
4343
memoryrefget, memoryrefnew, memoryrefoffset, memoryrefset!, print, println, show, svec,
4444
typename, unsafe_write, write

Compiler/src/abstractinterpretation.jl

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -363,15 +363,13 @@ function find_union_split_method_matches(interp::AbstractInterpreter, argtypes::
363363
arg_n = split_argtypes[i]::Vector{Any}
364364
sig_n = argtypes_to_type(arg_n)
365365
sig_n === Bottom && continue
366-
mt = ccall(:jl_method_table_for, Any, (Any,), sig_n)
367-
mt === nothing && return FailedMethodMatch("Could not identify method table for call")
368-
mt = mt::MethodTable
369366
thismatches = findall(sig_n, method_table(interp); limit = max_methods)
370367
if thismatches === nothing
371368
return FailedMethodMatch("For one of the union split cases, too many methods matched")
372369
end
373370
valid_worlds = intersect(valid_worlds, thismatches.valid_worlds)
374371
thisfullmatch = any(match::MethodMatch->match.fully_covers, thismatches)
372+
mt = Core.GlobalMethods
375373
thisinfo = MethodMatchInfo(thismatches, mt, sig_n, thisfullmatch)
376374
push!(infos, thisinfo)
377375
for idx = 1:length(thismatches)
@@ -385,18 +383,14 @@ function find_union_split_method_matches(interp::AbstractInterpreter, argtypes::
385383
end
386384

387385
function find_simple_method_matches(interp::AbstractInterpreter, @nospecialize(atype), max_methods::Int)
388-
mt = ccall(:jl_method_table_for, Any, (Any,), atype)
389-
if mt === nothing
390-
return FailedMethodMatch("Could not identify method table for call")
391-
end
392-
mt = mt::MethodTable
393386
matches = findall(atype, method_table(interp); limit = max_methods)
394387
if matches === nothing
395388
# this means too many methods matched
396389
# (assume this will always be true, so we don't compute / update valid age in this case)
397390
return FailedMethodMatch("Too many methods matched")
398391
end
399392
fullmatch = any(match::MethodMatch->match.fully_covers, matches)
393+
mt = Core.GlobalMethods
400394
info = MethodMatchInfo(matches, mt, atype, fullmatch)
401395
applicable = MethodMatchTarget[MethodMatchTarget(matches[idx], info.edges, idx) for idx = 1:length(matches)]
402396
return MethodMatches(applicable, info, matches.valid_worlds)

Compiler/src/stmtinfo.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,16 @@ end
4747
add_edges_impl(edges::Vector{Any}, info::MethodMatchInfo) = _add_edges_impl(edges, info)
4848
function _add_edges_impl(edges::Vector{Any}, info::MethodMatchInfo, mi_edge::Bool=false)
4949
if !fully_covering(info)
50-
# add legacy-style missing backedge info also
5150
exists = false
5251
for i in 2:length(edges)
53-
if edges[i] === info.mt && edges[i-1] == info.atype
52+
if edges[i] === Core.GlobalMethods && edges[i-1] == info.atype
5453
exists = true
5554
break
5655
end
5756
end
5857
if !exists
5958
push!(edges, info.atype)
60-
push!(edges, info.mt)
59+
push!(edges, Core.GlobalMethods)
6160
end
6261
end
6362
nmatches = length(info.results)

Compiler/src/tfuncs.jl

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3199,15 +3199,12 @@ function _hasmethod_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, sv
31993199
isdispatchelem(ft) || return CallMeta(Bool, Any, Effects(), NoCallInfo()) # check that we might not have a subtype of `ft` at runtime, before doing supertype lookup below
32003200
types = rewrap_unionall(Tuple{ft, unwrapped.parameters...}, types)::Type
32013201
end
3202-
mt = ccall(:jl_method_table_for, Any, (Any,), types)
3203-
if !isa(mt, MethodTable)
3204-
return CallMeta(Bool, Any, EFFECTS_THROWS, NoCallInfo())
3205-
end
32063202
match, valid_worlds = findsup(types, method_table(interp))
32073203
update_valid_age!(sv, valid_worlds)
32083204
if match === nothing
32093205
rt = Const(false)
32103206
vresults = MethodLookupResult(Any[], valid_worlds, true)
3207+
mt = Core.GlobalMethods
32113208
vinfo = MethodMatchInfo(vresults, mt, types, false) # XXX: this should actually be an info with invoke-type edge
32123209
else
32133210
rt = Const(true)

Compiler/src/typeinfer.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ function store_backedges(caller::CodeInstance, edges::SimpleVector)
767767
if item isa Core.Binding
768768
maybe_add_binding_backedge!(item, caller)
769769
elseif item isa MethodTable
770-
ccall(:jl_method_table_add_backedge, Cvoid, (Any, Any, Any), item, invokesig, caller)
770+
ccall(:jl_method_table_add_backedge, Cvoid, (Any, Any), invokesig, caller)
771771
else
772772
item::MethodInstance
773773
ccall(:jl_method_instance_add_backedge, Cvoid, (Any, Any, Any), item, invokesig, caller)

Compiler/src/utilities.jl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,8 @@ end
158158

159159
function get_compileable_sig(method::Method, @nospecialize(atype), sparams::SimpleVector)
160160
isa(atype, DataType) || return nothing
161-
mt = ccall(:jl_method_get_table, Any, (Any,), method)
162-
mt === nothing && return nothing
163-
return ccall(:jl_normalize_to_compilable_sig, Any, (Any, Any, Any, Any, Cint),
164-
mt, atype, sparams, method, #=int return_if_compileable=#1)
161+
return ccall(:jl_normalize_to_compilable_sig, Any, (Any, Any, Any, Cint),
162+
atype, sparams, method, #=int return_if_compileable=#1)
165163
end
166164

167165

base/Base_compiler.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ function Core.kwcall(kwargs::NamedTuple, ::typeof(invoke), f, T, args...)
218218
return invoke(Core.kwcall, T, kwargs, f, args...)
219219
end
220220
# invoke does not have its own call cache, but kwcall for invoke does
221-
setfield!(typeof(invoke).name.mt, :max_args, 3, :monotonic) # invoke, f, T, args...
221+
setfield!(typeof(invoke).name, :max_args, Int32(3), :monotonic) # invoke, f, T, args...
222222

223223
# define applicable(f, T, args...; kwargs...), without kwargs wrapping
224224
# to forward to applicable
@@ -252,7 +252,7 @@ function Core.kwcall(kwargs::NamedTuple, ::typeof(invokelatest), f, args...)
252252
@inline
253253
return Core.invokelatest(Core.kwcall, kwargs, f, args...)
254254
end
255-
setfield!(typeof(invokelatest).name.mt, :max_args, 2, :monotonic) # invokelatest, f, args...
255+
setfield!(typeof(invokelatest).name, :max_args, Int32(2), :monotonic) # invokelatest, f, args...
256256

257257
"""
258258
invoke_in_world(world, f, args...; kwargs...)
@@ -286,7 +286,7 @@ function Core.kwcall(kwargs::NamedTuple, ::typeof(invoke_in_world), world::UInt,
286286
@inline
287287
return Core.invoke_in_world(world, Core.kwcall, kwargs, f, args...)
288288
end
289-
setfield!(typeof(invoke_in_world).name.mt, :max_args, 3, :monotonic) # invoke_in_world, world, f, args...
289+
setfield!(typeof(invoke_in_world).name, :max_args, Int32(3), :monotonic) # invoke_in_world, world, f, args...
290290

291291
# core operations & types
292292
include("promotion.jl")

base/deprecated.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ macro deprecate(old, new, export_old=true)
211211
maybe_export,
212212
:($(esc(old)) = begin
213213
$meta
214-
depwarn($"`$oldcall` is deprecated, use `$newcall` instead.", Core.Typeof($(esc(fnexpr))).name.mt.name)
214+
depwarn($"`$oldcall` is deprecated, use `$newcall` instead.", Core.Typeof($(esc(fnexpr))).name.singletonname)
215215
$(esc(new))
216216
end))
217217
else
@@ -222,7 +222,7 @@ macro deprecate(old, new, export_old=true)
222222
export_old ? Expr(:export, esc(old)) : nothing,
223223
:(function $(esc(old))(args...; kwargs...)
224224
$meta
225-
depwarn($"`$old` is deprecated, use `$new` instead.", Core.Typeof($(esc(old))).name.mt.name)
225+
depwarn($"`$old` is deprecated, use `$new` instead.", Core.Typeof($(esc(old))).name.singletonname)
226226
$(esc(new))(args...; kwargs...)
227227
end))
228228
end

base/docs/bindings.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,6 @@ end
4242

4343
aliasof(b::Binding) = defined(b) ? (a = aliasof(resolve(b), b); defined(a) ? a : b) : b
4444
aliasof(d::DataType, b) = Binding(d.name.module, d.name.name)
45-
aliasof::Function, b) = (m = typeof(λ).name.mt; Binding(m.module, m.name))
45+
aliasof::Function, b) = (m = typeof(λ).name; Binding(m.module, m.singletonname))
4646
aliasof(m::Module, b) = Binding(m, nameof(m))
4747
aliasof(other, b) = b

base/errorshow.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ function showerror(io::IO, ex::MethodError)
328328
print(io, "\nIn case you're trying to index into the array, use square brackets [] instead of parentheses ().")
329329
end
330330
# Check for local functions that shadow methods in Base
331-
let name = ft.name.mt.name
331+
let name = ft.name.singletonname
332332
if f_is_function && isdefined(Base, name)
333333
basef = getfield(Base, name)
334334
if basef !== f && hasmethod(basef, arg_types)

base/invalidation.jl

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,36 +15,6 @@ function iterate(gri::GlobalRefIterator, i = 1)
1515
return ((b::Core.Binding).globalref, i+1)
1616
end
1717

18-
const TYPE_TYPE_MT = Type.body.name.mt
19-
const NONFUNCTION_MT = Core.MethodTable.name.mt
20-
function foreach_module_mtable(visit, m::Module, world::UInt)
21-
for gb in globalrefs(m)
22-
binding = gb.binding
23-
bpart = lookup_binding_partition(world, binding)
24-
if is_defined_const_binding(binding_kind(bpart))
25-
v = partition_restriction(bpart)
26-
uw = unwrap_unionall(v)
27-
name = gb.name
28-
if isa(uw, DataType)
29-
tn = uw.name
30-
if tn.module === m && tn.name === name && tn.wrapper === v && isdefined(tn, :mt)
31-
# this is the original/primary binding for the type (name/wrapper)
32-
mt = tn.mt
33-
if mt !== nothing && mt !== TYPE_TYPE_MT && mt !== NONFUNCTION_MT
34-
@assert mt.module === m
35-
visit(mt) || return false
36-
end
37-
end
38-
elseif isa(v, Core.MethodTable) && v.module === m && v.name === name
39-
# this is probably an external method table here, so let's
40-
# assume so as there is no way to precisely distinguish them
41-
visit(v) || return false
42-
end
43-
end
44-
end
45-
return true
46-
end
47-
4818
function foreachgr(visit, src::CodeInfo)
4919
stmts = src.code
5020
for i = 1:length(stmts)

base/methodshow.jl

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ function kwarg_decl(m::Method, kwtype = nothing)
8181
if m.sig !== Tuple # OpaqueClosure or Builtin
8282
kwtype = typeof(Core.kwcall)
8383
sig = rewrap_unionall(Tuple{kwtype, NamedTuple, (unwrap_unionall(m.sig)::DataType).parameters...}, m.sig)
84-
kwli = ccall(:jl_methtable_lookup, Any, (Any, Any, UInt), kwtype.name.mt, sig, get_world_counter())
84+
kwli = ccall(:jl_methtable_lookup, Any, (Any, UInt), sig, get_world_counter())
8585
if kwli !== nothing
8686
kwli = kwli::Method
8787
slotnames = ccall(:jl_uncompress_argnames, Vector{Symbol}, (Any,), kwli.slot_syms)
@@ -259,10 +259,10 @@ function show_method(io::IO, m::Method; modulecolor = :light_black, digit_align_
259259
end
260260

261261
function show_method_list_header(io::IO, ms::MethodList, namefmt::Function)
262-
mt = ms.mt
263-
name = mt.name
264-
hasname = isdefined(mt.module, name) &&
265-
typeof(getfield(mt.module, name)) <: Function
262+
tn = ms.tn
263+
name = tn.singletonname
264+
hasname = isdefined(tn.module, name) &&
265+
typeof(getfield(tn.module, name)) <: Function
266266
n = length(ms)
267267
m = n==1 ? "method" : "methods"
268268
print(io, "# $n $m")
@@ -271,18 +271,18 @@ function show_method_list_header(io::IO, ms::MethodList, namefmt::Function)
271271
if hasname
272272
what = (startswith(sname, '@') ?
273273
"macro"
274-
: mt.module === Core && mt.defs isa Core.TypeMapEntry && (mt.defs.func::Method).sig === Tuple ?
274+
: tn.module === Core && tn.wrapper <: Core.Builtin ?
275275
"builtin function"
276276
: # else
277277
"generic function")
278278
print(io, " for ", what, " ", namedisplay, " from ")
279279

280-
col = get!(() -> popfirst!(STACKTRACE_MODULECOLORS), STACKTRACE_FIXEDCOLORS, parentmodule_before_main(ms.mt.module))
280+
col = get!(() -> popfirst!(STACKTRACE_MODULECOLORS), STACKTRACE_FIXEDCOLORS, parentmodule_before_main(tn.module))
281281

282-
printstyled(io, ms.mt.module, color=col)
282+
printstyled(io, tn.module, color=col)
283283
elseif '#' in sname
284284
print(io, " for anonymous function ", namedisplay)
285-
elseif mt === _TYPE_NAME.mt
285+
elseif tn === _TYPE_NAME || iskindtype(tn.wrapper)
286286
print(io, " for type constructor")
287287
else
288288
print(io, " for callable object")
@@ -293,6 +293,8 @@ end
293293
# Determine the `modulecolor` value to pass to `show_method`
294294
function _modulecolor(method::Method)
295295
mmt = get_methodtable(method)
296+
# TODO: this looks like a buggy bit of internal hacking, so disable for now
297+
return nothing
296298
if mmt === nothing || mmt.module === parentmodule(method)
297299
return nothing
298300
end
@@ -314,10 +316,10 @@ function _modulecolor(method::Method)
314316
end
315317

316318
function show_method_table(io::IO, ms::MethodList, max::Int=-1, header::Bool=true)
317-
mt = ms.mt
318-
name = mt.name
319-
hasname = isdefined(mt.module, name) &&
320-
typeof(getfield(mt.module, name)) <: Function
319+
tn = ms.tn
320+
name = tn.singletonname
321+
hasname = isdefined(tn.module, name) &&
322+
typeof(getfield(tn.module, name)) <: Function
321323
if header
322324
show_method_list_header(io, ms, str -> "\""*str*"\"")
323325
end
@@ -458,7 +460,6 @@ function show(io::IO, ::MIME"text/html", m::Method)
458460
end
459461

460462
function show(io::IO, mime::MIME"text/html", ms::MethodList)
461-
mt = ms.mt
462463
show_method_list_header(io, ms, str -> "<b>"*str*"</b>")
463464
print(io, "<ul>")
464465
for meth in ms

base/operators.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ function afoldl(op, a, bs...)
633633
end
634634
return y
635635
end
636-
setfield!(typeof(afoldl).name.mt, :max_args, 34, :monotonic)
636+
setfield!(typeof(afoldl).name, :max_args, Int32(34), :monotonic)
637637

638638
for op in (:+, :*, :&, :|, :xor, :min, :max, :kron)
639639
@eval begin

base/reflection.jl

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -933,13 +933,7 @@ this is a compiler-generated name. For explicitly-declared subtypes of
933933
`Function`, it is the name of the function's type.
934934
"""
935935
function nameof(f::Function)
936-
t = typeof(f)
937-
mt = t.name.mt
938-
if mt === Symbol.name.mt
939-
# uses shared method table, so name is not unique to this function type
940-
return nameof(t)
941-
end
942-
return mt.name
936+
return typeof(f).name.singletonname
943937
end
944938

945939
function nameof(f::Core.IntrinsicFunction)

base/runtime_internals.jl

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,14 +1356,14 @@ hasproperty(x, s::Symbol) = s in propertynames(x)
13561356
Make method `m` uncallable and force recompilation of any methods that use(d) it.
13571357
"""
13581358
function delete_method(m::Method)
1359-
ccall(:jl_method_table_disable, Cvoid, (Any, Any), get_methodtable(m), m)
1359+
ccall(:jl_method_table_disable, Cvoid, (Any,), m)
13601360
end
13611361

13621362

13631363
# type for reflecting and pretty-printing a subset of methods
13641364
mutable struct MethodList <: AbstractArray{Method,1}
13651365
ms::Array{Method,1}
1366-
mt::Core.MethodTable
1366+
tn::Core.TypeName # contains module.singletonname globalref for altering some aspects of printing
13671367
end
13681368

13691369
size(m::MethodList) = size(m.ms)
@@ -1374,10 +1374,10 @@ function MethodList(mt::Core.MethodTable)
13741374
visit(mt) do m
13751375
push!(ms, m)
13761376
end
1377-
return MethodList(ms, mt)
1377+
return MethodList(ms, Any.name)
13781378
end
13791379

1380-
function matches_to_methods(ms::Array{Any,1}, mt::Core.MethodTable, mod)
1380+
function matches_to_methods(ms::Array{Any,1}, tn::Core.TypeName, mod)
13811381
# Lack of specialization => a comprehension triggers too many invalidations via _collect, so collect the methods manually
13821382
ms = Method[(ms[i]::Core.MethodMatch).method for i in 1:length(ms)]
13831383
# Remove shadowed methods with identical type signatures
@@ -1392,7 +1392,7 @@ function matches_to_methods(ms::Array{Any,1}, mt::Core.MethodTable, mod)
13921392
mod === nothing || filter!(ms) do m
13931393
return parentmodule(m) mod
13941394
end
1395-
return MethodList(ms, mt)
1395+
return MethodList(ms, tn)
13961396
end
13971397

13981398
"""
@@ -1414,7 +1414,7 @@ function methods(@nospecialize(f), @nospecialize(t),
14141414
world = get_world_counter()
14151415
world == typemax(UInt) && error("code reflection cannot be used from generated functions")
14161416
ms = _methods(f, t, -1, world)::Vector{Any}
1417-
return matches_to_methods(ms, typeof(f).name.mt, mod)
1417+
return matches_to_methods(ms, typeof(f).name, mod)
14181418
end
14191419
methods(@nospecialize(f), @nospecialize(t), mod::Module) = methods(f, t, (mod,))
14201420

@@ -1425,7 +1425,7 @@ function methods_including_ambiguous(@nospecialize(f), @nospecialize(t))
14251425
min = RefValue{UInt}(typemin(UInt))
14261426
max = RefValue{UInt}(typemax(UInt))
14271427
ms = _methods_by_ftype(tt, nothing, -1, world, true, min, max, Ptr{Int32}(C_NULL))::Vector{Any}
1428-
return matches_to_methods(ms, typeof(f).name.mt, nothing)
1428+
return matches_to_methods(ms, typeof(f).name, nothing)
14291429
end
14301430

14311431
function methods(@nospecialize(f),
@@ -1623,10 +1623,8 @@ end
16231623

16241624
function get_nospecializeinfer_sig(method::Method, @nospecialize(atype), sparams::SimpleVector)
16251625
isa(atype, DataType) || return method.sig
1626-
mt = ccall(:jl_method_get_table, Any, (Any,), method)
1627-
mt === nothing && return method.sig
1628-
return ccall(:jl_normalize_to_compilable_sig, Any, (Any, Any, Any, Any, Cint),
1629-
mt, atype, sparams, method, #=int return_if_compileable=#0)
1626+
return ccall(:jl_normalize_to_compilable_sig, Any, (Any, Any, Any, Cint),
1627+
atype, sparams, method, #=int return_if_compileable=#0)
16301628
end
16311629

16321630
is_nospecialized(method::Method) = method.nospecialize 0

0 commit comments

Comments
 (0)