Skip to content

Commit d6b03cb

Browse files
committed
Revert "diagnostic: Add method error diagnostic (#169)" (08de28f)
Temporarily revert this new feature for cutting a new release.
1 parent 7aabaf1 commit d6b03cb

File tree

8 files changed

+2
-233
lines changed

8 files changed

+2
-233
lines changed

.JETLSConfig.toml

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,6 @@ match_type = "regex"
1515
severity = "off"
1616
path = "LSP/src/LSP.jl"
1717

18-
# TODO [JETLS]
19-
# `@interface` type instability for anonymous interface definitions
20-
[[diagnostic.patterns]]
21-
pattern = "no matching method found `.*var\"AnonymousInterface.*`"
22-
match_by = "message"
23-
match_type = "regex"
24-
severity = "off"
25-
path = "LSP/src/**/*.jl"
26-
27-
# This is type instability within JSON3.jl
28-
[[diagnostic.patterns]]
29-
pattern = "no matching method found `convert(.+)`"
30-
match_by = "message"
31-
match_type = "regex"
32-
severity = "off"
33-
path = "src/testrunner/testrunner-types.jl"
34-
3518
# TODO [JuliaLowering]
3619
# Temporarily downgrade some known JuliaLowering issues to information level
3720
[[diagnostic.patterns]]

CHANGELOG.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
4747
4848
### Added
4949
50-
- Added [`inference/method-error`](https://aviatesk.github.io/JETLS.jl/release/diagnostic/#diagnostic/inference/method-error)
51-
diagnostic that detects function calls where no matching method exists for
52-
the inferred argument types. This catches potential `MethodError`s that would
53-
occur at runtime. For union-split calls, the diagnostic reports only the
54-
failing branches with their count (e.g., "1/2 union split").
55-
5650
- Anonymous function assignments (`f = (x) -> x + 1` and
5751
`clos = function (y) ... end`) are now analyzed as `Function` symbols
5852
for `textDocument/documentSymbol`, with their arguments as children.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ the list itself is subject to change.
6161
- [x] Undefined bindings
6262
- [x] Non-existent struct fields
6363
- [x] Out-of-bounds field access by index
64-
- [x] `MethodError`
64+
- [ ] Potential `MethodError`
6565
- [x] Configuration support
6666
- [x] [CLI interface](https://aviatesk.github.io/JETLS.jl/release/cli-check)
6767
- Completion

docs/src/diagnostic.md

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ Here is a summary table of the diagnostics explained in this section:
111111
| [`inference/undef-global-var`](@ref diagnostic/reference/inference/undef-global-var) | `Warning` | `JETLS/save` | References to undefined global variables |
112112
| [`inference/field-error`](@ref diagnostic/reference/inference/field-error) | `Warning` | `JETLS/save` | Access to non-existent struct fields |
113113
| [`inference/bounds-error`](@ref diagnostic/reference/inference/bounds-error) | `Warning` | `JETLS/save` | Out-of-bounds field access by index |
114-
| [`inference/method-error`](@ref diagnostic/inference/method-error) | `Warning` | No matching method found for function calls |
115114
| [`testrunner/test-failure`](@ref diagnostic/reference/testrunner/test-failure) | `Error` | `JETLS/extra` | Test failures from TestRunner integration |
116115

117116
### [Syntax diagnostic (`syntax/*`)](@id diagnostic/reference/syntax)
@@ -665,34 +664,6 @@ function bounds_error(tpl::Tuple{Int})
665664
end
666665
```
667666
668-
#### [Method error (`inference/method-error`)](@id diagnostic/inference/method-error)
669-
670-
**Default severity:** `Warning`
671-
672-
Function calls where no matching method can be found for the inferred argument
673-
types. This diagnostic detects potential `MethodError`s that would occur at
674-
runtime.
675-
676-
Examples:
677-
678-
```julia
679-
function method_error_example()
680-
return sin(1, 2) # no matching method found `sin(::Int64, ::Int64)` (JETLS inference/method-error)
681-
end
682-
```
683-
684-
When multiple union-split signatures fail to find matches, the diagnostic will
685-
report all failed signatures:
686-
687-
```julia
688-
only_int(x::Int) = 2x
689-
690-
function union_split_method_error(x::Union{Int,String})
691-
return only_int(x) # no matching method found `only_int(::String)` (1/2 union split)
692-
# (JETLS inference/method-error)
693-
end
694-
```
695-
696667
### [TestRunner diagnostic (`testrunner/*`)](@id diagnostic/reference/testrunner)
697668
698669
TestRunner diagnostics are reported when you manually run tests via code lens

src/analysis/Analyzer.jl

Lines changed: 1 addition & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module Analyzer
22

33
export LSAnalyzer, inference_error_report_severity, inference_error_report_stack, reset_report_target_modules!
4-
export BoundsErrorReport, FieldErrorReport, MethodErrorReport, UndefVarErrorReport
4+
export BoundsErrorReport, FieldErrorReport, UndefVarErrorReport
55

66
using Core.IR
77
using JET.JETInterface
@@ -244,47 +244,6 @@ end # @static if VERSION ≥ v"1.12.2"
244244
# Analysis injections
245245
# ===================
246246

247-
# function is_from_kwcall(analyzer, sv)
248-
# report_target_modules = @something analyzer.report_target_modules return false
249-
# checkbounds(Bool, sv.callstack, sv.parentid) || return false
250-
# sv = sv.callstack[sv.parentid]
251-
# checkbounds(Bool, sv.callstack, sv.parentid) || return false
252-
# sv = sv.callstack[sv.parentid]
253-
# mi = CC.frame_instance(sv)
254-
# def = mi.def
255-
# def isa Method || return false
256-
# sig = Base.unwrap_unionall(def.sig)
257-
# sig isa DataType || return false
258-
# length(sig.parameters) >= 1 || return false
259-
# sig.parameters[1] === typeof(Core.kwcall) || return false
260-
# checkbounds(Bool, sv.callstack, sv.parentid) || return false
261-
# sv = sv.callstack[sv.parentid]
262-
# return CC.frame_module(sv) ∈ report_target_modules
263-
# end
264-
265-
function CC.abstract_call_gf_by_type(
266-
analyzer::LSAnalyzer, @nospecialize(func), arginfo::CC.ArgInfo, si::CC.StmtInfo,
267-
@nospecialize(atype), sv::CC.InferenceState, max_methods::Int
268-
)
269-
ret = @invoke CC.abstract_call_gf_by_type(analyzer::ToplevelAbstractAnalyzer,
270-
func::Any, arginfo::CC.ArgInfo, si::CC.StmtInfo, atype::Any, sv::CC.InferenceState, max_methods::Int)
271-
if !should_analyze(analyzer, sv)
272-
return ret
273-
end
274-
atype′ = Ref{Any}(atype)
275-
function after_abstract_call_gf_by_type(analyzer′::LSAnalyzer, sv′::CC.InferenceState)
276-
ret′ = ret[]
277-
report_method_error!(analyzer′, sv′, ret′, arginfo, atype′[])
278-
return true
279-
end
280-
if isready(ret)
281-
after_abstract_call_gf_by_type(analyzer, sv)
282-
else
283-
push!(sv.tasks, after_abstract_call_gf_by_type)
284-
end
285-
return ret
286-
end
287-
288247
# TODO Better to factor out and share it with `JET.JETAnalyzer`
289248
function CC.abstract_eval_globalref(
290249
analyzer::LSAnalyzer, g::GlobalRef, saw_latestworld::Bool, sv::CC.InferenceState;
@@ -520,84 +479,6 @@ function report_fieldaccess!(
520479
return true
521480
end
522481

523-
# MethodErrorReport
524-
# -----------------
525-
526-
@jetreport struct MethodErrorReport <: LSErrorReport
527-
@nospecialize t # ::Union{Type, Vector{Type}}
528-
union_split::Int
529-
end
530-
function JETInterface.print_report_message(io::IO, report::MethodErrorReport)
531-
print(io, "no matching method found ")
532-
if report.union_split == 0
533-
print_callsig(io, report.t)
534-
else
535-
ts = report.t::Vector{Any}
536-
nts = length(ts)
537-
for i = 1:nts
538-
print_callsig(io, ts[i])
539-
i == nts || print(io, ", ")
540-
end
541-
print(io, " (", nts, '/', report.union_split, " union split)")
542-
end
543-
end
544-
function print_callsig(io, @nospecialize(t))
545-
print(io, '`')
546-
Base.show_tuple_as_call(io, Symbol(""), t)
547-
print(io, '`')
548-
end
549-
inference_error_report_stack_impl(r::MethodErrorReport) = length(r.vst):-1:1
550-
inference_error_report_severity_impl(::MethodErrorReport) = DiagnosticSeverity.Warning
551-
552-
function report_method_error!(
553-
analyzer::LSAnalyzer, sv::CC.InferenceState, call::CC.CallMeta,
554-
arginfo::CC.ArgInfo, @nospecialize(atype)
555-
)
556-
info = call.info
557-
if isa(info, CC.ConstCallInfo)
558-
info = info.call
559-
end
560-
if isa(info, CC.MethodMatchInfo)
561-
report_method_error!(analyzer, sv, info, atype)
562-
elseif isa(info, CC.UnionSplitInfo)
563-
report_method_error_for_union_split!(analyzer, sv, info, arginfo)
564-
end
565-
end
566-
567-
function report_method_error!(
568-
analyzer::LSAnalyzer, sv::CC.InferenceState, info::CC.MethodMatchInfo,
569-
@nospecialize(atype)
570-
)
571-
if CC.isempty(info.results)
572-
report = MethodErrorReport(sv, atype, 0)
573-
add_new_report!(analyzer, sv.result, report)
574-
end
575-
end
576-
577-
function report_method_error_for_union_split!(
578-
analyzer::LSAnalyzer, sv::CC.InferenceState, info::CC.UnionSplitInfo,
579-
arginfo::CC.ArgInfo
580-
)
581-
# check each match for union-split signature
582-
split_argtypes = empty_matches = nothing
583-
for (i, matchinfo) in enumerate(info.split)
584-
if CC.isempty(matchinfo.results)
585-
if isnothing(split_argtypes)
586-
split_argtypes = CC.switchtupleunion(CC.typeinf_lattice(analyzer), arginfo.argtypes)
587-
end
588-
argtypes′ = split_argtypes[i]::Vector{Any}
589-
if empty_matches === nothing
590-
empty_matches = (Any[], length(info.split))
591-
end
592-
sig_n = CC.argtypes_to_type(argtypes′)
593-
push!(empty_matches[1], sig_n)
594-
end
595-
end
596-
if empty_matches !== nothing
597-
add_new_report!(analyzer, sv.result, MethodErrorReport(sv, empty_matches...))
598-
end
599-
end
600-
601482
# Constructor
602483
# ===========
603484

src/diagnostic.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -419,8 +419,6 @@ function inference_error_report_code(@nospecialize report::JET.InferenceErrorRep
419419
return INFERENCE_FIELD_ERROR_CODE
420420
elseif report isa BoundsErrorReport
421421
return INFERENCE_BOUNDS_ERROR_CODE
422-
elseif report isa MethodErrorReport
423-
return INFERENCE_METHOD_ERROR_CODE
424422
end
425423
error(lazy"Diagnostic code is not defined for this report: $report")
426424
end

src/types.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,6 @@ const INFERENCE_UNDEF_GLOBAL_VAR_CODE = "inference/undef-global-var"
399399
const INFERENCE_UNDEF_STATIC_PARAM_CODE = "inference/undef-static-param" # currently not reported
400400
const INFERENCE_FIELD_ERROR_CODE = "inference/field-error"
401401
const INFERENCE_BOUNDS_ERROR_CODE = "inference/bounds-error"
402-
const INFERENCE_METHOD_ERROR_CODE = "inference/method-error"
403402
const TESTRUNNER_TEST_FAILURE_CODE = "testrunner/test-failure"
404403

405404
const ALL_DIAGNOSTIC_CODES = Set{String}(String[
@@ -420,7 +419,6 @@ const ALL_DIAGNOSTIC_CODES = Set{String}(String[
420419
INFERENCE_UNDEF_STATIC_PARAM_CODE,
421420
INFERENCE_FIELD_ERROR_CODE,
422421
INFERENCE_BOUNDS_ERROR_CODE,
423-
INFERENCE_METHOD_ERROR_CODE,
424422
TESTRUNNER_TEST_FAILURE_CODE,
425423
])
426424

test/analysis/test_Analyzer.jl

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -99,47 +99,6 @@ end
9999
end
100100
end
101101

102-
only_int(x::Int) = 2x
103-
104-
@testset "MethodErrorReport" begin
105-
# no report when method exists
106-
let result = analyze_call((Int,)) do x
107-
sin(x)
108-
end
109-
@test isempty(get_reports(result))
110-
end
111-
112-
# basic method error
113-
let result = analyze_call() do
114-
sin(1, 2)
115-
end
116-
reports = get_reports(result)
117-
@test length(reports) == 1
118-
r = only(reports)
119-
@test r isa MethodErrorReport && r.union_split == 0
120-
end
121-
122-
# union split case: only one branch fails
123-
let result = analyze_call((Union{Int,String},)) do x
124-
only_int(x)
125-
end
126-
reports = get_reports(result)
127-
@test length(reports) == 1
128-
r = only(reports)
129-
@test r isa MethodErrorReport && r.union_split == 2 && length(r.t) == 1
130-
end
131-
132-
# union split case: all branches fail
133-
let result = analyze_call((Union{String,Symbol},)) do x
134-
only_int(x)
135-
end
136-
reports = get_reports(result)
137-
@test length(reports) == 1
138-
r = only(reports)
139-
@test r isa MethodErrorReport && r.union_split == 2 && length(r.t) == 2
140-
end
141-
end
142-
143102
@testset "BoundsError analysis" begin
144103
# `getindex(::Tuple, ::Int)`
145104
let result = analyze_call((Tuple{Int},)) do tpl1
@@ -301,21 +260,6 @@ end
301260
end
302261
@test isempty(get_reports(result))
303262
end
304-
305-
# MethodErrorReport
306-
let result = analyze_call(; report_target_modules=(@__MODULE__,)) do
307-
sin(1, 2)
308-
end
309-
reports = get_reports(result)
310-
@test length(reports) == 1
311-
r = only(reports)
312-
@test r isa MethodErrorReport
313-
end
314-
let result = analyze_call(; report_target_modules=(ExternalModule,)) do
315-
sin(1, 2)
316-
end
317-
@test isempty(get_reports(result))
318-
end
319263
end
320264

321265
end # module test_LSAnalyzer

0 commit comments

Comments
 (0)