From 3e6f97879aae3147540be1c675c4f6ddf66e978c Mon Sep 17 00:00:00 2001 From: Noah Bogart Date: Fri, 15 Sep 2023 14:07:32 -0400 Subject: [PATCH] Resolve imported vars at runtime, not read time If a var has tag metadata attached to the var symbol (not on the vector, as is the preferred method for return types in functions), it will be resolved when `import-*` is called during read time. This currently doesn't break anything, but if the proposed Clojure patch for [CLJ-1929][CLJ-1929] is accepted, then code that's so tagged will break. Includes a test that will break without the associated change if the Clojure patch is accepted. Closes [#72][#72] [CLJ-1929]: https://clojure.atlassian.net/browse/CLJ-1929 [#72]: https://github.com/clj-commons/potemkin/issues/72 --- src/potemkin/namespaces.clj | 30 +++++++++++++++--------------- test/potemkin/imports_test.clj | 3 +++ test/potemkin/namespaces_test.clj | 3 +++ 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/potemkin/namespaces.clj b/src/potemkin/namespaces.clj index f135b4a..3a3f26f 100644 --- a/src/potemkin/namespaces.clj +++ b/src/potemkin/namespaces.clj @@ -26,11 +26,11 @@ (throw (IllegalArgumentException. (str "Calling import-fn on a macro: " sym)))) - `(do - (def ~(with-meta n {:protocol protocol}) (deref ~vr)) - (alter-meta! (var ~n) merge (dissoc (meta ~vr) :name)) - (link-vars ~vr (var ~n)) - ~vr)))) + `(let [vr# (resolve '~sym)] + (def ~(with-meta n {:protocol protocol}) (deref vr#)) + (alter-meta! (var ~n) merge (dissoc (meta vr#) :name)) + (link-vars vr# (var ~n)) + vr#)))) (defmacro import-macro "Given a macro in another namespace, defines a macro with the same @@ -48,12 +48,12 @@ (when-not (:macro m) (throw (IllegalArgumentException. (str "Calling import-macro on a non-macro: " sym)))) - `(do - (def ~n ~(resolve sym)) - (alter-meta! (var ~n) merge (dissoc (meta ~vr) :name)) + `(let [vr# (resolve '~sym)] + (def ~n (deref vr#)) + (alter-meta! (var ~n) merge (dissoc (meta vr#) :name)) (.setMacro (var ~n)) - (link-vars ~vr (var ~n)) - ~vr)))) + (link-vars vr# (var ~n)) + vr#)))) (defmacro import-def "Given a regular def'd var from another namespace, defined a new var with the @@ -68,11 +68,11 @@ nspace (:ns m)] (when-not vr (throw (IllegalArgumentException. (str "Don't recognize " sym)))) - `(do - (def ~n @~vr) - (alter-meta! (var ~n) merge (dissoc (meta ~vr) :name)) - (link-vars ~vr (var ~n)) - ~vr)))) + `(let [vr# (resolve '~sym)] + (def ~n (deref vr#)) + (alter-meta! (var ~n) merge (dissoc (meta vr#) :name)) + (link-vars vr# (var ~n)) + vr#)))) (defmacro import-vars "Imports a list of vars from other namespaces." diff --git a/test/potemkin/imports_test.clj b/test/potemkin/imports_test.clj index baf1c62..f703896 100644 --- a/test/potemkin/imports_test.clj +++ b/test/potemkin/imports_test.clj @@ -20,3 +20,6 @@ x) (def some-value 1) + +(defn ^clojure.lang.ExceptionInfo ex-info-2 [msg data] + (ex-info msg data)) diff --git a/test/potemkin/namespaces_test.clj b/test/potemkin/namespaces_test.clj index df59fc2..c850b65 100644 --- a/test/potemkin/namespaces_test.clj +++ b/test/potemkin/namespaces_test.clj @@ -50,3 +50,6 @@ (is false "`import-vars` should have thrown an exception") (catch Exception ex (is "`clojure.set/onion-misspelled` does not exist" (.getMessage ex))))) + +;; This is the whole test for CLJ-1929 +(import-vars [potemkin.imports-test ex-info-2])