Static testing with JET vs interfaces

Hi there!
I’m starting to add JET testing to several packages, but I run into problems when I try to define abstract interfaces. As of right now, interfaces in Julia are mostly methodless functions with explicit documentation, so of course the static analysis errors when I make use of these functions downstream. More details here: JET errors on interface definitions (as it should) - what to do? · Issue #495 · aviatesk/JET.jl · GitHub
Does anyone have a suggestion?

1 Like

The question is, what do you want to test on the interface definition alone? The example you linked seems to report exactly what it should - there is no fallback implementation for bar(::AbstractFoo), which ought to be interpreted as “implement it yourself”.

The thing is, I’d like to use JET.test_package on some of my packages, where I define such an interface but no concrete implementation. It was more of a long shot / general question about design, cause I think the practical solution would be to add an ignore_function argument to JET or something

I think using JET for an interface package only makes sense when you have a concrete implementation & signature you want to check. You can’t check whether an interface without any callable signature matches with what you expect of it after all. If you want to check whether some concrete signature of a function was implemented, you could do it like this:

julia> abstract type Foo end

julia> struct NotImplementedError <: Exception
           f
       end

julia> func(::Foo) = throw(NotImplementedError(func))
func (generic function with 1 method)

julia> using JET

julia> JET.report_call(func, (Foo,))
═════ 1 possible error found ═════
┌ @ REPL[4]:1 func(::Foo)
│ may throw: throw(NotImplementedError(func)::NotImplementedError)
└─────────────

Of course, checking whether a concrete type implements that correctly is also possible:

julia> struct Bar <: Foo end

julia> JET.report_call(func, (Bar,))
═════ 1 possible error found ═════
┌ @ REPL[4]:1 func(::Bar)
│ may throw: throw(NotImplementedError(func)::NotImplementedError)
└─────────────

julia> func(::Bar) = "Bar!"
func (generic function with 2 methods)

julia> JET.report_call(func, (Bar,))
No errors detected

But for forward declarations in the style of function func end, there’s just no way to check whether a fallback works correctly, because there are simply no possible methods to call in the first place.

Do you have a concrete example I can take a look at?

1 Like

I think you’re right, test_package is not appropriate in this case and I need to look at calls individually. I thought it neat to be able to include JET tests in the CI, but I guess it takes more finesse.

1 Like

No particular example, but the issue popped up several times. Defining the signature with a NotImplementedError is a good option but it replaces one JET warning with another ^^