Clojure

Namespace metadata lost in AOT compile

Details

  • Type: Defect Defect
  • Status: In Progress In Progress
  • Priority: Major Major
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
  • Patch:
    Code
  • Approval:
    Triaged

Description

AOT-compilation drops namespace metadata.

This also affects all of the namespaces packaged with Clojure, except clojure.core, for which metadata is explicitly added in core.clj.

Cause of the bug:

  • a namespace inherits the metadata of the symbol used to create that namespace the first time
  • the namespace is created in the load() method, that is invoked after the __init() method
  • the __init0() method creates all the Vars of the namespace
  • interning a Var in a namespace that doesn't exist forces that namespace to be created

This means that the namespace will have been already created (with nil metadata) by the time the load() method gets invoked and thus the call to in-ns will be a no-op and the metadata will be lost.

Approach: The attached patch fixes this issue by explicitely attaching the metadata to the namespace after its creation (via ns) using a .resetMeta call

Activity

Stuart Halloway made changes -
Field Original Value New Value
Assignee Stuart Halloway [ stu ]
Stuart Sierra made changes -
Description For example, the namespace @clojure.contrib.def@ has metadata for doc and author.

We see this when we load the file directly from source:
<pre>
<code>
 tom@goya:~/src/clj$ java -cp clojure/clojure.jar:clojure-contrib/src clojure.lang.Repl
 Clojure 1.1.0-alpha-SNAPSHOT
 user=> (load "clojure/contrib/def")
 nil
 user=> (find-ns 'clojure.contrib.def)
 #<Namespace clojure.contrib.def>
 user=> ^(find-ns 'clojure.contrib.def)
 {:author "Stephen C. Gilardi", :doc "def.clj provides variants of def that make including doc strings and\nmaking private definitions more succinct."}
 user=>
</code>
</pre>

But if we load the file from the jar where it's been compiled, the metadata is lost:
<pre>
<code>
 tom@goya:~/src/clj$ java -cp clojure/clojure.jar:clojure-contrib/clojure-contrib.jar clojure.lang.Repl
 Clojure 1.1.0-alpha-SNAPSHOT
 user=> (use 'clojure.contrib.def)
 nil
 user=> (find-ns 'clojure.contrib.def)
 #<Namespace clojure.contrib.def>
 user=> ^(find-ns 'clojure.contrib.def)
 nil
 user=>
</code>
</pre>

Even if we use @load@, we don't see metadata on the item:
<pre>
<code>
 tom@goya:~/src/clj$ java -cp clojure/clojure.jar:clojure-contrib/clojure-contrib.jar clojure.lang.Repl
 Clojure 1.1.0-alpha-SNAPSHOT
 user=> (load "clojure/contrib/def")
 nil
 user=> (find-ns 'clojure.contrib.def)
 #<Namespace clojure.contrib.def>
 user=> ^(find-ns 'clojure.contrib.def)
 nil
 user=>
</code>
</pre>


The jar isn't the problem, for if we use the slim jar (without the AOT
class files), we see that the metadata is fine:
<pre>
<code>
 tom@goya:~/src/clj$ java -cp clojure/clojure.jar:clojure-contrib/clojure-contrib-slim.jar clojure.lang.Repl
 Clojure 1.1.0-alpha-SNAPSHOT
 user=> (use 'clojure.contrib.def)
 nil
 user=> (find-ns 'clojure.contrib.def)
 #<Namespace clojure.contrib.def>
 user=> ^(find-ns 'clojure.contrib.def)
 {:author "Stephen C. Gilardi", :doc "def.clj provides variants of def that make including doc strings and\nmaking private definitions more succinct."}
 user=>
</code>
</pre>

This seems to be true usually, but not always. For example the
metadata on the pretty print namespace is just fine from the AOT version:
<pre>
<code>
 tom@goya:~/src/clj$ java -cp clojure/clojure.jar:clojure-contrib/clojure-contrib.jar clojure.lang.Repl
 Clojure 1.1.0-alpha-SNAPSHOT
 user=> (use 'clojure.contrib.pprint)
 nil
 user=> (find-ns 'clojure.contrib.pprint)
 #<Namespace clojure.contrib.pprint>
 user=> ^(find-ns 'clojure.contrib.pprint)
 {:author "Tom Faulhaber", :doc "This module comprises two elements:\n1) A pretty printer for Clojure data structures, implemented in the function \"pprint\"\n2) A Common Lisp compatible format function, implemented as \"cl-format\" because\n Clojure is using the name \"format\" for its own format.\n\nComplete documentation is available on the wiki at the contrib google code site.", :see-also [["PrettyPrinting" "Documentation for the pretty printer"] ["CommonLispFormat" "Documentation for Common Lisp format function"]]}
 user=>
</code>
</pre>
AOT-compilation drops namespace metadata.

This also affects all of the namespaces packaged with Clojure, except {{clojure.core}}, for which metadata is [explicitly added|https://github.com/clojure/clojure/blob/229bf8fe9a751e4f48bb2b7ea57e27ebc43d26ae/src/clj/clojure/core.clj#L6158] in core.clj.

This behavior was originally reported against Clojure 1.1.0-alpha. Using the attached test script {{aot-drops-metadata-demo.sh}}, I can confirm it still exists for Clojure 1.3.0, 1.4.0, and 1.5.1.
Priority Blocker [ 1 ]
Reporter Stuart Sierra [ stuart.sierra ]
Attachment aot-drops-metadata-demo.sh [ 12069 ]
Stuart Sierra made changes -
Priority Blocker [ 1 ] Minor [ 4 ]
Alex Miller made changes -
Fix Version/s Backlog [ 10035 ]
Alex Miller made changes -
Labels aot
Nicola Mometto made changes -
Nicola Mometto made changes -
Patch Code [ 10001 ]
Labels aot aot metadata
Alex Miller made changes -
Approval Triaged [ 10120 ]
Alex Miller made changes -
Priority Minor [ 4 ] Major [ 3 ]
Nicola Mometto made changes -
Description AOT-compilation drops namespace metadata.

This also affects all of the namespaces packaged with Clojure, except {{clojure.core}}, for which metadata is [explicitly added|https://github.com/clojure/clojure/blob/229bf8fe9a751e4f48bb2b7ea57e27ebc43d26ae/src/clj/clojure/core.clj#L6158] in core.clj.

This behavior was originally reported against Clojure 1.1.0-alpha. Using the attached test script {{aot-drops-metadata-demo.sh}}, I can confirm it still exists for Clojure 1.3.0, 1.4.0, and 1.5.1.
AOT-compilation drops namespace metadata.

This also affects all of the namespaces packaged with Clojure, except {{clojure.core}}, for which metadata is [explicitly added|https://github.com/clojure/clojure/blob/229bf8fe9a751e4f48bb2b7ea57e27ebc43d26ae/src/clj/clojure/core.clj#L6158] in core.clj.

*Cause of the bug:*
Here's an explaination of why this bug happens:
- a namespace inherits the metadata of the symbol used to create that namespace the first time
- the namespace is created in the load() method, that is invoked *after* the __init() method
- the __init0() method creates all the Vars of the namespace
- interning a Var in a namespace that doesn't exist forces that namespace to be created

This means that the namespace will have been already created (with nil metadata) by the time the load() method gets invoked and thus the call to in-ns will be a no-op and the metadata will be lost.

*Approach:* The attached patch fixes this issue by explicitely attaching the metadata to the namespace after its creation (via ns) using a .resetMeta call
Nicola Mometto made changes -
Description AOT-compilation drops namespace metadata.

This also affects all of the namespaces packaged with Clojure, except {{clojure.core}}, for which metadata is [explicitly added|https://github.com/clojure/clojure/blob/229bf8fe9a751e4f48bb2b7ea57e27ebc43d26ae/src/clj/clojure/core.clj#L6158] in core.clj.

*Cause of the bug:*
Here's an explaination of why this bug happens:
- a namespace inherits the metadata of the symbol used to create that namespace the first time
- the namespace is created in the load() method, that is invoked *after* the __init() method
- the __init0() method creates all the Vars of the namespace
- interning a Var in a namespace that doesn't exist forces that namespace to be created

This means that the namespace will have been already created (with nil metadata) by the time the load() method gets invoked and thus the call to in-ns will be a no-op and the metadata will be lost.

*Approach:* The attached patch fixes this issue by explicitely attaching the metadata to the namespace after its creation (via ns) using a .resetMeta call
AOT-compilation drops namespace metadata.

This also affects all of the namespaces packaged with Clojure, except {{clojure.core}}, for which metadata is [explicitly added|https://github.com/clojure/clojure/blob/229bf8fe9a751e4f48bb2b7ea57e27ebc43d26ae/src/clj/clojure/core.clj#L6158] in core.clj.

*Cause of the bug:*
- a namespace inherits the metadata of the symbol used to create that namespace the first time
- the namespace is created in the load() method, that is invoked *after* the __init() method
- the __init0() method creates all the Vars of the namespace
- interning a Var in a namespace that doesn't exist forces that namespace to be created

This means that the namespace will have been already created (with nil metadata) by the time the load() method gets invoked and thus the call to in-ns will be a no-op and the metadata will be lost.

*Approach:* The attached patch fixes this issue by explicitely attaching the metadata to the namespace after its creation (via ns) using a .resetMeta call

People

Vote (4)
Watch (5)

Dates

  • Created:
    Updated: