无法覆盖具有非易失性上限的类型 [英] Cannot override a type with non-volatile upper bound

查看:51
本文介绍了无法覆盖具有非易失性上限的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


我在 Scala 中有一个编译器错误,我不知道它指的是什么:
假设这些声明:


I have a compiler error in scala and I don't know what does it refer to:
Assume these declarations:

trait Abstract {
  type MyType
}
trait AInner
trait A extends Abstract{
  type MyType <: AInner
}
trait BInner {
  def bMethod : Int
}
trait B extends Abstract with A{
  override type MyType <: BInner with A#MyType
}

我在这里试图实现的(在特征 B 中)是进一步限制在 Abstract 中声明的类型 MyType,因此任何类型的值MyType 必须扩展 mixin 树中的所有 MyType.

编译器给了我这个消息(如标题所示):type MyType 是一个 volatile 类型;不能覆盖具有非易失性上限的类型.我明白,类型波动在这里发生是因为类型结合with A#MyType,错误的一部分:type with non-volatile upper bound 可能是指类型声明 type MyType <: AInner,其中 AInner 不是抽象类型,因此是非易失性的.

What I'm trying to achieve here(in trait B) is to further restrict the type MyType declared in Abstract, so any value of type MyType must extend all the MyTypes in the mixin tree.

The compiler is giving me this message(as in title): type MyType is a volatile type; cannot override a type with non-volatile upper bound. I understand, that type volatility is happening here because of type conjuction with A#MyType, the part of the error: type with non-volatile upper bound probably refers to the type declaration type MyType <: AInner, where AInner is not an abstract type thus non-volatile.

推荐答案

在编译器中移除这个检查让我们发现不健全的可能性.

Removing this check in the compiler lets us shine a light on the potential for unsoundness.

diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 37a7e3c..78a8959 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -5128,8 +5128,7 @@ trait Typers extends Adaptations with Tags {

       def typedSelectFromTypeTree(tree: SelectFromTypeTree) = {
         val qual1 = typedType(tree.qualifier, mode)
-        if (qual1.tpe.isVolatile) TypeSelectionFromVolatileTypeError(tree, qual1)
-        else typedSelect(tree, qual1, tree.name)
+        typedSelect(tree, qual1, tree.name)
       }

       def typedTypeBoundsTree(tree: TypeBoundsTree) = {

然后,从编译器测试用例中运行代码,以进行 volatile 类型的非法类型选择:

Then, running the code from a compiler test case for illegal type selection for volatile types:

scala> class A; class B extends A
defined class A
defined class B

scala> trait C {
     |   type U
     |   trait D { type T >: B <: A }
     |   val y: (D with U)#T = new B
     | }
defined trait C

scala> class D extends C {
     |   trait E
     |   trait F { type T = E }
     |   type U = F
     |   def frob(arg : E) : E = arg
     |   frob(y)
     | }
defined class D

scala> new D
java.lang.ClassCastException: B cannot be cast to D$E

据我所知,问题源于 Scala 没有真正的交集类型.

As I understand it, the issue stems from the fact that Scala doesn't have true intersection types.

scala> type A = { type T = Int }
defined type alias A

scala> type B = { type T = String }
defined type alias B

scala> "": (A with B)#T
res16: String = ""

scala> 0: (A with B)#T
<console>:37: error: type mismatch;
 found   : Int(0)
 required: String
              0: (A with B)#T
              ^

如果对相关对象类型 (DOT) 的研究结果可行,这在未来可能会发生变化水果.

This might change in the future, if the research into Dependent Object Types (DOT) bears fruit.

这篇关于无法覆盖具有非易失性上限的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆