2024 年 Clojure 状况调查!中分享您的想法。

欢迎!请查阅关于页面以获取有关如何操作的更多信息。

0 投票
编译器
即使在它们是最终的,也可以为 defrecord 的字段设置!


(defprotocol SetA (seta [x a]))
=> SetA
(defrecord X [a]
  SetA
  (seta [this newa]
    ; 下一行应该在编译时出错,但实际上并没有出错。
    ; (然而(set! a newa)会正确地出错。)
    (set! (.a this) newa)))
=> user.X
(def x (->X 0))
=> #'user/x
x
=> #user.X{:a 0}
(seta x 1) ;; 这不应该运行。
=> 1
x
=> #user.X{:a 1}


这里有两个问题

# Clojure 编译器没有检测到 (set! (.a this) x) 是对最终字段的赋值。这可以加强。Nicola Mometto 发现了原因,并相信他已经找到了一个简单的补丁。
# JVM 字节码验证器仅在 9 版本及以上版本的 classfiles 上执行必要的最终赋值检查:https://bugs.openjdk.java.net/browse/JDK-8159215 (Clojure 生成版本 6 的 classfiles。)这超出了我们的控制。


*方法:* 如果尝试设置!一个最终字段,则使编译器在编译时失败

*补丁:* 0001-CLJ-2126-don-t-assign-final-fields.patch

1 答案

0 投票
参考: https://clojure.atlassian.net/browse/CLJ-2126 (由 favila 报告)
...