clj-kondo

2026-01-02T14:14:16.662839Z

Would clj-kondo be able to detect superfluous primitive type coercion calls? e.g. (double (f x)) where the f has a ^double return type

borkdude 2026-01-02T14:15:34.183689Z

I think it could

2026-01-02T14:17:33.161119Z

Would an issue for this be welcome?

borkdude 2026-01-02T14:19:54.052129Z

I'm looking at this now. When I print the types that are coming into double I'm getting this:

$ clj -M:clj-kondo/dev --lint - <<< '(defn foo ^double [] 1.0) (double (foo))'
:tags (#{:double :int :float})
linting took 38ms, errors: 0, warnings: 0
Not sure why int and float are in there... :)

borkdude 2026-01-02T14:20:42.500239Z

probably type inference adds more stuff than is reported by the return tag

borkdude 2026-01-02T14:20:46.685659Z

sure issue welcome

borkdude 2026-01-02T14:21:06.352449Z

I added this to lint-arg-types! just to give you an idea:

(when (and
             (= 'double (:name called-fn))
             (utils/one-of (:ns called-fn) [clojure.core cljs.core])
             )
        (prn :tags tags)
        (findings/reg-finding! ctx
                               (assoc (select-keys call [:row :end-row :col :end-col :filename])
                                      :type :equals-float
                                      :message "Equality comparison of floating point numbers")))

2026-01-02T14:58:02.093039Z

#{:double :float :int} is coming from tag-from-meta. It looks like the double, float, Double and Float cases should be tightened up. I’ll explore.

borkdude 2026-01-02T14:58:51.950389Z

nice

2026-01-02T15:36:08.670219Z

It looks like tightening tag-from-meta will work with additional is-a-relations and could-be-relations changes: https://github.com/hugoduncan/clj-kondo/commit/f881e08d924f2ab8cecdb4fbe72b1c9ece78ddf1

borkdude 2026-01-02T15:50:36.470929Z

awesome!

2026-01-02T15:58:06.607899Z

It doesn’t help that clojure type coercion functions don’t type hint their return values (this doesn’t cause problems when using the functions, because of the :inline meta, and because calling as a function object is going to return an object anyway).

borkdude 2026-01-02T15:59:33.370909Z

we can override this in types/clojure/core.clj

👍 1