Arcadia icon indicating copy to clipboard operation
Arcadia copied to clipboard

invalid il on deftype mutation

Open timsgardner opened this issue 7 years ago • 3 comments

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.

timsgardner avatar Aug 27 '18 21:08 timsgardner

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))


timsgardner avatar Aug 27 '18 23:08 timsgardner

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.

nasser avatar Sep 21 '18 17:09 nasser

ClojureJVM throws NullPointerException for the same code.

nasser avatar Oct 01 '18 19:10 nasser