How do I properly annotate overloaded Java methods?

104 views Asked by At

In working to annotate clojang, I'm having some trouble with protocol methods that call overloaded Java methods. I've narrowed the problem down to the following minimal tricky case from 'clojang.jinterface.otp.nodes:

(ns clojang.jinterface.otp.nodes
  (:require [clojure.core.typed :as t :refer [ann ann-protocol]]
            [clojure.core.typed.utils :refer [defprotocol]])
  (:import [com.ericsson.otp.erlang OtpTransport]
           [java.net InetAddress])
  (:refer-clojure :exclude [defprotocol]))

(ann-protocol AbstractNodeObject
  create-transport
  (t/IFn [AbstractNodeObject InetAddress int -> (t/Nilable OtpTransport)]
         [AbstractNodeObject String int -> (t/Nilable OtpTransport)]))
(defprotocol AbstractNodeObject
  (create-transport [this addr port-num]
    "Create instance of ``OtpTransport``."))

(extend-type AbstractNode
  AbstractNodeObject
  (create-transport [this addr port-num]
    (.createTransport this addr port-num)))

Per the JInterface Javadocs, AbstractNode.createTransport can take a java.lang.String or a java.net.InetAddress as addr. While I believe I've annotated this correctly in the ann-protocol form, core.typed complains about the implementation (on the last line in the example). I suspect I can somehow fix this using t/inst, but have yet to sort out the exact incantation.

I know I could add the type hint, ^String or ^InetAddress to the arglist (on the second to last line of the example) and remove the other clause from the corresponding t/IFn form above, but how can I tell core.typed that either type is viable?

1

There are 1 answers

0
yurrriq On BEST ANSWER

After a brief discussion with Ambrose on IRC, the solution we've reached is to branch on (string? addr) as follows:

(create-transport [this addr port-num]
  (if (string? addr)
    (.createTransport this ^String addr port-num)
    (.createTransport this ^InetAddress addr port-num)))

and to replace the IFn annotation with:

[AbstractNodeObject (t/U String InetAddress) int -> (t/Nilable OtpTransport)]