4

我无法理解为什么编译器允许当前代码。

我使用幻像类型来保护对方法的访问。只有在特定的“状态”下才允许调用方法。

在大多数情况下,这个不变量确实是经过编译验证的。然而,有时编译器只是忽略了幻像类型所施加的约束。这感觉像是一个重大错误。我不明白什么?

我试图尽可能地简化问题。我的用例更复杂:

class Door[State <: DoorState] private { 
    def doorKey: Int = 1
    def open[Phatom >: State <: Closed.type]: Door[Open.type] = new Door[Open.type]
    def close[Phatom >: State <: Open.type]: Door[Closed.type] = new Door[Closed.type]
}

object Door {
    def applyOpenDoor: Door[Open.type] = new Door[Open.type]
    def applyClosedDoor: Door[Closed.type] = new Door[Closed.type]
}

sealed trait DoorState
case object Closed extends DoorState
case object Open extends DoorState

然后

val aClosedDoor = Door.applyClosedDoor
val res1 = aClosedDoor.close                       // does not compile. Good!
val res2 = aClosedDoor.open.close.close            // does not compile. Good!
println(aClosedDoor.open.close.close)              // does not compile. Good!
println(aClosedDoor.open.close.close.doorKey)      // does not compile. Good!
aClosedDoor.open.close.close.doorKey == 1          // does not compile. Good!
println(aClosedDoor.open.close.close.doorKey == 1) // compiles! WTF?

正如您在上面看到的,客户端可以关闭一扇关闭的门。在我的库中,相应的行为是抛出运行时异常。(我确信异常得到了很好的保护并且无法访问)

我只能为返回布尔值的表达式复制此问题,并且当这是函数的参数时(在示例中,println

我不是在寻找替代解决方案,而是在寻找关于如何发生这种情况的解释?你不同意这是一个相当大的缺陷吗?或者,也许我错过了什么?

Scala version: 2.13.5

编辑
在讨论了gitter之后,我打开了错误请求@https ://github.com/scala/bug
问题似乎没有出现在 scala 3 中。

4

1 回答 1

4

似乎这是与使用空值方法有关的错误

def doorKey: Int = 1

如果相反,它被定义为 nilary 方法

def doorKey(): Int = 1

然后它按预期工作

println(aClosedDoor.open.close.close.doorKey() == 1) // compiler error
于 2021-06-12T19:21:49.870 回答