Open E-A-Griffin opened 1 year ago
with-spy
and with-stub
use with-redefs
in their implementation to temporarily swap out the root binding of the stubbed var with one that tracks calls, so that when that var is accessed the replacement function is read rather than the original function.
Inline metadata gives the compiler the option of replacing a call to the function with the expansion of the :inline
metadata instead.
Since the function call has been replaced with the inline body there is no var access so it doesn't matter what the root binding of the var currently is, the inlined code is what gets executed.
E.g. with this code
(ns inline.core)
;; definline is a macro convenience to generate a function
;; var with the same body and :inline metadata
(definline foo
[]
`(println "foo"))
(defn bar
[]
(println "bar")
(foo))
The body of bar
may get expanded by the compiler to the equivalent of:
(defn bar
[]
(println "bar")
(println "foo"))
And so it doesn't matter how foo
is stubbed or spied, it's not called.
That makes sense, I think I know a solution to this issue though if bond
would like to add support for functions with inlined arities defined based on the example here: https://clojuredocs.org/clojure.core/alter-var-root#example-5c266712e4b0ca44402ef601
I haven't developed a full proof of concept yet but I believe that a with-no-inline
macro could be written and used such that a var's inline definition is dissoc
ed from its metadata at the beginning of the macro call and then re-assoc
ed back at the end of the macro call.
As far as I can tell, calling
with-spy
(andwith-stub!
) seem to not work as expected on functions that have an inline definition (i.e. a function with:inline
defined in the metadata).