{"record":{"id":"13289d3626a96cde","repo":"clojure/clojure","slug":"must-assign-primitive-to-primitive-mutable","errorCode":null,"errorMessage":"Must assign primitive to primitive mutable: ","messagePattern":"Must assign primitive to primitive mutable: ","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/jvm/clojure/lang/Compiler.java","lineNumber":5657,"sourceCode":"\n    Class jc;\n\tpublic Class getJavaClass() {\n\t\tif (jc == null)\n            jc = (compiledClass != null) ? compiledClass\n                : (tag != null) ? HostExpr.tagToClass(tag)\n                : IFn.class;\n        return jc;\n\t}\n\n\tpublic void emitAssignLocal(GeneratorAdapter gen, LocalBinding lb,Expr val){\n\t\tif(!isMutable(lb))\n\t\t\tthrow new IllegalArgumentException(\"Cannot assign to non-mutable: \" + lb.name);\n\t\tClass primc = lb.getPrimitiveType();\n\t\tgen.loadThis();\n\t\tif(primc != null)\n\t\t\t{\n\t\t\tif(!(val instanceof MaybePrimitiveExpr && ((MaybePrimitiveExpr) val).canEmitPrimitive()))\n\t\t\t\tthrow new IllegalArgumentException(\"Must assign primitive to primitive mutable: \" + lb.name);\n\t\t\tMaybePrimitiveExpr me = (MaybePrimitiveExpr) val;\n\t\t\tme.emitUnboxed(C.EXPRESSION, this, gen);\n\t\t\tgen.putField(objtype, lb.name, Type.getType(primc));\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tval.emit(C.EXPRESSION, this, gen);\n\t\t\tgen.putField(objtype, lb.name, OBJECT_TYPE);\n\t\t\t}\n\t}\n\n\tprivate void emitLocal(GeneratorAdapter gen, LocalBinding lb, boolean clear){\n\t\tif(closes.containsKey(lb))\n\t\t\t{\n\t\t\tClass primc = lb.getPrimitiveType();\n\t\t\tgen.loadThis();\n\t\t\tif(primc != null)\n\t\t\t\t{","sourceCodeStart":5639,"sourceCodeEnd":5675,"githubUrl":"https://github.com/clojure/clojure/blob/f3b143341d6efc6428b523b2eaa099a6cc99156e/src/jvm/clojure/lang/Compiler.java#L5639-L5675","documentation":"Within emitAssignLocal, if the local binding is a primitive mutable (e.g. ^:mutable ^long x), the assigned value expression must itself be able to emit an unboxed primitive of matching type. Assigning a boxed/Object-valued expression to a primitive mutable throws this IllegalArgumentException — Clojure refuses to silently box/unbox in this path.","triggerScenarios":"(set! prim-local boxedExpr) where prim-local is ^:mutable ^long/^double but the value expression cannot emit a primitive (e.g. the value comes from a function returning Object, a boxed intermediate, or an untagged computation).","commonSituations":"Assigning the result of a generic function (returning Object) to a ^long local; missing type hints in a chain of calls feeding the set!; looping with values derived from collections (which are always boxed).","solutions":["Add matching primitive type hints to the value expression (e.g. ^long on args/return) so it can emit unboxed","Use an explicitly primitive-producing function like (unchecked-inc x) with hints","If primitives can't be guaranteed, make the field non-primitive (drop ^long/^double hint)","Restructure loop/recur code so values stay primitive throughout"],"exampleFix":"// before\n(deftype T [^:mutable ^long x]\n  P (set-from [this v] (set! x v)))  ; v untagged -> Object\n// after\n(deftype T [^:mutable ^long x]\n  P (set-from [this ^long v] (set! x v)))","handlingStrategy":"type-guard","validationCode":"(defn primitive-assignable? [^Class primc val-tag]\n  (and (contains? #{long double} primc)\n       (= primc val-tag)))","typeGuard":null,"tryCatchPattern":"(try\n  (compile 'myns)\n  (catch IllegalArgumentException e\n    (when-not (re-find #\"Must assign primitive to primitive mutable\" (.getMessage e)) (throw e))\n    (log/error \"value expr cannot emit primitive; add ^long/^double hints\")))","preventionTips":["Type-hint the whole chain feeding a primitive mutable local","Only assign expressions known to return primitives (arith on hinted values)","Avoid assigning collection-derived values to primitive mutables","Use (set! x (unchecked-long v)) style with matching hints"],"tags":["clojure","compiler","primitives","type-hints"],"backgroundTag":"type-mismatch","analyzedSha":"f3b143341d6efc6428b523b2eaa099a6cc99156e","analyzedAt":"2026-09-09T12:04:58.961Z","contentChangedAt":"2026-09-09T12:04:58.961Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}