But even if that's the case (and I'm not really sure it is), it seems like the my.foo/IFoo case ought to take the first path in resolve-var's cond, so it's probably unrelated.

There are no discernible problems at runtime, only when (auto-)building. I wonder whether this is limited to code reloading scenarios like the lein-cljsbuild auto-builder. Protocols in JVM clojure certainly have lots of code-reloading caveats around them.

I only dug into it a bit before needing to give up for now, but hopefully this helps.

But even if that's the case (and I'm not really sure it is), it seems like the my.foo/IFoo case ought to take the first path in resolve-var's cond, so it's probably unrelated.
There are no discernible problems at runtime, only when (auto-)building. I wonder whether this is limited to code reloading scenarios like the lein-cljsbuild auto-builder. Protocols in JVM clojure certainly have lots of code-reloading caveats around them.
I only dug into it a bit before needing to give up for now, but hopefully this helps.

In the example above, the warning will get printed when compiling foo.cljs and fubar.cljs for the second time, after fubar.cljs has changed since first compilation, but foo.cljs hasn't. It will only happen if compile-file is called on foo.cljs before fubar.cljs. Since foo.cljs doesn't require compilation, only its ns form will get analyzed, and basic namespace info put into cljs.analyzer/namespaces. When compile-file gets called on fubar.cljs later, the analyzer will see that fubar.cljs depends on foo.cljs, but will not go on to analyze it since 'foo.cljs will already be present in cljs.analyzer/namespaces.

I'm attaching a patch that tries to reverse the change that parse-ns makes to cljs.analyzer/namespaces. It is the simplest patch I could come up with, although it would probably be more appropriate to not use cljs.analyzer/analyze to parse the namespace form in parse-ns at all, but instead create a separate function (cljs.analyzer/analyze-file-ns ( ? )) whose only purpose would be to gather file's namespace info, without changing the analyzer's state.

Matjaz Gregoric
added a comment - 12/Jun/13 4:38 PM The reason for these warnings is that under some circumstances, some of the files that don't require compilation (as determined by cljs.compiler/requires-compilation?), don't get properly analyzed.
Normally when analyzing a file, the analyzer will also analyze all of the namespaces that the current file/namespace depends on (using cljs.analyzer/analyze-deps). The analyzer tries to avoid analyzing the same namespace twice by checking whether the namespace is already present in cljs.analyzer/namespaces, see: https://github.com/clojure/clojurescript/blob/f80956d90f455810be140cfec1632f55254385a5/src/clj/cljs/analyzer.clj#L615
When trying to compile a file that doesn't require compilation, cljs.compiler/compile-file delegates to cljs.compiler/parse-ns, which uses cljs.analyzer/analyze to parse the ns form. Once it reaches the ns form, it stops further analysis of the file. Analyzing the ns form has the side effect of populating cljs.analyzer/namespaces with the basic namespace info (https://github.com/clojure/clojurescript/blob/f80956d90f455810be140cfec1632f55254385a5/src/clj/cljs/analyzer.clj#L710-L721), preventing the analyzer from subsequently fully analyzing the file in case another file that gets compiled depends on it.
In the example above, the warning will get printed when compiling foo.cljs and fubar.cljs for the second time, after fubar.cljs has changed since first compilation, but foo.cljs hasn't. It will only happen if compile-file is called on foo.cljs before fubar.cljs. Since foo.cljs doesn't require compilation, only its ns form will get analyzed, and basic namespace info put into cljs.analyzer/namespaces. When compile-file gets called on fubar.cljs later, the analyzer will see that fubar.cljs depends on foo.cljs, but will not go on to analyze it since 'foo.cljs will already be present in cljs.analyzer/namespaces.
I'm attaching a patch that tries to reverse the change that parse-ns makes to cljs.analyzer/namespaces. It is the simplest patch I could come up with, although it would probably be more appropriate to not use cljs.analyzer/analyze to parse the namespace form in parse-ns at all, but instead create a separate function (cljs.analyzer/analyze-file-ns ( ? )) whose only purpose would be to gather file's namespace info, without changing the analyzer's state.

David Nolen
added a comment - 25/Aug/13 11:04 PM - edited I would prefer a patch that does as Matjaz suggests - don't call analyze and instead provide a separate function just for parsing namespace forms.

David Nolen
added a comment - 04/Sep/13 11:37 PM - edited While it's always annoying to add yet another dynamic var isn't this best solved by binding such a dynamic var such that analyze-ns doesn't emit any warnings or side effects namespaces?
Another option would be restore the previous namespaces value after ns analysis?

Can everyone experiencing this bug please try this branch - http://github.com/clojure/clojurescript/tree/509-protocol-warn. Fixing this bug also made me look at bit closer at the build process, lein cljsbuild auto builds when not using optimizations should be considerably faster (10X) as a result - we no longer analyze files that haven't changed.

David Nolen
added a comment - 07/Sep/13 8:51 PM - edited Can everyone experiencing this bug please try this branch - http://github.com/clojure/clojurescript/tree/509-protocol-warn. Fixing this bug also made me look at bit closer at the build process, lein cljsbuild auto builds when not using optimizations should be considerably faster (10X) as a result - we no longer analyze files that haven't changed.

I have not seen the protocol warning in a while, so I can't say anything to wether that is fixed or not.

I tried the branch for the optimization alone and while it works it is coupled to the behavior of lein-cljsbuild in that "incremental" builds only work when the increments happen in the same JVM instance. You can't build incrementally if you kill the build VM and restart it, at least my build tool couldn't.

lein-cljsbuild deletes the :output-to directory whenever it is launched therefore forcing a compile/analyze of everything, if that delete doesn't happen something is missing and the compilation fails cause cljs.core is not known. Not exactly sure whats missing but if :output-to is deleted whenever a new build VM is started everything works fine.

Thomas Heller
added a comment - 08/Sep/13 1:41 AM I have not seen the protocol warning in a while, so I can't say anything to wether that is fixed or not.
I tried the branch for the optimization alone and while it works it is coupled to the behavior of lein-cljsbuild in that "incremental" builds only work when the increments happen in the same JVM instance. You can't build incrementally if you kill the build VM and restart it, at least my build tool couldn't.
lein-cljsbuild deletes the :output-to directory whenever it is launched therefore forcing a compile/analyze of everything, if that delete doesn't happen something is missing and the compilation fails cause cljs.core is not known. Not exactly sure whats missing but if :output-to is deleted whenever a new build VM is started everything works fine.

The protocol warning problem is definitely real, w/o the fix you will get it with the minimal project that Jonas describes - unpleasant and surprising. As far as incremental builds - I'm not sure what we can about the different JVM "problem". Also I can't recreate your issue with lein cljsbuild.

David Nolen
added a comment - 08/Sep/13 1:50 AM - edited The protocol warning problem is definitely real, w/o the fix you will get it with the minimal project that Jonas describes - unpleasant and surprising. As far as incremental builds - I'm not sure what we can about the different JVM "problem". Also I can't recreate your issue with lein cljsbuild.

However, I don't see any improvements in "lein cljsbuild auto". My code still takes about 13 seconds to do an incremental compilation. I believe it used to be ~1 sec earlier with another auto build script I was using. Not sure if "lein cljsbuild" was ever faster than 13 seconds as I started using it only recently.

Praki Prakash
added a comment - 08/Sep/13 11:50 AM The protocol warnings have gone away with this branch.
However, I don't see any improvements in "lein cljsbuild auto". My code still takes about 13 seconds to do an incremental compilation. I believe it used to be ~1 sec earlier with another auto build script I was using. Not sure if "lein cljsbuild" was ever faster than 13 seconds as I started using it only recently.

The speed of lein cljsbuild auto is completely dependent on whether you're using Closure as part of the step. With :optimizations :none, a simple file with a few definitions now takes ~0.04s to recompile on my Macbook Air 1.7ghz after the first build.

David Nolen
added a comment - 08/Sep/13 12:00 PM - edited The speed of lein cljsbuild auto is completely dependent on whether you're using Closure as part of the step. With :optimizations :none, a simple file with a few definitions now takes ~0.04s to recompile on my Macbook Air 1.7ghz after the first build.