• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37829

04 Jul 2024 08:47PM UTC coverage: 86.588% (+0.9%) from 85.714%
#37829

push

local

web-flow
Support `@opaque Tuple{T,U...}->RT (...)->...` syntax for explicit arg/return types (#54947)

This gives users a way to explicitly specify the return type of an
OpaqueClosure, and it also removes the old syntax `@opaque AT ...` in
preference of `@opaque AT->_ ...`

10 of 12 new or added lines in 2 files covered. (83.33%)

962 existing lines in 39 files now uncovered.

76341 of 88166 relevant lines covered (86.59%)

15255050.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

40.25
/stdlib/InteractiveUtils/src/InteractiveUtils.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
"""
4
The `InteractiveUtils` module provides utilities for interactive use of Julia,
5
such as code introspection and clipboard access.
6
It is intended for interactive work and is loaded automatically in interactive mode.
7
"""
8
module InteractiveUtils
9

10
Base.Experimental.@optlevel 1
11

12
export apropos, edit, less, code_warntype, code_llvm, code_native, methodswith, varinfo,
13
    versioninfo, subtypes, supertypes, @which, @edit, @less, @functionloc, @code_warntype,
14
    @code_typed, @code_lowered, @code_llvm, @code_native, @time_imports, clipboard
15

16
import Base.Docs.apropos
17

18
using Base: unwrap_unionall, rewrap_unionall, isdeprecated, Bottom, summarysize,
19
    signature_type, format_bytes
20
using Base.Libc
21
using Markdown
22

23
include("editless.jl")
24
include("codeview.jl")
25
include("macros.jl")
26
include("clipboard.jl")
27

28
"""
29
    varinfo(m::Module=Main, pattern::Regex=r""; all=false, imported=false, recursive=false, sortby::Symbol=:name, minsize::Int=0)
30

31
Return a markdown table giving information about public global variables in a module, optionally restricted
32
to those matching `pattern`.
33

34
The memory consumption estimate is an approximate lower bound on the size of the internal structure of the object.
35

36
- `all` : also list non-public objects defined in the module, deprecated objects, and compiler-generated objects.
37
- `imported` : also list objects explicitly imported from other modules.
38
- `recursive` : recursively include objects in sub-modules, observing the same settings in each.
39
- `sortby` : the column to sort results by. Options are `:name` (default), `:size`, and `:summary`.
40
- `minsize` : only includes objects with size at least `minsize` bytes. Defaults to `0`.
41

42
The output of `varinfo` is intended for display purposes only.  See also [`names`](@ref) to get an array of symbols defined in
43
a module, which is suitable for more general manipulations.
44
"""
UNCOV
45
function varinfo(m::Module=Base.active_module(), pattern::Regex=r""; all::Bool = false, imported::Bool = false, recursive::Bool = false, sortby::Symbol = :name, minsize::Int=0)
×
UNCOV
46
    sortby in (:name, :size, :summary) || throw(ArgumentError("Unrecognized `sortby` value `:$sortby`. Possible options are `:name`, `:size`, and `:summary`"))
×
UNCOV
47
    rows = Vector{Any}[]
×
UNCOV
48
    workqueue = [(m, ""),]
×
UNCOV
49
    while !isempty(workqueue)
×
UNCOV
50
        m2, prep = popfirst!(workqueue)
×
UNCOV
51
        for v in names(m2; all, imported)
×
UNCOV
52
            if !isdefined(m2, v) || !occursin(pattern, string(v))
×
UNCOV
53
                continue
×
54
            end
UNCOV
55
            value = getfield(m2, v)
×
UNCOV
56
            isbuiltin = value === Base || value === Base.active_module() || value === Core
×
UNCOV
57
            if recursive && !isbuiltin && isa(value, Module) && value !== m2 && nameof(value) === v && parentmodule(value) === m2
×
UNCOV
58
                push!(workqueue, (value, "$prep$v."))
×
59
            end
UNCOV
60
            ssize_str, ssize = if isbuiltin
×
61
                    ("", typemax(Int))
×
62
                else
UNCOV
63
                    ss = summarysize(value)
×
UNCOV
64
                    (format_bytes(ss), ss)
×
65
                end
UNCOV
66
            if ssize >= minsize
×
UNCOV
67
                push!(rows, Any[string(prep, v), ssize_str, summary(value), ssize])
×
68
            end
UNCOV
69
        end
×
UNCOV
70
    end
×
UNCOV
71
    let (col, rev) = if sortby === :name
×
UNCOV
72
            1, false
×
UNCOV
73
        elseif sortby === :size
×
UNCOV
74
            4, true
×
UNCOV
75
        elseif sortby === :summary
×
UNCOV
76
            3, false
×
77
        else
UNCOV
78
            @assert "unreachable"
×
79
        end
UNCOV
80
        sort!(rows; by=r->r[col], rev)
×
81
    end
UNCOV
82
    pushfirst!(rows, Any["name", "size", "summary"])
×
83

UNCOV
84
    return Markdown.MD(Any[Markdown.Table(map(r->r[1:3], rows), Symbol[:l, :r, :l])])
×
85
end
86
varinfo(pat::Regex; kwargs...) = varinfo(Base.active_module(), pat; kwargs...)
×
87

88
"""
89
    versioninfo(io::IO=stdout; verbose::Bool=false)
90

91
Print information about the version of Julia in use. The output is
92
controlled with boolean keyword arguments:
93

94
- `verbose`: print all additional information
95

96
!!! warning "Warning"
97
    The output of this function may contain sensitive information. Before sharing the output,
98
    please review the output and remove any data that should not be shared publicly.
99

100
See also: [`VERSION`](@ref).
101
"""
102
function versioninfo(io::IO=stdout; verbose::Bool=false)
7✔
103
    println(io, "Julia Version $VERSION")
3✔
104
    if !isempty(Base.GIT_VERSION_INFO.commit_short)
3✔
105
        println(io, "Commit $(Base.GIT_VERSION_INFO.commit_short) ($(Base.GIT_VERSION_INFO.date_string))")
3✔
106
    end
107
    official_release = Base.TAGGED_RELEASE_BANNER == "Official https://julialang.org release"
3✔
108
    if Base.isdebugbuild() || !isempty(Base.TAGGED_RELEASE_BANNER) || (Base.GIT_VERSION_INFO.tagged_commit && !official_release)
6✔
109
        println(io, "Build Info:")
×
110
        if Base.isdebugbuild()
×
111
            println(io, "  DEBUG build")
×
112
        end
113
        if !isempty(Base.TAGGED_RELEASE_BANNER)
×
114
            println(io, "  ", Base.TAGGED_RELEASE_BANNER)
×
115
        end
116
        if Base.GIT_VERSION_INFO.tagged_commit && !official_release
×
117
            println(io,
×
118
                """
119

120
                    Note: This is an unofficial build, please report bugs to the project
121
                    responsible for this build and not to the Julia project unless you can
122
                    reproduce the issue using official builds available at https://julialang.org/downloads
123
                """
124
            )
125
        end
126
    end
127
    println(io, "Platform Info:")
3✔
128
    println(io, "  OS: ", Sys.iswindows() ? "Windows" : Sys.isapple() ?
3✔
129
        "macOS" : Sys.KERNEL, " (", Sys.MACHINE, ")")
130

131
    if verbose
3✔
UNCOV
132
        lsb = ""
×
UNCOV
133
        if Sys.islinux()
×
UNCOV
134
            try lsb = readchomp(pipeline(`lsb_release -ds`, stderr=devnull)); catch; end
×
135
        end
UNCOV
136
        if Sys.iswindows()
×
137
            try lsb = strip(read(`$(ENV["COMSPEC"]) /c ver`, String)); catch; end
×
138
        end
UNCOV
139
        if !isempty(lsb)
×
140
            println(io, "      ", lsb)
×
141
        end
UNCOV
142
        if Sys.isunix()
×
UNCOV
143
            println(io, "  uname: ", readchomp(`uname -mprsv`))
×
144
        end
145
    end
146

147
    if verbose
3✔
UNCOV
148
        cpuio = IOBuffer() # print cpu_summary with correct alignment
×
UNCOV
149
        Sys.cpu_summary(cpuio)
×
UNCOV
150
        for (i, line) in enumerate(split(chomp(String(take!(cpuio))), "\n"))
×
UNCOV
151
            prefix = i == 1 ? "  CPU: " : "       "
×
UNCOV
152
            println(io, prefix, line)
×
UNCOV
153
        end
×
154
    else
155
        cpu = Sys.cpu_info()
3✔
156
        println(io, "  CPU: ", length(cpu), " × ", cpu[1].model)
3✔
157
    end
158

159
    if verbose
3✔
UNCOV
160
        println(io, "  Memory: $(Sys.total_memory()/2^30) GB ($(Sys.free_memory()/2^20) MB free)")
×
UNCOV
161
        try println(io, "  Uptime: $(Sys.uptime()) sec"); catch; end
×
UNCOV
162
        print(io, "  Load Avg: ")
×
UNCOV
163
        Base.print_matrix(io, Sys.loadavg()')
×
UNCOV
164
        println(io)
×
165
    end
166
    println(io, "  WORD_SIZE: ", Sys.WORD_SIZE)
3✔
167
    println(io, "  LLVM: libLLVM-",Base.libllvm_version," (", Sys.JIT, ", ", Sys.CPU_NAME, ")")
3✔
168
    println(io, """Threads: $(Threads.nthreads(:default)) default, $(Threads.nthreads(:interactive)) interactive, \
3✔
169
      $(Threads.ngcthreads()) GC (on $(Sys.CPU_THREADS) virtual cores)""")
170

171
    function is_nonverbose_env(k::String)
3✔
172
        return occursin(r"^JULIA_|^DYLD_|^LD_", k)
393✔
173
    end
174
    function is_verbose_env(k::String)
3✔
UNCOV
175
        return occursin(r"PATH|FLAG|^TERM$|HOME", k) && !is_nonverbose_env(k)
×
176
    end
177
    env_strs = String[
6✔
178
        String["  $(k) = $(v)" for (k,v) in ENV if is_nonverbose_env(uppercase(k))];
179
        (verbose ?
180
         String["  $(k) = $(v)" for (k,v) in ENV if is_verbose_env(uppercase(k))] :
181
         String[]);
182
    ]
183
    if !isempty(env_strs)
3✔
184
        println(io, "Environment:")
3✔
185
        for str in env_strs
3✔
186
            println(io, str)
14✔
187
        end
14✔
188
    end
189
end
190

191

UNCOV
192
function type_close_enough(@nospecialize(x), @nospecialize(t))
×
UNCOV
193
    x == t && return true
×
194
    # TODO: handle UnionAll properly
UNCOV
195
    return (isa(x, DataType) && isa(t, DataType) && x.name === t.name && x <: t) ||
×
196
           (isa(x, Union) && isa(t, DataType) && (type_close_enough(x.a, t) || type_close_enough(x.b, t)))
197
end
198

199
# `methodswith` -- shows a list of methods using the type given
200
"""
201
    methodswith(typ[, module or function]; supertypes::Bool=false])
202

203
Return an array of methods with an argument of type `typ`.
204

205
The optional second argument restricts the search to a particular module or function
206
(the default is all top-level modules).
207

208
If keyword `supertypes` is `true`, also return arguments with a parent type of `typ`,
209
excluding type `Any`.
210

211
See also: [`methods`](@ref).
212
"""
UNCOV
213
function methodswith(@nospecialize(t::Type), @nospecialize(f::Base.Callable), meths = Method[]; supertypes::Bool=false)
×
UNCOV
214
    for d in methods(f)
×
UNCOV
215
        if any(function (x)
×
UNCOV
216
                   let x = rewrap_unionall(x, d.sig)
×
UNCOV
217
                       (type_close_enough(x, t) ||
×
218
                        (supertypes ? (isa(x, Type) && t <: x && (!isa(x,TypeVar) || x.ub != Any)) :
219
                         (isa(x,TypeVar) && x.ub != Any && t == x.ub)) &&
220
                        x != Any)
221
                   end
222
               end,
223
               unwrap_unionall(d.sig).parameters)
UNCOV
224
            push!(meths, d)
×
225
        end
UNCOV
226
    end
×
UNCOV
227
    return meths
×
228
end
229

UNCOV
230
function _methodswith(@nospecialize(t::Type), m::Module, supertypes::Bool)
×
UNCOV
231
    meths = Method[]
×
UNCOV
232
    for nm in names(m)
×
UNCOV
233
        if isdefined(m, nm)
×
UNCOV
234
            f = getfield(m, nm)
×
UNCOV
235
            if isa(f, Base.Callable)
×
UNCOV
236
                methodswith(t, f, meths; supertypes = supertypes)
×
237
            end
238
        end
UNCOV
239
    end
×
UNCOV
240
    return unique(meths)
×
241
end
242

UNCOV
243
methodswith(@nospecialize(t::Type), m::Module; supertypes::Bool=false) = _methodswith(t, m, supertypes)
×
244

UNCOV
245
function methodswith(@nospecialize(t::Type); supertypes::Bool=false)
×
UNCOV
246
    meths = Method[]
×
UNCOV
247
    for mod in Base.loaded_modules_array()
×
UNCOV
248
        append!(meths, _methodswith(t, mod, supertypes))
×
UNCOV
249
    end
×
UNCOV
250
    return unique(meths)
×
251
end
252

253
# subtypes
254
function _subtypes_in!(mods::Array, x::Type)
19✔
255
    xt = unwrap_unionall(x)
19✔
256
    if !isabstracttype(x) || !isa(xt, DataType)
27✔
257
        # Fast path
258
        return Type[]
11✔
259
    end
260
    sts = Vector{Any}()
8✔
261
    while !isempty(mods)
1,060✔
262
        m = pop!(mods)
1,052✔
263
        xt = xt::DataType
1,052✔
264
        for s in names(m, all = true)
1,052✔
265
            if isdefined(m, s) && !isdeprecated(m, s)
192,447✔
266
                t = getfield(m, s)
192,415✔
267
                dt = isa(t, UnionAll) ? unwrap_unionall(t) : t
192,415✔
268
                if isa(dt, DataType)
192,415✔
269
                    if dt.name.name === s && dt.name.module == m && supertype(dt).name == xt.name
97,179✔
270
                        ti = typeintersect(t, x)
29✔
271
                        ti != Bottom && push!(sts, ti)
29✔
272
                    end
273
                elseif isa(t, Module) && nameof(t) === s && parentmodule(t) === m && t !== m
95,236✔
274
                    t === Base || push!(mods, t) # exclude Base, since it also parented by Main
861✔
275
                end
276
            end
277
        end
192,447✔
278
    end
1,052✔
279
    return permute!(sts, sortperm(map(string, sts)))
8✔
280
end
281

282
subtypes(m::Module, x::Type) = _subtypes_in!([m], x)
×
283

284
"""
285
    subtypes(T::DataType)
286

287
Return a list of immediate subtypes of DataType `T`. Note that all currently loaded subtypes
288
are included, including those not visible in the current module.
289

290
See also [`supertype`](@ref), [`supertypes`](@ref), [`methodswith`](@ref).
291

292
# Examples
293
```jldoctest
294
julia> subtypes(Integer)
295
3-element Vector{Any}:
296
 Bool
297
 Signed
298
 Unsigned
299
```
300
"""
301
subtypes(x::Type) = _subtypes_in!(Base.loaded_modules_array(), x)
19✔
302

303
"""
304
    supertypes(T::Type)
305

306
Return a tuple `(T, ..., Any)` of `T` and all its supertypes, as determined by
307
successive calls to the [`supertype`](@ref) function, listed in order of `<:`
308
and terminated by `Any`.
309

310
See also [`subtypes`](@ref).
311

312
# Examples
313
```jldoctest
314
julia> supertypes(Int)
315
(Int64, Signed, Integer, Real, Number, Any)
316
```
317
"""
UNCOV
318
function supertypes(T::Type)
×
UNCOV
319
    S = supertype(T)
×
320
    # note: we return a tuple here, not an Array as for subtypes, because in
321
    #       the future we could evaluate this function statically if desired.
UNCOV
322
    return S === T ? (T,) : (T, supertypes(S)...)
×
323
end
324

325
# TODO: @deprecate peakflops to LinearAlgebra
326
export peakflops
327
"""
328
    peakflops(n::Integer=4096; eltype::DataType=Float64, ntrials::Integer=3, parallel::Bool=false)
329

330
`peakflops` computes the peak flop rate of the computer by using double precision
331
[`gemm!`](@ref LinearAlgebra.BLAS.gemm!). For more information see
332
[`LinearAlgebra.peakflops`](@ref).
333

334
!!! compat "Julia 1.1"
335
    This function will be moved from `InteractiveUtils` to `LinearAlgebra` in the
336
    future. In Julia 1.1 and later it is available as `LinearAlgebra.peakflops`.
337
"""
338
function peakflops(n::Integer=4096; eltype::DataType=Float64, ntrials::Integer=3, parallel::Bool=false)
×
339
    # Base.depwarn("`peakflops` has moved to the LinearAlgebra module, " *
340
    #              "add `using LinearAlgebra` to your imports.", :peakflops)
341
    let LinearAlgebra = Base.require_stdlib(Base.PkgId(
×
342
            Base.UUID((0x37e2e46d_f89d_539d,0xb4ee_838fcccc9c8e)), "LinearAlgebra"))
343
        return LinearAlgebra.peakflops(n, eltype=eltype, ntrials=ntrials, parallel=parallel)
×
344
    end
345
end
346

347
function report_bug(kind)
1✔
348
    @info "Loading BugReporting package..."
1✔
349
    BugReportingId = Base.PkgId(
1✔
350
        Base.UUID((0xbcf9a6e7_4020_453c,0xb88e_690564246bb8)), "BugReporting")
351
    # Check if the BugReporting package exists in the current environment
352
    local BugReporting
353
    if Base.locate_package(BugReportingId) === nothing
1✔
354
        @info "Package `BugReporting` not found - attempting temporary installation"
1✔
355
        # Create a temporary environment and add BugReporting
356
        let Pkg = Base.require_stdlib(Base.PkgId(
1✔
357
            Base.UUID((0x44cfe95a_1eb2_52ea,0xb672_e2afdf69b78f)), "Pkg"))
358
            mktempdir() do tmp
1✔
359
                old_load_path = copy(LOAD_PATH)
1✔
360
                push!(empty!(LOAD_PATH), joinpath(tmp, "Project.toml"))
3✔
361
                old_active_project = Base.ACTIVE_PROJECT[]
1✔
362
                Base.ACTIVE_PROJECT[] = nothing
1✔
363
                pkgspec = @invokelatest Pkg.PackageSpec(BugReportingId.name, BugReportingId.uuid)
2✔
364
                @invokelatest Pkg.add(pkgspec)
1✔
365
                BugReporting = Base.require(BugReportingId)
1✔
366
                append!(empty!(LOAD_PATH), old_load_path)
2✔
367
                Base.ACTIVE_PROJECT[] = old_active_project
1✔
368
            end
369
        end
370
    else
371
        BugReporting = Base.require(BugReportingId)
×
372
    end
373
    return @invokelatest BugReporting.make_interactive_report(kind, ARGS)
1✔
374
end
375

376
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc