Skip to content

Commit 668f3eb

Browse files
committed
Drop requirement that self types are closed
#702 introduced a requirement that self types are closed. This means > If trait X has self type S and C is a class symbol of S, then S also conforms to the self type of C. An example that violates this requirement is ```scala trait X { self: Y => } // error: missing requirement: self type Y & X of trait X does not conform to self type Z of required trait Y trait Y { self: Z => } trait Z ``` But it's no longer clear what the requirement should achieve. If we let the example above typecheck and try to implement X with something like ```scala class C extends X, Y ``` we would at that point get an error saying that `C` does not conform to the self type Z of Y. So it would have to be ```scala class C extends X, Y, Z ``` and this one looks fine. The original change in #702 was made to avoid a crash in pending/run/t7933.scala. Unfortunately, we cannot reproduce this anymore since it depends on nsc.interpreter, which is no longer part of Scala 2.13. Since we are no longer sure what the restriction should achieve I think it's better to drop it for now. If people discover problems with code that uses "open" self types, we can try to fix those problems, and if that does not work, would fallback re-instituting the restriction. It's not ideal, but I don't see another way.
1 parent ed81385 commit 668f3eb

File tree

5 files changed

+20
-25
lines changed

5 files changed

+20
-25
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -702,21 +702,8 @@ object SymDenotations {
702702
flagsUNSAFE.is(Provisional) // do not force the info to check the flag
703703

704704
/** Is this the denotation of a self symbol of some class?
705-
* This is the case if one of two conditions holds:
706-
* 1. It is the symbol referred to in the selfInfo part of the ClassInfo
707-
* which is the type of this symbol's owner.
708-
* 2. This symbol is owned by a class, it's selfInfo field refers to a type
709-
* (indicating the self definition does not introduce a name), and the
710-
* symbol's name is "_".
711-
* TODO: Find a more robust way to characterize self symbols, maybe by
712-
* spending a Flag on them?
713-
*/
714-
final def isSelfSym(using Context): Boolean = owner.infoOrCompleter match {
715-
case ClassInfo(_, _, _, _, selfInfo) =>
716-
selfInfo == symbol ||
717-
selfInfo.isInstanceOf[Type] && name == nme.WILDCARD
718-
case _ => false
719-
}
705+
*/
706+
final def isSelfSym(using Context): Boolean = is(SelfName)
720707

721708
/** Is this definition contained in `boundary`?
722709
* Same as `ownersIterator contains boundary` but more efficient.

compiler/src/dotty/tools/dotc/typer/RefChecks.scala

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,18 +102,15 @@ object RefChecks {
102102
withMode(Mode.CheckBoundsOrSelfType) {
103103
val cinfo = cls.classInfo
104104

105-
def checkSelfConforms(other: ClassSymbol, category: String, relation: String) =
105+
def checkSelfConforms(other: ClassSymbol) =
106106
val otherSelf = other.declaredSelfTypeAsSeenFrom(cls.thisType)
107107
if otherSelf.exists then
108108
if !(cinfo.selfType <:< otherSelf) then
109-
report.error(DoesNotConformToSelfType(category, cinfo.selfType, cls, otherSelf, relation, other),
109+
report.error(DoesNotConformToSelfType("illegal inheritance", cinfo.selfType, cls, otherSelf, "parent", other),
110110
cls.srcPos)
111111

112112
for psym <- parents do
113-
checkSelfConforms(psym.asClass, "illegal inheritance", "parent")
114-
for reqd <- cls.asClass.givenSelfType.classSymbols do
115-
if reqd != cls then
116-
checkSelfConforms(reqd, "missing requirement", "required")
113+
checkSelfConforms(psym.asClass)
117114
}
118115
end checkSelfAgainstParents
119116

tests/neg/selfInheritance.scala

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,3 @@ object Test {
2626
object M extends C // error: illegal inheritance: self type Test.M.type of object M$ does not conform to self type B of parent class C
2727

2828
}
29-
30-
trait X { self: Y => } // error: missing requirement: self type Y & X of trait X does not conform to self type Z of required trait Y
31-
trait Y { self: Z => }
32-
trait Z

tests/pos/i16407.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
trait X { //missing requirement: self type Z[?] & X of trait X does not conform to self type Z[X.this.A] of required trait Z
2+
self: Z[_] =>
3+
}
4+
5+
trait Z[A] extends X {
6+
self: Z[A] => // comment this to compile successfully
7+
}

tests/pos/open-selftype.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
trait X { self: Y => } // error: missing requirement: self type Y & X of trait X does not conform to self type Z of required trait Y
3+
trait Y { self: Z => }
4+
trait Z
5+
6+
package squants:
7+
trait Quantity[A <: Quantity[A]] { self: A => }
8+
trait TimeDerivative[A <: Quantity[A]] { self: Quantity[_] => }

0 commit comments

Comments
 (0)