Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/JET.jl
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,7 @@ const JULIA_DIR = @static occursin("DEV", string(VERSION)) ?

# default UI (console)
include("ui/print.jl")
include("ui/reasons.jl")

# entries
# =======
Expand Down
2 changes: 1 addition & 1 deletion src/abstractinterpret/inferenceerrorreport.jl
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ _get_sig_type(::StateAtPC, @nospecialize(x)) = Any[repr(x; context = :compact =>
"""
InferenceErrorReport

An interface type of error reports that JET collects by abstract interpration.
An interface type of error reports that JET collects by abstract interpretation.
If `T` implements this interface, the following requirements should be satisfied:

---
Expand Down
39 changes: 39 additions & 0 deletions src/ui/reasons.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""
JET.reasons(results)

Construct a unique set of "reasons" for errors. Each reason is a unique file/line location, signature, and explanation.

`results` is most easily constructed from SnoopCompile's `report.(itrigs)`, where `itrigs` is a list of inference triggers.
See the SnoopCompile documentation for details.
"""
reasons(results::AbstractVector{<:JETCallResult}) = unique(reduce(vcat, filter(!isempty, reasons.(results)); init=Reason[]))
reasons(result::JETCallResult) = Reason.(get_reports(result))

struct Reason
report::InferenceErrorReport
end

# A limited form of comparison so as to aggregate equivalent errors that were
# arrived at by different callgraphs
function Base.:(==)(a::Reason, b::Reason)
a.report.msg == b.report.msg || return false
af, bf = a.report.vst[end], b.report.vst[end]
af.file == bf.file && af.line == bf.line || return false
a.report.sig == b.report.sig
end

const reason_seed = Int === Int64 ? 0xfbdf9de4cc04c870 : 0x5e6fcd4e
function Base.hash(r::Reason, h::UInt)
h = hash(reason_seed, h)
h = hash(r.report.msg, h)
f = r.report.vst[end]
h = hash(f.file, h)
h = hash(f.line)
h = hash(r.report.sig, h)
end

function Base.show(io::IO, r::Reason)
print_error_report(io, r.report)
f = r.report.vst[end]
print(io, f.file, ':', f.line)
end