Cannot override a type with non-volatile upper bound

non-volatile, scala, type-bounds, types, volatility

Solution

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.

Problem

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 `MyType`s 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?

Original source