Completed
Details
Assignee
UnassignedUnassignedReporter
Howard Lewis ShipHoward Lewis ShipApproval
OkPatch
Code and TestPriority
MinorAffects versions
Fix versions
Details
Details
Assignee
Unassigned
UnassignedReporter
Howard Lewis Ship
Howard Lewis ShipApproval
Ok
Patch
Code and Test
Priority
Affects versions
Fix versions
Created September 12, 2013 at 9:42 PM
Updated August 29, 2014 at 3:24 PM
Resolved August 29, 2014 at 3:24 PM
I was introducing a namespace that included a defrecord.
My defrecord was wrong; it used a keyword to define a field, not a symbol. Minimal test case:
% cat src/useclj16/init.clj (ns useclj16.init) (defrecord Application [:shutdown-fn])
% cat src/useclj16/app.clj (ns useclj16.app (:require [useclj16.init :as init]))
However, the exception was perplexing:
% java -cp clojure-1.6.0-master-SNAPSHOT.jar:src clojure.main user=> (require 'useclj16.app) ClassCastException clojure.lang.Keyword cannot be cast to clojure.lang.IObj clojure.core/with-meta (core.clj:214) user=> (pst *e 100) ClassCastException clojure.lang.Keyword cannot be cast to clojure.lang.IObj clojure.core/with-meta (core.clj:214) clojure.core/defrecord/fn--147 (core_deftype.clj:362) clojure.core/map/fn--4210 (core.clj:2494) clojure.lang.LazySeq.sval (LazySeq.java:42) clojure.lang.LazySeq.seq (LazySeq.java:60) clojure.lang.RT.seq (RT.java:484) clojure.lang.LazilyPersistentVector.create (LazilyPersistentVector.java:31) clojure.core/vec (core.clj:354) clojure.core/defrecord (core_deftype.clj:362) clojure.lang.Var.invoke (Var.java:427) clojure.lang.Var.applyTo (Var.java:532) clojure.lang.Compiler.macroexpand1 (Compiler.java:6483) clojure.lang.Compiler.macroexpand (Compiler.java:6544) clojure.lang.Compiler.eval (Compiler.java:6618) clojure.lang.Compiler.load (Compiler.java:7079) clojure.lang.RT.loadResourceScript (RT.java:370) clojure.lang.RT.loadResourceScript (RT.java:361) clojure.lang.RT.load (RT.java:440) clojure.lang.RT.load (RT.java:411) clojure.core/load/fn--5024 (core.clj:5546) clojure.core/load (core.clj:5545) clojure.core/load-one (core.clj:5352) clojure.core/load-lib/fn--4973 (core.clj:5391) clojure.core/load-lib (core.clj:5390) clojure.core/apply (core.clj:619) clojure.core/load-libs (core.clj:5429) clojure.core/apply (core.clj:619) clojure.core/require (core.clj:5512) useclj16.app/eval322/loading--4916--auto----323 (app.clj:1) useclj16.app/eval322 (app.clj:1) clojure.lang.Compiler.eval (Compiler.java:6634) clojure.lang.Compiler.eval (Compiler.java:6623) clojure.lang.Compiler.load (Compiler.java:7079) clojure.lang.RT.loadResourceScript (RT.java:370) clojure.lang.RT.loadResourceScript (RT.java:361) clojure.lang.RT.load (RT.java:440) clojure.lang.RT.load (RT.java:411) clojure.core/load/fn--5024 (core.clj:5546) clojure.core/load (core.clj:5545) clojure.core/load-one (core.clj:5352) clojure.core/load-lib/fn--4973 (core.clj:5391) clojure.core/load-lib (core.clj:5390) clojure.core/apply (core.clj:619) clojure.core/load-libs (core.clj:5429) clojure.core/apply (core.clj:619) clojure.core/require (core.clj:5512) user/eval318 (NO_SOURCE_FILE:1) clojure.lang.Compiler.eval (Compiler.java:6634) clojure.lang.Compiler.eval (Compiler.java:6597) clojure.core/eval (core.clj:2864) clojure.main/repl/read-eval-print--6594/fn--6597 (main.clj:260) clojure.main/repl/read-eval-print--6594 (main.clj:260) clojure.main/repl/fn--6603 (main.clj:278) clojure.main/repl (main.clj:278) clojure.main/repl-opt (main.clj:344) clojure.main/main (main.clj:442) clojure.lang.Var.invoke (Var.java:411) clojure.lang.Var.applyTo (Var.java:532) clojure.main.main (main.java:37) nil
The error was attributed to app.clj (useclj16.app), a namespace which requires useclj16.init, the namespace containing the defrecord.
No indication that this concerned a defrecord, or even what namespace contained the error, was present in the exception.
Patch: clj-1261-5.diff
Approach: Check explicitly that the fields are all symbols, for both defrecord and deftype, and throw a CompilerException with file, line, and column number if not. Example of exception after patch is applied, in the case give above:
user=> (require 'useclj16.app) CompilerException java.lang.AssertionError: defrecord and deftype fields must be symbols, useclj16.init.Application had: :shutdown-fn, compiling:(useclj16/init.clj:3:1)
Screened by: Alex Miller