[CLJ-1330] Class name clash between top-level functions and defn'ed ones Created: 22/Jan/14 Updated: 30/Jun/14
|Fix Version/s:||Release 1.7|
Named anonymous fn's are not guaranteed to have unique class names when AOT-compiled.
When AOT-compiled both functions will emit user$g.class, the latter overwriting the former.
Demonstration script: demo1.clj
Approach: Generate unique class names for named fn's the same way as for unnamed anonymous fn's.
See also: This patch also fixes the issue reported in
|Comment by Ambrose Bonnaire-Sergeant [ 22/Jan/14 11:12 AM ]|
This seems like the reason why jvm.tools.analyzer cannot analyze clojure.core. On analyzing a definline, there is an "attempted duplicate class definition" error.
This doesn't really matter, but I thought it may or may not be useful information to someone.
|Comment by Nicola Mometto [ 22/Jan/14 11:35 AM ]|
Attached a fix.
This also fixes AOT compiling of code like:
|Comment by Nicola Mometto [ 22/Jan/14 11:39 AM ]|
Cleaned up patch
|Comment by Alex Miller [ 22/Jan/14 12:43 PM ]|
It looks like the patch changes indentation of some of the code - can you fix that?
|Comment by Nicola Mometto [ 22/Jan/14 3:57 PM ]|
Updated patch without whitespace changes
|Comment by Alex Miller [ 22/Jan/14 4:15 PM ]|
Thanks, that's helpful.
|Comment by Alex Miller [ 24/Jan/14 10:03 AM ]|
There is consensus that this is a problem, however this is an area of the code with broad impacts as it deals with how classes are named. To that end, there is some work that needs to be done in understanding the impacts before we can consider it.
Some questions we would like to answer:
1) According to Rich, naming of (fn x ) function classes used to work in the manner of this patch - with generated names. Some code archaeology needs to be done on why that was changed and whether the change to the current behavior was addressing problems that we are likely to run into.
2) Are there issues with recursive functions? Are there impacts either in AOT or non-AOT use cases? Need some tests.
3) Are there issues with dynamic redefinition of functions? With the static naming scheme, redefinition causes a new class of the same name which can be picked up by reload of classes compiled to the old definition. With the dynamic naming scheme, redefinition will create a differently named class so old classes can never pick up a redefinition. Is this a problem? What are the impacts with and without AOT? Need some tests.
|Comment by Nicola Mometto [ 24/Jan/14 11:39 AM ]|
Looks like the current behaviour has been such since https://github.com/clojure/clojure/commit/4651e60808bb459355a3a5d0d649c4697c672e28
My guess is that Rich simply forgot to consider the (def y (fn x  ..)) case.
Regarding 2 and 3, the dynamic naming scheme is no different than what happens for anonymous functions so I don't see how this could cause any issue.
Recursion on the fn arg is simply a call to .invoke on "this", it's classname unaware.
I can add some tests to test thatand compile to different classnames but other than that I don't see what should be tested.
|Comment by Stuart Halloway [ 27/Jun/14 2:17 PM ]|
incomplete pending the answers to Alex Miller's questions in the comments
|Comment by Nicola Mometto [ 27/Jun/14 3:20 PM ]|
I believe I already answered his questions, I'll try to be a bit more explicit:
Regarding redefinitions or recursive functions, both of those operations never take in account the generated fn name so they are unaffected.