<< Back to previous view

[CLJ-1023] non-tail-position try block breaks mutable fields in deftype Created: 08/Jul/12  Updated: 27/Jun/13  Resolved: 03/Dec/12

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

Type: Defect Priority: Minor
Reporter: Stuart Sierra Assignee: Rich Hickey
Resolution: Declined Votes: 0
Labels: None

Attachments: File demonstration.clj    


The :unsynchronized-mutable fields of a deftype cannot be set! inside a try block that is not in tail position of the method.

See file *demonstration.clj* for an complete code example.

Comment by Rich Hickey [ 05/Sep/12 7:07 AM ]

I looked at this. The problem is that non-tail try blocks turn into closures, and thus the field gets propagated as a constant. IOW this can't work:

(deftype Foo4 [^:unsynchronized-mutable x]
  (set-x [this v]
    ((fn [] (set! x v)))

I'm not going to re-evaluate the try/closure approach right now, so I recommend you make a helper method that just does the assignment and then call that in the bigger context, as a workaround.

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

Closing this as it requires more than a simple bug fix. If you feel that Rich's work-around is unsatisfactory please create a clojure-dev discussion about rewriting try-catch.

Comment by Nicola Mometto [ 27/Jun/13 5:33 AM ]

The patch at ticket CLJ-1226 makes it possible to write

(deftype foo [^:unsynchronized-mutable x] MutableX (set-x [this v] (try (set! (.x this) v)) v))

that is probably a better workaround than writing a helper method

Generated at Tue Jan 16 21:38:19 CST 2018 using JIRA 4.4#649-r158309.