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?
After a brief discussion with Ambrose on IRC, the solution we've reached is to branch on
(string? addr)
as follows:and to replace the
IFn
annotation with: