Details
Assignee
Alex MillerAlex MillerReporter
Francis AvilaFrancis AvilaLabels
Approval
VettedPatch
CodePriority
MajorAffects versions
Details
Details
Assignee
Alex Miller
Alex MillerReporter
Francis Avila
Francis AvilaLabels
Approval
Vetted
Patch
Code
Priority

Affects versions
Created March 14, 2017 at 8:05 PM
Updated April 16, 2024 at 7:14 PM
The docstring for deftype says that the (set! field value) syntax is available in method bodies for mutable deftype fields. Trying to set an immutable type or record field with
(set! a newa)
will fail at compile time:However, you can also use the instance field set! syntax in this location
(set! (.a this) newa)
- this is passes the compiler and (susprisingly!) works at runtime even though the field is final:Cause:
The
set!
instance assignment does not check whether the field can be written and just emits the bytecode. The Java verifier for Java 8 bytecode does not prevent a write to a final field from happening (the policy on this has changed multiple times over the lifetime of Java). In JVM 9+, the bytecode verifier does perform final assignment check on class files version 9+ (Clojure class files are currently Java 8 level).Alternatives:
Do nothing, and wait for this to get caught at runtime in the future when we are using a later Java verifier, ie: don’t do that. This would probably fail at runtime with an IllegalAccessError if I understand correctly.
At compile time, in InstanceFieldExpr and StaticFieldExpr, check whether the field is ‘final’ and throw a compiler exception. The class may be unknown, in which case this is a reflective call and it must fail at runtime instead.
At compile time, do something specific in InstanceFieldExpr for type/record immutable fields (IRecord/IType). Don’t think we have access to the type field metadata just based on the class so the best we can do here is probably same as #2, checking final field.
Approach:
Check field accessibility for assignment and fail if attempting to emit a field assignment to a final field at compile time. A reflective field assignment will fail at runtime.
Patch: 0001-CLJ-2126-don-t-assign-final-fields.patch