Arcadia
Arcadia copied to clipboard
invalid il on deftype mutation
As uncovered by #289: If
(defprotocol P
(foo [this]))
(deftype B [^:unsynchronized-mutable ^int a]
P
(foo [this]
(set! a 20)))
then
(foo (->B 3))
throws
InvalidProgramException Invalid IL code in arcadia.core.B:foo (): IL_000a: stfld 0x0affc860
arcadia/core$eval__20988__20993.invokeStatic (:0)
arcadia/core$eval__20988__20993.invoke (:0)
clojure.lang.Compiler.eval (:0)
clojure/core$eval__3112.invokeStatic (:0)
clojure/core$eval__3112.invoke (:0)
arcadia/socket_repl$game_thread_evalfn__17132fn__17137__17149.invoke (:0)
However if
(deftype B [^:unsynchronized-mutable ^int a]
P
(foo [this]
(set! (.a this) 20)))
then
(foo (->B 3))
totally works.
while we're at it, in Arcadia this works:
(defprotocol P
(foo [this]))
(deftype B [^:unsynchronized-mutable ^String a]
P
(foo [this]
(set! (.a this) 20)))
(let [b (->B "albatross")]
(set! (.a b) :milkman)
(.a b))
This works:
(defprotocol P
(foo [this]))
(deftype B [^:unsynchronized-mutable ^long a] ;; <= type hint changed from int to long
P
(foo [this]
(set! a 20)))
and this works
(defprotocol P
(foo [this]))
(deftype B [^:unsynchronized-mutable ^int a]
P
(foo [this]
(set! a (int 20)))) ;; <= casting to int
This is a compiler bug. It's not emitting correct IL to convert between long and int in the provided case. Clojure integer literals are all longs, so a conversion is needed when you do (set! a 20). The compiler is dropping the ball here for some reason. I will investigate.
ClojureJVM throws NullPointerException for the same code.