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

JuliaLang / julia / #37997

29 Jan 2025 02:08AM UTC coverage: 17.283% (-68.7%) from 85.981%
#37997

push

local

web-flow
bpart: Start enforcing min_world for global variable definitions (#57150)

This is the analog of #57102 for global variables. Unlike for consants,
there is no automatic global backdate mechanism. The reasoning for this
is that global variables can be declared at any time, unlike constants
which can only be decalared once their value is available. As a result
code patterns using `Core.eval` to declare globals are rarer and likely
incorrect.

1 of 22 new or added lines in 3 files covered. (4.55%)

31430 existing lines in 188 files now uncovered.

7903 of 45728 relevant lines covered (17.28%)

98663.7 hits per line

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

26.88
/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, @trace_compile, @trace_dispatch,
15
    @activate
16

17
import Base.Docs.apropos
18

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

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

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

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

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

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

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

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

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

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

95
- `verbose`: print all additional information
96

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

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

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

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

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

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

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

193

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

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

205
Return an array of methods with an argument of type `typ`.
206

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

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

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

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

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

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

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

284
subtypes(m::Module, x::Type) = _subtypes_in!([m], x)
×
285

286
"""
287
    subtypes(T::DataType)
288

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

292
See also [`supertype`](@ref), [`supertypes`](@ref), [`methodswith`](@ref).
293

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

305
"""
306
    supertypes(T::Type)
307

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

312
See also [`subtypes`](@ref).
313

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

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

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

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

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

378
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

© 2026 Coveralls, Inc