clj-kondo 2026-04-14

I'm implementing a "missing protocol method arity" linter, but it occurs to me that it may be totally fine to omit arities. E.g. when implementing IFn, you often don't have to implement all 20 or so arities. Thoughts?

config to turn it on/off based on a/ protocol b/ implementing type c/ regex, namespace, etc?

I actually have two parts: mismatch, i.e. implementing an arity that does not match the protocol and missing arity: protocol declares arity which isn't implemented. I could split these into two different linters and default the latter to off.

Tangentially related, but it might have helped with a situation like this I ran into earlier this year:

(defprotocol Bounded
  (beg [x])
  (end [x])
  (size [x]))

(defrecord Interval [lo hi]
  Bounded
  (beg [x] lo)
  (end [x] hi))

;   Syntax error (VerifyError) compiling new at (dev/repro.cljc:9:1).
;   Bad type on operand stack
;   Exception Details:
;     Location:
;       repro/Interval.size()Ljava/lang/Object; @6: areturn
;     Reason:
;       Type integer (current frame, stack[0]) is not assignable to reference type
;     Current Frame:
;       bci: @6
;       flags: { }
;       locals: { 'repro/Interval' }
;       stack: { integer }
;     Bytecode:
;       0000000: 2ab9 017d 0100 b0
After much confusion I eventually found out that it was due to a name conflict with java.util.Map/size injected by the defrecord constructor

oops ignore the above, I realise clj-kondo already emits a Missing protocol method(s): size (clj-kondo-clj) warning which I must have missed at the time - in any case the method had to be renamed

I don't know how old the missing protocol method is, but it's fairly new

The 2 part approach makes sense to me but I'd still vote for detailed config of the latter if it does not complicate things too much. Might also suggest adding method name to it too. Some protocols and implementing types might have been designed with holes in mind similarly to ifn you wrote

I'll first push it out with off by default and then wait for more feedback. I want to get out a clj-kondo release this week :)

👍 1

By all means. Just wanted to throw some ideas

people could also ignore it with #_{:clj-kondo/ignore [:missing-protocol-method-arity]}

I think the partial IFn implementation will be fairly common. I know at work we only ever implement just one or two arities for that, and we don't implement applyTo (or whatever it's called).

would it be possible to say "any protocol not in clojure.core raises a warning"?

would there be a reason not to write a protocol like IFn outside of core?

i'm sorry, i mean that the protocols in clojure.core wouldn't be checked for missing method arities, but usage of a protocol defined in idk noahtheduke.splint.foo would be checked for missing method arities

👍🏻 1

but i guess that could even be lowered to just IFn, as nearly everything else would want to be covered

my question is more like: why would core protocols be any different in nature than user written protocols

👍 1

I was trying to think of a solution for folks not implementing all 20 IFn arities lol

configurability with useful defaults 😉

👍 1

I think IFn is probably a common but pathological case: lots of arities, almost no one implements all of them. For all other protocols, yes, the linter would be useful. So, I agree with @nbtheduke 🙂

👍 1

I have a project when I want IFn to warn (SCI)

👍 1

to continue the bikeshed, i wonder if :missing-protocol-method-arity {:check-ifn false} would be a good default (similar to :exclude-destructured-as)

That's weirdly specific. If it's configurable beyond enable/disable globally/locally, I'd prefer that to be flexible to be applied to more protocols/types/namespaces/methods/arities etc.

👍 1

@ericdallo perhaps you can try it, so I can release tomorrow without clojure-lsp regressions

thanks, but I'm pretty busy this week to test :/

ok no problem, then we'll just see.