scala3 中的类型投影仍然不健全吗?

问题描述 投票:0回答:1

Scala3 已经放弃了通用类型投影,因为它不健全:
编译运行时失败的代码是可能的。

(编辑问题以反映评论)

考虑以下 scala3 代码: 斯卡斯蒂

class A:
    class X:
        def outer : A.this.type = A.this
    

class B extends A
class C extends A

val b0 = new B
val b1 = b0
val b2 = new B

val c0 = new C
val c1 = c0
val c2 = new C

val b0x : A#X = new b0.X

val pathTypeMatch = b0x match
    case _ : c2.X => "c2.X"
    case _ : c1.X => "c1.x"
    case _ : c0.X => "c0.X"
    case _ : b2.X => "b2.X"
    case _ : b1.X => "b1.X"
    case _ : b0.X => "b0.X"
    case _        => "ELSE"

pathTypeMatch // "b1.x" 

val projectionTypeMatch = b0x match
    case _ : C#X => "C#X"
    case _ : B#X => "B#X"
    case _ : A#X => "A#X"
    case _       => "ELSE"

projectionTypeMatch // "C#X" !!!

val failingTypeMatch = b0x match
    case cx : C#X =>
        val c : C = cx.outer // Fails at runtime

代码可以编译,但在运行时失败,并显示“B 类无法转换为 C 类”。

编译器将

C#X
B#X
擦除视为
A#X
,因此
case cx:C#X
分支匹配。从那里开始,将
cx.outer
视为
C
是合理的(这是错误的),因此是例外。

不发出任何警告。 不涉及类型测试。

查看

projectionTypeMatch
的字节码时,所有3个分支的测试完全相同。

类型模式中:

(类型模式 T 是 ...)对类

C
p.C
T#C
的引用。 此类型模式匹配给定类的任何非空实例。 请注意,类的前缀(如果存在)与 确定类实例。

事实上,当与路径依赖类型进行匹配时,行为是预期的(

pathTypeMatch
b1.x
)。特别是,编译器必须在匹配中考虑 X 外部。

人们会期望与 projection-types 的匹配是一致的,不是吗?

意图是什么?

似乎 scala3 中对具体类型的类型投影限制将允许一致的行为。是这样吗?

scala pattern-matching scala-3 type-projection
1个回答
0
投票

参见https://github.com/lampepfl/dotty/issues/16728

已修复https://github.com/lampepfl/dotty/pull/17136

观察到的行为并不反映意图。 scala3 编译器已修复:

3.3.1-RC1-bin-20230327-a569057-NIGHTLY
的行为符合预期。

请注意,错误行为可能被视为一般类型投影不健全的味道,并且无法在scala2中修复。

© www.soinside.com 2019 - 2024. All rights reserved.