Clojure

Certain actions on mutable fields in deftype lead to very strange error messages

Details

  • Type: Defect Defect
  • Status: Open Open
  • Priority: Minor Minor
  • Resolution: Unresolved
  • Affects Version/s: Release 1.4
  • Fix Version/s: None
  • Component/s: None
  • Labels:
  • Environment:
    Archlinux x86_64, Windows 7 x86_64

Description

Consider the following code:

(definterface Test
(^void fail []))

(deftype TestImpl
[^{:unsynchronized-mutable true :tag int} x]
Test
(fail [this]
(set! x (dec x))))

Its compilation fails with the following message:
CompilerException java.lang.VerifyError: (class: test/TestImpl, method: fail signature: ()V) Expecting to find integer on stack, compiling.../test.clj:27)

The following code works:

(definterface Test
(^void fail []))

(deftype TestImpl
[^{:unsynchronized-mutable true :tag int} x]
Test
(fail [this]
(set! x (int (dec x)))))

The only change here is that I have wrapped (dec x) form into (int) call.

I understand that in fact the former code should not work anyway (or at least should not work as I have expected) because (dec) is defined as a call to clojure.lang.Numbers.dec(), which is overloaded for double, long and Object only (in fact, changing :tag int to :tag long in the first example allows the program to compile). However, the error message is completely uninformative and misleading; it also looks like that it is a consequence of compiler error. It is also not a problem of this concrete example; I found this error in more complex interface method implementation where (set!) call was right in the middle of its body.

I'm using Clojure 1.4.0 and have experienced this problem on Archlinux x86_64 and Windows 7 x86_64.

Full stack trace of the error, in case it would be helpful:

java.lang.VerifyError: (class: test/TestImpl, method: fail signature: ()V) Expecting to find integer on stack, compiling.../test.clj:27)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6462)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.analyze(Compiler.java:6223)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5618)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5054)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3674)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6453)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6443)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.access$100(Compiler.java:37)
at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:518)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6455)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6443)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.analyze(Compiler.java:6223)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5618)
at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:5919)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6455)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.analyze(Compiler.java:6223)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5618)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5054)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3674)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6453)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.eval(Compiler.java:6508)
at clojure.lang.Compiler.load(Compiler.java:6952)
at clojure.lang.Compiler.loadFile(Compiler.java:6912)
at clojure.lang.RT$3.invoke(RT.java:307)
at test$eval3224.invoke(NO_SOURCE_FILE:43)
at clojure.lang.Compiler.eval(Compiler.java:6511)
at clojure.lang.Compiler.eval(Compiler.java:6477)
at clojure.core$eval.invoke(core.clj:2797)
at clojure.main$repl$read_eval_print__6405.invoke(main.clj:245)
at clojure.main$repl$fn__6410.invoke(main.clj:266)
at clojure.main$repl.doInvoke(main.clj:266)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.main$repl_opt.invoke(main.clj:332)
at clojure.main$main.doInvoke(main.clj:428)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.Var.invoke(Var.java:411)
at clojure.lang.AFn.applyToHelper(AFn.java:159)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.main.main(main.java:37)
Caused by: java.lang.VerifyError: (class: test/TestImpl, method: fail signature: ()V) Expecting to find integer on stack
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at clojure.lang.RT.classForName(RT.java:2039)
at clojure.lang.Compiler$HostExpr.maybeClass(Compiler.java:957)
at clojure.lang.Compiler$HostExpr.access$400(Compiler.java:736)
at clojure.lang.Compiler$NewExpr$Parser.parse(Compiler.java:2473)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6455)
... 45 more

Activity

Hide
Vladimir Matveev added a comment -

Shouldn't have set major priority; but I cannot edit issue again

Show
Vladimir Matveev added a comment - Shouldn't have set major priority; but I cannot edit issue again
Hide
Andy Fingerhut added a comment -

Reduced priority to minor, since ticket creator could not do so themselves.

Show
Andy Fingerhut added a comment - Reduced priority to minor, since ticket creator could not do so themselves.

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated: