clj-commons / potemkin

some ideas which are almost good
572 stars 53 forks source link

import-vars and tools.namespace do not seem to be friends #33

Closed MichaelBlume closed 9 years ago

MichaelBlume commented 9 years ago

I have a namespace in my project that imports some names (including 'middlewares) from compojure.api.sweet. c.a.s uses import-vars to export a bunch of names defined elsewhere in compojure-api. If I screw something up in my namespace, such that it doesn't compile anymore, and then run clojure.tools.namespace.repl/refresh, the error I get isn't the reason my namespace doesn't compile, but something about how 'middlewares already refers to compojure.api.meta/middlewares. Worse, if I fix the compile problem in my namespace, repeated calls to refresh return the same "middlewares already refers" error, and as far as I can tell, the only way to make that go away is to manually call ns-unmap on everything that my namespace imported from someone using import-vars.

I realize this is a convoluted error-description -- I can upload a small demonstration project if that will help.

ztellman commented 9 years ago

A reproducing case would be great, thanks.

MichaelBlume commented 9 years ago

Hey, thanks for the quick response. I'm digging into this a little more and it looks like I've got more of a heisenbug than I initially realized -- I'm now having trouble reproducing it myself.

I'll see if it turns up again; in the meantime sorry for raising the alarm prematurely =)

ztellman commented 9 years ago

No worries. All of these tools are different kinds of hacks, I wouldn't be surprised if there are lurking issues. Let me know if you find anything else.

henryw374 commented 9 years ago

I came across this same issue I think you describe and I can reproduce it as follows.

say you have var

'foo/bar

and you use import vars like this

(ns importer)

(import-vars
[foo bar])

then, in another ns you have (ns consumer (:require [importer :refer :all]))

now in the result of (ns-refers 'consumer) you will see #'importer/bar but the :ns on the metadata of that var will be foo as expected. all ok so far.

now, with clojure.tools.namespace, when you have a compilation error, it calls clojure.tools.namespace.repl/recover-ns which walks over the ns-refers of your current ns and for each one calls (refer ns ...) , but the ns in question is found from the metadata, which is foo. the current ns already has bar from importer, and that is where it blows up.