Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
939 views
in Technique[技术] by (71.8m points)

scala - Cannot override a type with non-volatile upper bound


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
}
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.

Why can't I do it? Is there a way, how to achieve my goal? See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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) = {

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

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
              ^

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...