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

JuliaLang / julia / #37745

11 Apr 2024 03:54AM UTC coverage: 87.241% (+5.8%) from 81.402%
#37745

push

local

web-flow
Fix comparison base for line table compression (#54032)

I'm not entirely sure what the original intent of this statement was,
but the effect ends up being that some codeloc entries end up negative
in the compressed representation, but the code always assumes unsigned
integers, so things roundtripped badly, leading to badly corrupted stack
traces. I guess this might have been a rebase mistake,
since the same line exists (correctly) a few lines prior. Fixes #54031.

75950 of 87058 relevant lines covered (87.24%)

15852930.37 hits per line

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

89.94
/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
"""
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)
32✔
46
    sortby in (:name, :size, :summary) || throw(ArgumentError("Unrecognized `sortby` value `:$sortby`. Possible options are `:name`, `:size`, and `:summary`"))
11✔
47
    rows = Vector{Any}[]
11✔
48
    workqueue = [(m, ""),]
11✔
49
    while !isempty(workqueue)
23✔
50
        m2, prep = popfirst!(workqueue)
12✔
51
        for v in names(m2; all, imported)
12✔
52
            if !isdefined(m2, v) || !occursin(pattern, string(v))
136✔
53
                continue
9✔
54
            end
55
            value = getfield(m2, v)
59✔
56
            isbuiltin = value === Base || value === Base.active_module() || value === Core
118✔
57
            if recursive && !isbuiltin && isa(value, Module) && value !== m2 && nameof(value) === v && parentmodule(value) === m2
59✔
58
                push!(workqueue, (value, "$prep$v."))
1✔
59
            end
60
            ssize_str, ssize = if isbuiltin
59✔
61
                    ("", typemax(Int))
×
62
                else
63
                    ss = summarysize(value)
59✔
64
                    (format_bytes(ss), ss)
118✔
65
                end
66
            if ssize >= minsize
59✔
67
                push!(rows, Any[string(prep, v), ssize_str, summary(value), ssize])
55✔
68
            end
69
        end
68✔
70
    end
12✔
71
    let (col, rev) = if sortby === :name
11✔
72
            1, false
9✔
73
        elseif sortby === :size
2✔
74
            4, true
1✔
75
        elseif sortby === :summary
1✔
76
            3, false
1✔
77
        else
78
            @assert "unreachable"
13✔
79
        end
80
        sort!(rows; by=r->r[col], rev)
190✔
81
    end
82
    pushfirst!(rows, Any["name", "size", "summary"])
22✔
83

84
    return Markdown.MD(Any[Markdown.Table(map(r->r[1:3], rows), Symbol[:l, :r, :l])])
143✔
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)
15✔
103
    println(io, "Julia Version $VERSION")
6✔
104
    if !isempty(Base.GIT_VERSION_INFO.commit_short)
6✔
105
        println(io, "Commit $(Base.GIT_VERSION_INFO.commit_short) ($(Base.GIT_VERSION_INFO.date_string))")
6✔
106
    end
107
    official_release = Base.TAGGED_RELEASE_BANNER == "Official https://julialang.org release"
6✔
108
    if Base.isdebugbuild() || !isempty(Base.TAGGED_RELEASE_BANNER) || (Base.GIT_VERSION_INFO.tagged_commit && !official_release)
12✔
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:")
6✔
128
    println(io, "  OS: ", Sys.iswindows() ? "Windows" : Sys.isapple() ?
6✔
129
        "macOS" : Sys.KERNEL, " (", Sys.MACHINE, ")")
130

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

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

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

171
    function is_nonverbose_env(k::String)
6✔
172
        return occursin(r"^JULIA_|^DYLD_|^LD_", k)
547✔
173
    end
174
    function is_verbose_env(k::String)
6✔
175
        return occursin(r"PATH|FLAG|^TERM$|HOME", k) && !is_nonverbose_env(k)
244✔
176
    end
177
    env_strs = String[
12✔
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)
6✔
184
        println(io, "Environment:")
5✔
185
        for str in env_strs
5✔
186
            println(io, str)
39✔
187
        end
39✔
188
    end
189
end
190

191

192
function type_close_enough(@nospecialize(x), @nospecialize(t))
69,461✔
193
    x == t && return true
70,448✔
194
    # TODO: handle UnionAll properly
195
    return (isa(x, DataType) && isa(t, DataType) && x.name === t.name && x <: t) ||
70,090✔
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
"""
213
function methodswith(@nospecialize(t::Type), @nospecialize(f::Base.Callable), meths = Method[]; supertypes::Bool=false)
5,962✔
214
    for d in methods(f)
5,864✔
215
        if any(function (x)
85,624✔
216
                   let x = rewrap_unionall(x, d.sig)
73,939✔
217
                       (type_close_enough(x, t) ||
62,664✔
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)
224
            push!(meths, d)
358✔
225
        end
226
    end
43,037✔
227
    return meths
2,981✔
228
end
229

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

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

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

253
# subtypes
254
function _subtypes_in!(mods::Array, x::Type)
24✔
255
    xt = unwrap_unionall(x)
24✔
256
    if !isabstracttype(x) || !isa(xt, DataType)
36✔
257
        # Fast path
258
        return Type[]
12✔
259
    end
260
    sts = Vector{Any}()
12✔
261
    while !isempty(mods)
1,248✔
262
        m = pop!(mods)
1,236✔
263
        xt = xt::DataType
1,236✔
264
        for s in names(m, all = true)
1,236✔
265
            if isdefined(m, s) && !isdeprecated(m, s)
266,458✔
266
                t = getfield(m, s)
266,422✔
267
                dt = isa(t, UnionAll) ? unwrap_unionall(t) : t
266,422✔
268
                if isa(dt, DataType)
266,422✔
269
                    if dt.name.name === s && dt.name.module == m && supertype(dt).name == xt.name
133,248✔
270
                        ti = typeintersect(t, x)
33✔
271
                        ti != Bottom && push!(sts, ti)
33✔
272
                    end
273
                elseif isa(t, Module) && nameof(t) === s && parentmodule(t) === m && t !== m
133,174✔
274
                    t === Base || push!(mods, t) # exclude Base, since it also parented by Main
979✔
275
                end
276
            end
277
        end
266,458✔
278
    end
1,236✔
279
    return permute!(sts, sortperm(map(string, sts)))
12✔
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)
24✔
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
"""
318
function supertypes(T::Type)
10✔
319
    S = supertype(T)
16✔
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.
322
    return S === T ? (T,) : (T, supertypes(S)...)
10✔
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

© 2026 Coveralls, Inc