Welcome! Please see the About page for a little more info on how this works.

+1 vote
in Compiler by

As shown in the following example, the protocol method, pfoo doesn't appear to be directly linked.

$ clj -J-Dclojure.compiler.direct-linking=true
Clojure 1.10.1
user=> (defprotocol Foo (pfoo [this]))
user=> (defn libfn [x] (pfoo x))
user=> (extend-protocol Foo String (pfoo [_] :dude))
user=> (libfn "hello")
user=> (alter-var-root #'user/pfoo (fn [old] (fn [this] (prn :this) (old this))))
#object[user$eval178$fn__179$fn__180 0x18eec010 "user$eval178$fn__179$fn__180@18eec010"]
user=> (libfn "hello")

The reason I ask is because I'm trying to find a generic way to patch protocol methods to work within sci + graal native-image. The constraints are:

  • works under direct-linking (important for native-image use)
  • use with 3rd party libraries
    • avoid source code changes to target protocols (can't add ^:dynamic, ^:redef meta)

I have a solution that works here, but it relies on the fact that protocol vars can be altered using alter-var-root at compile time even under direct linking. Is that a safe assumption?

1 Answer

0 votes
selected by
Best answer

the way protocol functions are created currently they will not be compiled with a invokeStatic method (they close over some data), so the compiler will never compile them as a call to the invokeStatic static method (which is what direct linking does).

It seems very unlikely that this would change, but guarantee is a strong word.

Something to keep in mind is whenever a protocol definition is re-evaluated the vars that point to the functions are reset.