I encountered a, to me, slightly surprising behaviour seemingly related to clojure records.

The setup is as follows:

  1. One namespace defines a record type:

    (ns defrecordissue.arecord)
    
    (defrecord ARecord [])
    
  2. Another namespace defines a protocol, and extends it to the record type defined in 1:

    (ns defrecordissue.aprotocol
      (:require [defrecordissue.arecord])
      (:import [defrecordissue.arecord ARecord]))
    
    (defprotocol AProtocol
      (afn [this]))
    
    (extend-protocol AProtocol
      ARecord
      (afn [this] 42))
    
  3. A third namespace constructs an instance of the record and invokes the protocol function on the record.

    (ns defrecordissue.aot1
      (:require [defrecordissue.aprotocol]
                [defrecordissue.arecord]))
    
    (defrecordissue.aprotocol/afn (defrecordissue.arecord/->ARecord))
    

When the defrecordissue.aot1 namespace is compiled, in my case using lein compile defrecordissue.aot1, compilation fails with the following exception:

Exception in thread "main" java.lang.IllegalArgumentException: No implementation of method: :afn of protocol: #'defrecordissue.aprotocol/AProtocol found for class: defrecordissue.arecord.ARecord, compiling:(aot1.clj:5:1)
    at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3463)
    at clojure.lang.Compiler.compile1(Compiler.java:7153)
    at clojure.lang.Compiler.compile(Compiler.java:7219)
    at clojure.lang.RT.compile(RT.java:398)
    at clojure.lang.RT.load(RT.java:438)
    at clojure.lang.RT.load(RT.java:411)
    at clojure.core$load$fn__5018.invoke(core.clj:5530)
    at clojure.core$load.doInvoke(core.clj:5529)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.core$load_one.invoke(core.clj:5336)
    at clojure.core$compile$fn__5023.invoke(core.clj:5541)
    at clojure.core$compile.invoke(core.clj:5540)
    at user$eval7.invoke(NO_SOURCE_FILE:1
Edit
Report