<< Back to previous view

[CLJ-1075] deftype: compiler error on set! for mutable field Created: 24/Sep/12  Updated: 03/Dec/12  Resolved: 03/Dec/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.4
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Gunnar Völkel Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None


 Description   

The following code demonstrates the error in a minimal example:

(defprotocol IBlob (do-sth [this, x]))

(deftype Blob [^{:volatile-mutable true} a]
  IBlob
  (do-sth [this, x] 
    (try (/ 1 x) 
      (catch Throwable t 
        (set! a (inc a))))
        (inc x)))

(deftype Blob2 [^{:volatile-mutable true} a]
  IBlob
  (do-sth [this, x] 
    (try (/ 1 x) 
      (catch Throwable t 
        (set! a (inc a))))))

Compiling Blob results in the following exception:

CompilerException java.lang.IllegalArgumentException: Cannot assign to non-mutable: a

Compiling Blob2 works as expected.



 Comments   
Comment by Chouser [ 24/Sep/12 9:13 AM ]
(defmethod print-method clojure.lang.Compiler$LocalBinding 
  [^clojure.lang.Compiler$LocalBinding o w]
  (.write w
    (str "#<LB "
      (binding [*print-meta* true]
        (pr-str {:sym (.-sym o)
                 :tag (.-tag o)
                 :idx (.-idx o)
                 :name (.-name o)
                 :isArg (.-isArg o)
                 :canBeCleared (.canBeCleared o)
                 :recurMistmatch (.-recurMistmatch o)})) ">")))

(defmacro prn-env []
  (doseq [[_ lb] &env]
    (prn lb)))

(deftype T [^:volatile-mutable x]
  clojure.lang.IDeref
  (deref [this]
    (try
      (catch Exception e
        (prn-env)
        (set! x 0)))
    1))

#<LB {:sym ^{:volatile-mutable true} x, :tag nil, :idx -1, :name "x", :isArg false, :canBeCleared true, :recurMistmatch false}>
#<LB {:sym e, :tag Exception, :idx 3, :name "e", :isArg false, :canBeCleared true, :recurMistmatch false}>
#<LB {:sym this, :tag compile__stub.user.T, :idx 0, :name "this", :isArg false, :canBeCleared true, :recurMistmatch false}>
CompilerException java.lang.IllegalArgumentException: Cannot assign to non-mutable: x, compiling:(NO_SOURCE_PATH:1)
Comment by Gunnar Völkel [ 24/Sep/12 9:21 AM ]

As a workaround you can create a setter method for that field, e.g.

(set-a [this, na] (set! a na))
Comment by Andy Fingerhut [ 24/Sep/12 10:06 AM ]

Is this the same issue as CLJ-1023?

Comment by Gunnar Völkel [ 04/Oct/12 4:15 AM ]

That one looks very similar, yes.
The "non-tail try-catch as closure" being the problem, would explain the examples above, as well.

Comment by Timothy Baldridge [ 03/Dec/12 10:52 AM ]

closing as duplicate of CLJ-1023

Generated at Tue Oct 21 13:23:13 CDT 2014 using JIRA 4.4#649-r158309.