StatProfilerHTML.jl report
Generated on ons 9 okt 2019 08:41:28
File source code
Line Exclusive Inclusive Code
1 # This file is a part of Julia. License is MIT: https://julialang.org/license
2
3 # name and module reflection
4
5 """
6 nameof(m::Module) -> Symbol
7
8 Get the name of a `Module` as a `Symbol`.
9
10 # Examples
11 ```jldoctest
12 julia> nameof(Base.Broadcast)
13 :Broadcast
14 ```
15 """
16 nameof(m::Module) = ccall(:jl_module_name, Ref{Symbol}, (Any,), m)
17
18 """
19 parentmodule(m::Module) -> Module
20
21 Get a module's enclosing `Module`. `Main` is its own parent.
22
23 # Examples
24 ```jldoctest
25 julia> parentmodule(Main)
26 Main
27
28 julia> parentmodule(Base.Broadcast)
29 Base
30 ```
31 """
32 parentmodule(m::Module) = ccall(:jl_module_parent, Ref{Module}, (Any,), m)
33
34 """
35 moduleroot(m::Module) -> Module
36
37 Find the root module of a given module. This is the first module in the chain of
38 parent modules of `m` which is either a registered root module or which is its
39 own parent module.
40 """
41 function moduleroot(m::Module)
42 while true
43 is_root_module(m) && return m
44 p = parentmodule(m)
45 p == m && return m
46 m = p
47 end
48 end
49
50 """
51 @__MODULE__ -> Module
52
53 Get the `Module` of the toplevel eval,
54 which is the `Module` code is currently being read from.
55 """
56 macro __MODULE__()
57 return __module__
58 end
59
60 """
61 fullname(m::Module)
62
63 Get the fully-qualified name of a module as a tuple of symbols. For example,
64
65 # Examples
66 ```jldoctest
67 julia> fullname(Base.Iterators)
68 (:Base, :Iterators)
69
70 julia> fullname(Main)
71 (:Main,)
72 ```
73 """
74 function fullname(m::Module)
75 mn = nameof(m)
76 if m === Main || m === Base || m === Core
77 return (mn,)
78 end
79 mp = parentmodule(m)
80 if mp === m
81 return (mn,)
82 end
83 return (fullname(mp)..., mn)
84 end
85
86 """
87 names(x::Module; all::Bool = false, imported::Bool = false)
88
89 Get an array of the names exported by a `Module`, excluding deprecated names.
90 If `all` is true, then the list also includes non-exported names defined in the module,
91 deprecated names, and compiler-generated names.
92 If `imported` is true, then names explicitly imported from other modules
93 are also included.
94
95 As a special case, all names defined in `Main` are considered \"exported\",
96 since it is not idiomatic to explicitly export names from `Main`.
97 """
98 names(m::Module; all::Bool = false, imported::Bool = false) =
99 sort!(ccall(:jl_module_names, Array{Symbol,1}, (Any, Cint, Cint), m, all, imported))
100
101 isexported(m::Module, s::Symbol) = ccall(:jl_module_exports_p, Cint, (Any, Any), m, s) != 0
102 isdeprecated(m::Module, s::Symbol) = ccall(:jl_is_binding_deprecated, Cint, (Any, Any), m, s) != 0
103 isbindingresolved(m::Module, var::Symbol) = ccall(:jl_binding_resolved_p, Cint, (Any, Any), m, var) != 0
104
105 function binding_module(m::Module, s::Symbol)
106 p = ccall(:jl_get_module_of_binding, Ptr{Cvoid}, (Any, Any), m, s)
107 p == C_NULL && return m
108 return unsafe_pointer_to_objref(p)::Module
109 end
110
111 function resolve(g::GlobalRef; force::Bool=false)
112 if force || isbindingresolved(g.mod, g.name)
113 return GlobalRef(binding_module(g.mod, g.name), g.name)
114 end
115 return g
116 end
117
118 const NamedTuple_typename = NamedTuple.body.body.name
119
120 function _fieldnames(@nospecialize t)
121 if t.name === NamedTuple_typename
122 if t.parameters[1] isa Tuple
123 return t.parameters[1]
124 else
125 throw(ArgumentError("type does not have definite field names"))
126 end
127 end
128 isdefined(t, :names) ? t.names : t.name.names
129 end
130
131 """
132 fieldname(x::DataType, i::Integer)
133
134 Get the name of field `i` of a `DataType`.
135
136 # Examples
137 ```jldoctest
138 julia> fieldname(Rational, 1)
139 :num
140
141 julia> fieldname(Rational, 2)
142 :den
143 ```
144 """
145 function fieldname(t::DataType, i::Integer)
146 if t.abstract
147 throw(ArgumentError("type does not have definite field names"))
148 end
149 names = _fieldnames(t)
150 n_fields = length(names)
151 field_label = n_fields == 1 ? "field" : "fields"
152 i > n_fields && throw(ArgumentError("Cannot access field $i since type $t only has $n_fields $field_label."))
153 i < 1 && throw(ArgumentError("Field numbers must be positive integers. $i is invalid."))
154 return names[i]::Symbol
155 end
156
157 fieldname(t::UnionAll, i::Integer) = fieldname(unwrap_unionall(t), i)
158 fieldname(t::Type{<:Tuple}, i::Integer) =
159 i < 1 || i > fieldcount(t) ? throw(BoundsError(t, i)) : Int(i)
160
161 """
162 fieldnames(x::DataType)
163
164 Get a tuple with the names of the fields of a `DataType`.
165
166 # Examples
167 ```jldoctest
168 julia> fieldnames(Rational)
169 (:num, :den)
170 ```
171 """
172 fieldnames(t::DataType) = (fieldcount(t); # error check to make sure type is specific enough
173 (_fieldnames(t)...,))
174 fieldnames(t::UnionAll) = fieldnames(unwrap_unionall(t))
175 fieldnames(::Core.TypeofBottom) =
176 throw(ArgumentError("The empty type does not have field names since it does not have instances."))
177 fieldnames(t::Type{<:Tuple}) = ntuple(identity, fieldcount(t))
178
179 """
180 nameof(t::DataType) -> Symbol
181
182 Get the name of a (potentially `UnionAll`-wrapped) `DataType` (without its parent module)
183 as a symbol.
184
185 # Examples
186 ```jldoctest
187 julia> module Foo
188 struct S{T}
189 end
190 end
191 Foo
192
193 julia> nameof(Foo.S{T} where T)
194 :S
195 ```
196 """
197 nameof(t::DataType) = t.name.name
198 nameof(t::UnionAll) = nameof(unwrap_unionall(t))
199
200 """
201 parentmodule(t::DataType) -> Module
202
203 Determine the module containing the definition of a (potentially `UnionAll`-wrapped) `DataType`.
204
205 # Examples
206 ```jldoctest
207 julia> module Foo
208 struct Int end
209 end
210 Foo
211
212 julia> parentmodule(Int)
213 Core
214
215 julia> parentmodule(Foo.Int)
216 Foo
217 ```
218 """
219 parentmodule(t::DataType) = t.name.module
220 parentmodule(t::UnionAll) = parentmodule(unwrap_unionall(t))
221
222 """
223 isconst(m::Module, s::Symbol) -> Bool
224
225 Determine whether a global is declared `const` in a given `Module`.
226 """
227 isconst(m::Module, s::Symbol) =
228 ccall(:jl_is_const, Cint, (Any, Any), m, s) != 0
229
230 """
231 @isdefined s -> Bool
232
233 Tests whether variable `s` is defined in the current scope.
234
235 # Examples
236 ```jldoctest
237 julia> function f()
238 println(@isdefined x)
239 x = 3
240 println(@isdefined x)
241 end
242 f (generic function with 1 method)
243
244 julia> f()
245 false
246 true
247 ```
248 """
249 macro isdefined(s::Symbol)
250 return Expr(:isdefined, esc(s))
251 end
252
253 """
254 objectid(x)
255
256 Get a hash value for `x` based on object identity. `objectid(x)==objectid(y)` if `x === y`.
257 """
258 objectid(@nospecialize(x)) = ccall(:jl_object_id, UInt, (Any,), x)
259
260 # concrete datatype predicates
261
262 struct DataTypeLayout
263 nfields::UInt32
264 alignment::UInt32
265 # alignment : 28;
266 # haspadding : 1;
267 # pointerfree : 1;
268 # fielddesc_type : 2;
269 end
270
271 """
272 Base.datatype_alignment(dt::DataType) -> Int
273
274 Memory allocation minimum alignment for instances of this type.
275 Can be called on any `isconcretetype`.
276 """
277 function datatype_alignment(dt::DataType)
278 @_pure_meta
279 dt.layout == C_NULL && throw(UndefRefError())
280 alignment = unsafe_load(convert(Ptr{DataTypeLayout}, dt.layout)).alignment
281 return Int(alignment & 0x1FF)
282 end
283
284 """
285 Base.datatype_haspadding(dt::DataType) -> Bool
286
287 Return whether the fields of instances of this type are packed in memory,
288 with no intervening padding bytes.
289 Can be called on any `isconcretetype`.
290 """
291 function datatype_haspadding(dt::DataType)
292 @_pure_meta
293 dt.layout == C_NULL && throw(UndefRefError())
294 alignment = unsafe_load(convert(Ptr{DataTypeLayout}, dt.layout)).alignment
295 return (alignment >> 9) & 1 == 1
296 end
297
298 """
299 Base.datatype_pointerfree(dt::DataType) -> Bool
300
301 Return whether instances of this type can contain references to gc-managed memory.
302 Can be called on any `isconcretetype`.
303 """
304 function datatype_pointerfree(dt::DataType)
305 @_pure_meta
306 dt.layout == C_NULL && throw(UndefRefError())
307 alignment = unsafe_load(convert(Ptr{DataTypeLayout}, dt.layout)).alignment
308 return (alignment >> 10) & 0xFFFFF == 0
309 end
310
311 """
312 Base.datatype_fielddesc_type(dt::DataType) -> Int
313
314 Return the size in bytes of each field-description entry in the layout array,
315 located at `(dt.layout + sizeof(DataTypeLayout))`.
316 Can be called on any `isconcretetype`.
317
318 See also [`Base.fieldoffset`](@ref).
319 """
320 function datatype_fielddesc_type(dt::DataType)
321 @_pure_meta
322 dt.layout == C_NULL && throw(UndefRefError())
323 alignment = unsafe_load(convert(Ptr{DataTypeLayout}, dt.layout)).alignment
324 return (alignment >> 30) & 3
325 end
326
327 """
328 isimmutable(v) -> Bool
329
330 Return `true` iff value `v` is immutable. See [Mutable Composite Types](@ref)
331 for a discussion of immutability. Note that this function works on values, so if you give it
332 a type, it will tell you that a value of `DataType` is mutable.
333
334 # Examples
335 ```jldoctest
336 julia> isimmutable(1)
337 true
338
339 julia> isimmutable([1,2])
340 false
341 ```
342 """
343 isimmutable(@nospecialize(x)) = (@_pure_meta; !typeof(x).mutable)
344
345 """
346 Base.isstructtype(T) -> Bool
347
348 Determine whether type `T` was declared as a struct type
349 (i.e. using the `struct` or `mutable struct` keyword).
350 """
351 function isstructtype(@nospecialize(t::Type))
352 @_pure_meta
353 t = unwrap_unionall(t)
354 # TODO: what to do for `Union`?
355 isa(t, DataType) || return false
356 return length(t.types) != 0 || (t.size == 0 && !t.abstract)
357 end
358
359 """
360 Base.isprimitivetype(T) -> Bool
361
362 Determine whether type `T` was declared as a primitive type
363 (i.e. using the `primitive` keyword).
364 """
365 function isprimitivetype(@nospecialize(t::Type))
366 @_pure_meta
367 t = unwrap_unionall(t)
368 # TODO: what to do for `Union`?
369 isa(t, DataType) || return false
370 return length(t.types) == 0 && t.size != 0 && !t.abstract
371 end
372
373 """
374 isbitstype(T)
375
376 Return `true` if type `T` is a "plain data" type,
377 meaning it is immutable and contains no references to other values,
378 only `primitive` types and other `isbitstype` types.
379 Typical examples are numeric types such as [`UInt8`](@ref),
380 [`Float64`](@ref), and [`Complex{Float64}`](@ref).
381 This category of types is significant since they are valid as type parameters,
382 may not track [`isdefined`](@ref) / [`isassigned`](@ref) status,
383 and have a defined layout that is compatible with C.
384
385 # Examples
386 ```jldoctest
387 julia> isbitstype(Complex{Float64})
388 true
389
390 julia> isbitstype(Complex)
391 false
392 ```
393 """
394 isbitstype(@nospecialize(t::Type)) = (@_pure_meta; isa(t, DataType) && t.isbitstype)
395
396 """
397 isbits(x)
398
399 Return `true` if `x` is an instance of an `isbitstype` type.
400 """
401 isbits(@nospecialize x) = (@_pure_meta; typeof(x).isbitstype)
402
403 """
404 isdispatchtuple(T)
405
406 Determine whether type `T` is a tuple "leaf type",
407 meaning it could appear as a type signature in dispatch
408 and has no subtypes (or supertypes) which could appear in a call.
409 """
410 isdispatchtuple(@nospecialize(t)) = (@_pure_meta; isa(t, DataType) && t.isdispatchtuple)
411
412 iskindtype(@nospecialize t) = (t === DataType || t === UnionAll || t === Union || t === typeof(Bottom))
413 isconcretedispatch(@nospecialize t) = isconcretetype(t) && !iskindtype(t)
414 has_free_typevars(@nospecialize(t)) = ccall(:jl_has_free_typevars, Cint, (Any,), t) != 0
415
416 # equivalent to isa(v, Type) && isdispatchtuple(Tuple{v}) || v === Union{}
417 # and is thus perhaps most similar to the old (pre-1.0) `isleaftype` query
418 const _TYPE_NAME = Type.body.name
419 function isdispatchelem(@nospecialize v)
420 return (v === Bottom) || (v === typeof(Bottom)) || isconcretedispatch(v) ||
421 (isa(v, DataType) && v.name === _TYPE_NAME && !has_free_typevars(v)) # isType(v)
422 end
423
424 """
425 isconcretetype(T)
426
427 Determine whether type `T` is a concrete type, meaning it could have direct instances
428 (values `x` such that `typeof(x) === T`).
429
430 # Examples
431 ```jldoctest
432 julia> isconcretetype(Complex)
433 false
434
435 julia> isconcretetype(Complex{Float32})
436 true
437
438 julia> isconcretetype(Vector{Complex})
439 true
440
441 julia> isconcretetype(Vector{Complex{Float32}})
442 true
443
444 julia> isconcretetype(Union{})
445 false
446
447 julia> isconcretetype(Union{Int,String})
448 false
449 ```
450 """
451 isconcretetype(@nospecialize(t)) = (@_pure_meta; isa(t, DataType) && t.isconcretetype)
452
453 """
454 Base.isabstracttype(T)
455
456 Determine whether type `T` was declared as an abstract type
457 (i.e. using the `abstract` keyword).
458
459 # Examples
460 ```jldoctest
461 julia> Base.isabstracttype(AbstractArray)
462 true
463
464 julia> Base.isabstracttype(Vector)
465 false
466 ```
467 """
468 function isabstracttype(@nospecialize(t))
469 @_pure_meta
470 t = unwrap_unionall(t)
471 # TODO: what to do for `Union`?
472 return isa(t, DataType) && t.abstract
473 end
474
475 """
476 Base.parameter_upper_bound(t::UnionAll, idx)
477
478 Determine the upper bound of a type parameter in the underlying datatype.
479 This method should generally not be relied upon:
480 code instead should usually use static parameters in dispatch to extract these values.
481
482 # Examples
483 ```jldoctest
484 julia> struct Foo{T<:AbstractFloat, N}
485 x::Tuple{T, N}
486 end
487
488 julia> Base.parameter_upper_bound(Foo, 1)
489 AbstractFloat
490
491 julia> Base.parameter_upper_bound(Foo, 2)
492 Any
493 ```
494 """
495 function parameter_upper_bound(t::UnionAll, idx)
496 @_pure_meta
497 return rewrap_unionall((unwrap_unionall(t)::DataType).parameters[idx], t)
498 end
499
500 """
501 typeintersect(T, S)
502
503 Compute a type that contains the intersection of `T` and `S`. Usually this will be the
504 smallest such type or one close to it.
505 """
506 typeintersect(@nospecialize(a),@nospecialize(b)) = (@_pure_meta; ccall(:jl_type_intersection, Any, (Any,Any), a, b))
507
508 """
509 fieldoffset(type, i)
510
511 The byte offset of field `i` of a type relative to the data start. For example, we could
512 use it in the following manner to summarize information about a struct:
513
514 ```jldoctest
515 julia> structinfo(T) = [(fieldoffset(T,i), fieldname(T,i), fieldtype(T,i)) for i = 1:fieldcount(T)];
516
517 julia> structinfo(Base.Filesystem.StatStruct)
518 12-element Array{Tuple{UInt64,Symbol,DataType},1}:
519 (0x0000000000000000, :device, UInt64)
520 (0x0000000000000008, :inode, UInt64)
521 (0x0000000000000010, :mode, UInt64)
522 (0x0000000000000018, :nlink, Int64)
523 (0x0000000000000020, :uid, UInt64)
524 (0x0000000000000028, :gid, UInt64)
525 (0x0000000000000030, :rdev, UInt64)
526 (0x0000000000000038, :size, Int64)
527 (0x0000000000000040, :blksize, Int64)
528 (0x0000000000000048, :blocks, Int64)
529 (0x0000000000000050, :mtime, Float64)
530 (0x0000000000000058, :ctime, Float64)
531 ```
532 """
533 fieldoffset(x::DataType, idx::Integer) = (@_pure_meta; ccall(:jl_get_field_offset, Csize_t, (Any, Cint), x, idx))
534
535 """
536 fieldtype(T, name::Symbol | index::Int)
537
538 Determine the declared type of a field (specified by name or index) in a composite DataType `T`.
539
540 # Examples
541 ```jldoctest
542 julia> struct Foo
543 x::Int64
544 y::String
545 end
546
547 julia> fieldtype(Foo, :x)
548 Int64
549
550 julia> fieldtype(Foo, 2)
551 String
552 ```
553 """
554 fieldtype
555
556 """
557 fieldindex(T, name::Symbol, err:Bool=true)
558
559 Get the index of a named field, throwing an error if the field does not exist (when err==true)
560 or returning 0 (when err==false).
561
562 # Examples
563 ```jldoctest
564 julia> struct Foo
565 x::Int64
566 y::String
567 end
568
569 julia> Base.fieldindex(Foo, :z)
570 ERROR: type Foo has no field z
571 Stacktrace:
572 [...]
573
574 julia> Base.fieldindex(Foo, :z, false)
575 0
576 ```
577 """
578 function fieldindex(T::DataType, name::Symbol, err::Bool=true)
579 return Int(ccall(:jl_field_index, Cint, (Any, Any, Cint), T, name, err)+1)
580 end
581
582 argument_datatype(@nospecialize t) = ccall(:jl_argument_datatype, Any, (Any,), t)
583 function argument_mt(@nospecialize t)
584 dt = argument_datatype(t)
585 (dt === nothing || !isdefined(dt.name, :mt)) && return nothing
586 dt.name.mt
587 end
588
589 """
590 fieldcount(t::Type)
591
592 Get the number of fields that an instance of the given type would have.
593 An error is thrown if the type is too abstract to determine this.
594 """
595 function fieldcount(@nospecialize t)
596 if t isa UnionAll || t isa Union
597 t = argument_datatype(t)
598 if t === nothing
599 throw(ArgumentError("type does not have a definite number of fields"))
600 end
601 t = t::DataType
602 elseif t == Union{}
603 throw(ArgumentError("The empty type does not have a well-defined number of fields since it does not have instances."))
604 end
605 if !(t isa DataType)
606 throw(TypeError(:fieldcount, "", Type, t))
607 end
608 if t.name === NamedTuple_typename
609 names, types = t.parameters
610 if names isa Tuple
611 return length(names)
612 end
613 if types isa DataType && types <: Tuple
614 return fieldcount(types)
615 end
616 abstr = true
617 else
618 abstr = t.abstract || (t.name === Tuple.name && isvatuple(t))
619 end
620 if abstr
621 throw(ArgumentError("type does not have a definite number of fields"))
622 end
623 return length(t.types)
624 end
625
626 # return all instances, for types that can be enumerated
627
628 """
629 instances(T::Type)
630
631 Return a collection of all instances of the given type, if applicable. Mostly used for
632 enumerated types (see `@enum`).
633
634 # Example
635 ```jldoctest
636 julia> @enum Color red blue green
637
638 julia> instances(Color)
639 (red::Color = 0, blue::Color = 1, green::Color = 2)
640 ```
641 """
642 function instances end
643
644 function to_tuple_type(@nospecialize(t))
645 @_pure_meta
646 if isa(t,Tuple) || isa(t,AbstractArray) || isa(t,SimpleVector)
647 t = Tuple{t...}
648 end
649 if isa(t,Type) && t<:Tuple
650 for p in unwrap_unionall(t).parameters
651 if !(isa(p,Type) || isa(p,TypeVar))
652 error("argument tuple type must contain only types")
653 end
654 end
655 else
656 error("expected tuple type")
657 end
658 t
659 end
660
661 function signature_type(@nospecialize(f), @nospecialize(args))
662 f_type = isa(f, Type) ? Type{f} : typeof(f)
663 if isa(args, Type)
664 u = unwrap_unionall(args)
665 return rewrap_unionall(Tuple{f_type, u.parameters...}, args)
666 else
667 return Tuple{f_type, args...}
668 end
669 end
670
671 """
672 code_lowered(f, types; generated = true)
673
674 Return an array of the lowered forms (IR) for the methods matching the given generic function
675 and type signature.
676
677 If `generated` is `false`, the returned `CodeInfo` instances will correspond to fallback
678 implementations. An error is thrown if no fallback implementation exists.
679 If `generated` is `true`, these `CodeInfo` instances will correspond to the method bodies
680 yielded by expanding the generators.
681
682 Note that an error will be thrown if `types` are not leaf types when `generated` is
683 `true` and the corresponding method is a `@generated` method.
684 """
685 function code_lowered(@nospecialize(f), @nospecialize(t = Tuple); generated::Bool = true)
686 return map(method_instances(f, t)) do m
687 if generated && isgenerated(m)
688 if isa(m, Core.MethodInstance)
689 return Core.Compiler.get_staged(m)
690 else # isa(m, Method)
691 error("Could not expand generator for `@generated` method ", m, ". ",
692 "This can happen if the provided argument types (", t, ") are ",
693 "not leaf types, but the `generated` argument is `true`.")
694 end
695 end
696 return uncompressed_ast(m)
697 end
698 end
699
700 isgenerated(m::Method) = isdefined(m, :generator)
701 isgenerated(m::Core.MethodInstance) = isgenerated(m.def)
702
703 # low-level method lookup functions used by the compiler
704
705 unionlen(x::Union) = unionlen(x.a) + unionlen(x.b)
706 unionlen(@nospecialize(x)) = 1
707
708 _uniontypes(x::Union, ts) = (_uniontypes(x.a,ts); _uniontypes(x.b,ts); ts)
709 _uniontypes(@nospecialize(x), ts) = (push!(ts, x); ts)
710 uniontypes(@nospecialize(x)) = _uniontypes(x, Any[])
711
712 function _methods(@nospecialize(f), @nospecialize(t), lim::Int, world::UInt)
713 tt = signature_type(f, t)
714 return _methods_by_ftype(tt, lim, world)
715 end
716
717 function _methods_by_ftype(@nospecialize(t), lim::Int, world::UInt)
718 return _methods_by_ftype(t, lim, world, UInt[typemin(UInt)], UInt[typemax(UInt)])
719 end
720 function _methods_by_ftype(@nospecialize(t), lim::Int, world::UInt, min::Array{UInt,1}, max::Array{UInt,1})
721 1 (2.70%) 1 (2.70%)
1 (2.70%) samples spent in _methods_by_ftype
1 (100.00%) (ex.), 1 (100.00%) (incl.) when called from abstract_call_gf_by_type line 49
return ccall(:jl_matching_methods, Any, (Any, Cint, Cint, UInt, Ptr{UInt}, Ptr{UInt}), t, lim, 0, world, min, max)
722 end
723
724 # high-level, more convenient method lookup functions
725
726 # type for reflecting and pretty-printing a subset of methods
727 mutable struct MethodList
728 ms::Array{Method,1}
729 mt::Core.MethodTable
730 end
731
732 length(m::MethodList) = length(m.ms)
733 isempty(m::MethodList) = isempty(m.ms)
734 iterate(m::MethodList, s...) = iterate(m.ms, s...)
735 eltype(::Type{MethodList}) = Method
736
737 function MethodList(mt::Core.MethodTable)
738 ms = Method[]
739 visit(mt) do m
740 push!(ms, m)
741 end
742 return MethodList(ms, mt)
743 end
744
745 """
746 methods(f, [types])
747
748 Returns the method table for `f`.
749
750 If `types` is specified, returns an array of methods whose types match.
751 """
752 function methods(@nospecialize(f), @nospecialize(t))
753 if isa(f, Core.Builtin)
754 throw(ArgumentError("argument is not a generic function"))
755 end
756 t = to_tuple_type(t)
757 world = typemax(UInt)
758 return MethodList(Method[m[3] for m in _methods(f, t, -1, world)], typeof(f).name.mt)
759 end
760
761 methods(f::Core.Builtin) = MethodList(Method[], typeof(f).name.mt)
762
763 function methods_including_ambiguous(@nospecialize(f), @nospecialize(t))
764 tt = signature_type(f, t)
765 world = typemax(UInt)
766 min = UInt[typemin(UInt)]
767 max = UInt[typemax(UInt)]
768 ms = ccall(:jl_matching_methods, Any, (Any, Cint, Cint, UInt, Ptr{UInt}, Ptr{UInt}), tt, -1, 1, world, min, max)::Array{Any,1}
769 return MethodList(Method[m[3] for m in ms], typeof(f).name.mt)
770 end
771 function methods(@nospecialize(f))
772 # return all matches
773 return methods(f, Tuple{Vararg{Any}})
774 end
775
776 function visit(f, mt::Core.MethodTable)
777 mt.defs !== nothing && visit(f, mt.defs)
778 nothing
779 end
780 function visit(f, mc::Core.TypeMapLevel)
781 if mc.targ !== nothing
782 e = mc.targ::Vector{Any}
783 for i in 1:length(e)
784 isassigned(e, i) && visit(f, e[i])
785 end
786 end
787 if mc.arg1 !== nothing
788 e = mc.arg1::Vector{Any}
789 for i in 1:length(e)
790 isassigned(e, i) && visit(f, e[i])
791 end
792 end
793 mc.list !== nothing && visit(f, mc.list)
794 mc.any !== nothing && visit(f, mc.any)
795 nothing
796 end
797 function visit(f, d::Core.TypeMapEntry)
798 while d !== nothing
799 f(d.func)
800 d = d.next
801 end
802 nothing
803 end
804
805 function length(mt::Core.MethodTable)
806 n = 0
807 visit(mt) do m
808 n += 1
809 end
810 return n::Int
811 end
812 isempty(mt::Core.MethodTable) = (mt.defs === nothing)
813
814 uncompressed_ast(m::Method) = isdefined(m,:source) ? uncompressed_ast(m, m.source) :
815 isdefined(m,:generator) ? error("Method is @generated; try `code_lowered` instead.") :
816 error("Code for this Method is not available.")
817 uncompressed_ast(m::Method, s::CodeInfo) = s
818 uncompressed_ast(m::Method, s::Array{UInt8,1}) = ccall(:jl_uncompress_ast, Any, (Any, Any), m, s)::CodeInfo
819 uncompressed_ast(m::Core.MethodInstance) = uncompressed_ast(m.def)
820
821 function method_instances(@nospecialize(f), @nospecialize(t), world::UInt = typemax(UInt))
822 tt = signature_type(f, t)
823 results = Vector{Union{Method,Core.MethodInstance}}()
824 for method_data in _methods_by_ftype(tt, -1, world)
825 mtypes, msp, m = method_data
826 instance = Core.Compiler.code_for_method(m, mtypes, msp, world, false)
827 push!(results, ifelse(isa(instance, Core.MethodInstance), instance, m))
828 end
829 return results
830 end
831
832 # this type mirrors jl_cgparams_t (documented in julia.h)
833 struct CodegenParams
834 cached::Cint
835
836 track_allocations::Cint
837 code_coverage::Cint
838 static_alloc::Cint
839 prefer_specsig::Cint
840
841 module_setup::Any
842 module_activation::Any
843 raise_exception::Any
844 emit_function::Any
845 emitted_function::Any
846
847 CodegenParams(;cached::Bool=true,
848 track_allocations::Bool=true, code_coverage::Bool=true,
849 static_alloc::Bool=true, prefer_specsig::Bool=false,
850 module_setup=nothing, module_activation=nothing, raise_exception=nothing,
851 emit_function=nothing, emitted_function=nothing) =
852 new(Cint(cached),
853 Cint(track_allocations), Cint(code_coverage),
854 Cint(static_alloc), Cint(prefer_specsig),
855 module_setup, module_activation, raise_exception,
856 emit_function, emitted_function)
857 end
858
859 # give a decent error message if we try to instantiate a staged function on non-leaf types
860 function func_for_method_checked(m::Method, @nospecialize types)
861 if isdefined(m, :generator) && !isdispatchtuple(types)
862 error("cannot call @generated function `", m, "` ",
863 "with abstract argument types: ", types)
864 end
865 return m
866 end
867
868 """
869 code_typed(f, types; optimize=true)
870
871 Returns an array of type-inferred lowered form (IR) for the methods matching the given
872 generic function and type signature. The keyword argument `optimize` controls whether
873 additional optimizations, such as inlining, are also applied.
874 """
875 function code_typed(@nospecialize(f), @nospecialize(types=Tuple); optimize=true)
876 ccall(:jl_is_in_pure_context, Bool, ()) && error("code reflection cannot be used from generated functions")
877 if isa(f, Core.Builtin)
878 throw(ArgumentError("argument is not a generic function"))
879 end
880 types = to_tuple_type(types)
881 asts = []
882 world = ccall(:jl_get_world_counter, UInt, ())
883 params = Core.Compiler.Params(world)
884 for x in _methods(f, types, -1, world)
885 meth = func_for_method_checked(x[3], types)
886 (code, ty) = Core.Compiler.typeinf_code(meth, x[1], x[2], optimize, params)
887 code === nothing && error("inference not successful") # inference disabled?
888 push!(asts, code => ty)
889 end
890 return asts
891 end
892
893 function return_types(@nospecialize(f), @nospecialize(types=Tuple))
894 ccall(:jl_is_in_pure_context, Bool, ()) && error("code reflection cannot be used from generated functions")
895 if isa(f, Core.Builtin)
896 throw(ArgumentError("argument is not a generic function"))
897 end
898 types = to_tuple_type(types)
899 rt = []
900 world = ccall(:jl_get_world_counter, UInt, ())
901 params = Core.Compiler.Params(world)
902 for x in _methods(f, types, -1, world)
903 meth = func_for_method_checked(x[3], types)
904 ty = Core.Compiler.typeinf_type(meth, x[1], x[2], params)
905 ty === nothing && error("inference not successful") # inference disabled?
906 push!(rt, ty)
907 end
908 return rt
909 end
910
911 """
912 which(f, types)
913
914 Returns the method of `f` (a `Method` object) that would be called for arguments of the given `types`.
915
916 If `types` is an abstract type, then the method that would be called by `invoke` is returned.
917 """
918 function which(@nospecialize(f), @nospecialize(t))
919 if isa(f, Core.Builtin)
920 throw(ArgumentError("argument is not a generic function"))
921 end
922 t = to_tuple_type(t)
923 tt = signature_type(f, t)
924 m = ccall(:jl_gf_invoke_lookup, Any, (Any, UInt), tt, typemax(UInt))
925 if m === nothing
926 error("no unique matching method found for the specified argument types")
927 end
928 return m.func::Method
929 end
930
931 """
932 which(module, symbol)
933
934 Return the module in which the binding for the variable referenced by `symbol` in `module` was created.
935 """
936 function which(m::Module, s::Symbol)
937 if !isdefined(m, s)
938 error("\"$s\" is not defined in module $m")
939 end
940 return binding_module(m, s)
941 end
942
943 # function reflection
944 """
945 nameof(f::Function) -> Symbol
946
947 Get the name of a generic `Function` as a symbol, or `:anonymous`.
948 """
949 nameof(f::Function) = typeof(f).name.mt.name
950
951 functionloc(m::Core.MethodInstance) = functionloc(m.def)
952
953 """
954 functionloc(m::Method)
955
956 Returns a tuple `(filename,line)` giving the location of a `Method` definition.
957 """
958 function functionloc(m::Method)
959 ln = m.line
960 if ln <= 0
961 error("could not determine location of method definition")
962 end
963 return (find_source_file(string(m.file)), ln)
964 end
965
966 """
967 functionloc(f::Function, types)
968
969 Returns a tuple `(filename,line)` giving the location of a generic `Function` definition.
970 """
971 functionloc(@nospecialize(f), @nospecialize(types)) = functionloc(which(f,types))
972
973 function functionloc(@nospecialize(f))
974 mt = methods(f)
975 if isempty(mt)
976 if isa(f, Function)
977 error("function has no definitions")
978 else
979 error("object is not callable")
980 end
981 end
982 if length(mt) > 1
983 error("function has multiple methods; please specify a type signature")
984 end
985 return functionloc(first(mt))
986 end
987
988 """
989 parentmodule(f::Function) -> Module
990
991 Determine the module containing the (first) definition of a generic
992 function.
993 """
994 parentmodule(f::Function) = parentmodule(typeof(f))
995
996 """
997 parentmodule(f::Function, types) -> Module
998
999 Determine the module containing a given definition of a generic function.
1000 """
1001 function parentmodule(@nospecialize(f), @nospecialize(types))
1002 m = methods(f, types)
1003 if isempty(m)
1004 error("no matching methods")
1005 end
1006 return first(m).module
1007 end
1008
1009 """
1010 hasmethod(f, Tuple type; world = typemax(UInt)) -> Bool
1011
1012 Determine whether the given generic function has a method matching the given
1013 `Tuple` of argument types with the upper bound of world age given by `world`.
1014
1015 See also [`applicable`](@ref).
1016
1017 # Examples
1018 ```jldoctest
1019 julia> hasmethod(length, Tuple{Array})
1020 true
1021 ```
1022 """
1023 function hasmethod(@nospecialize(f), @nospecialize(t); world = typemax(UInt))
1024 t = to_tuple_type(t)
1025 t = signature_type(f, t)
1026 return ccall(:jl_method_exists, Cint, (Any, Any, UInt), typeof(f).name.mt, t, world) != 0
1027 end
1028
1029 """
1030 isambiguous(m1, m2; ambiguous_bottom=false) -> Bool
1031
1032 Determine whether two methods `m1` and `m2` (typically of the same
1033 function) are ambiguous. This test is performed in the context of
1034 other methods of the same function; in isolation, `m1` and `m2` might
1035 be ambiguous, but if a third method resolving the ambiguity has been
1036 defined, this returns `false`.
1037
1038 For parametric types, the `ambiguous_bottom` keyword argument controls whether
1039 `Union{}` counts as an ambiguous intersection of type parameters – when `true`,
1040 it is considered ambiguous, when `false` it is not.
1041
1042 # Examples
1043 ```jldoctest
1044 julia> foo(x::Complex{<:Integer}) = 1
1045 foo (generic function with 1 method)
1046
1047 julia> foo(x::Complex{<:Rational}) = 2
1048 foo (generic function with 2 methods)
1049
1050 julia> m1, m2 = collect(methods(foo));
1051
1052 julia> typeintersect(m1.sig, m2.sig)
1053 Tuple{#foo,Complex{Union{}}}
1054
1055 julia> Base.isambiguous(m1, m2, ambiguous_bottom=true)
1056 true
1057
1058 julia> Base.isambiguous(m1, m2, ambiguous_bottom=false)
1059 false
1060 ```
1061 """
1062 function isambiguous(m1::Method, m2::Method; ambiguous_bottom::Bool=false)
1063 ti = typeintersect(m1.sig, m2.sig)
1064 ti === Bottom && return false
1065 if !ambiguous_bottom
1066 has_bottom_parameter(ti) && return false
1067 end
1068 ml = _methods_by_ftype(ti, -1, typemax(UInt))
1069 isempty(ml) && return true
1070 for m in ml
1071 if ti <: m[3].sig
1072 return false
1073 end
1074 end
1075 return true
1076 end
1077
1078 """
1079 delete_method(m::Method)
1080
1081 Make method `m` uncallable and force recompilation of any methods that use(d) it.
1082 """
1083 function delete_method(m::Method)
1084 ccall(:jl_method_table_disable, Cvoid, (Any, Any), get_methodtable(m), m)
1085 end
1086
1087 function get_methodtable(m::Method)
1088 ft = ccall(:jl_first_argument_datatype, Any, (Any,), m.sig)
1089 (ft::DataType).name.mt
1090 end
1091
1092 """
1093 has_bottom_parameter(t) -> Bool
1094
1095 Determine whether `t` is a Type for which one or more of its parameters is `Union{}`.
1096 """
1097 function has_bottom_parameter(t::Type)
1098 ret = false
1099 for p in t.parameters
1100 ret |= (p == Bottom) || has_bottom_parameter(p)
1101 end
1102 ret
1103 end
1104 has_bottom_parameter(t::UnionAll) = has_bottom_parameter(unwrap_unionall(t))
1105 has_bottom_parameter(t::Union) = has_bottom_parameter(t.a) & has_bottom_parameter(t.b)
1106 has_bottom_parameter(t::TypeVar) = t.ub == Bottom || has_bottom_parameter(t.ub)
1107 has_bottom_parameter(::Any) = false
1108
1109 min_world(m::Method) = reinterpret(UInt, m.min_world)
1110 max_world(m::Method) = reinterpret(UInt, m.max_world)
1111 min_world(m::Core.MethodInstance) = reinterpret(UInt, m.min_world)
1112 max_world(m::Core.MethodInstance) = reinterpret(UInt, m.max_world)
1113
1114 """
1115 propertynames(x, private=false)
1116
1117 Get a tuple or a vector of the properties (`x.property`) of an object `x`.
1118 This is typically the same as [`fieldnames(typeof(x))`](@ref), but types
1119 that overload [`getproperty`](@ref) should generally overload `propertynames`
1120 as well to get the properties of an instance of the type.
1121
1122 `propertynames(x)` may return only "public" property names that are part
1123 of the documented interface of `x`. If you want it to also return "private"
1124 fieldnames intended for internal use, pass `true` for the optional second argument.
1125 REPL tab completion on `x.` shows only the `private=false` properties.
1126 """
1127 propertynames(x) = fieldnames(typeof(x))
1128 propertynames(m::Module) = names(m)
1129 propertynames(x, private) = propertynames(x) # ignore private flag by default