-
-
Notifications
You must be signed in to change notification settings - Fork 97
Description
extend-protocol doesn't work on deftype-fn backed types
Problem
When a deftype is backed by a custom type via :deftype-fn (e.g. SciMap in babashka), extend-protocol on that type doesn't work.
The root cause is that type-impl returns :sci.impl.protocols/reified for ICustomType instances (rather than the specific type symbol like user.MyCache), so the defmethod registered by extend-protocol for the specific type never matches.
Reproduction
(defprotocol Extra (extra [this]))
(extend-protocol Extra
MyCustomType
(extra [this] :it-works))
(extra (->MyCustomType ...))
;; => No implementation of method: :extra of protocol: #'user/Extra found for: :sci.impl.protocols/reifiedAnalysis
In sci.impl.types/type-impl:
SciTypeInstanceis checked first → returns specific type symbol (e.g.user.Foo) — extend-protocol worksICustomTypeis checked second → returns:sci.impl.protocols/reified— extend-protocol doesn't match
For the standard SciType path, inline protocol impls are registered as defmethods keyed on the specific type symbol. extend-protocol also registers defmethods for that symbol, so both work.
For custom types (via :deftype-fn), inline protocol impls go through the :reified defmethod which delegates to ICustomType.getMethods(). But extend-protocol registers a defmethod for the specific type symbol, which never fires because type-impl returns :reified.
Possible fix
Make custom type instances also implement SciTypeInstance (or otherwise return a specific type symbol from type-impl), then register a per-type defmethod that delegates to getMethods(). This would let both inline impls and extend-protocol coexist.
This would also open the door to unifying the standard SciType path and the custom type path, since both would use methods-map + per-type defmethod delegation.