Skip to content

Commit 1754995

Browse files
committed
Check that a self type T is closed.
What is checked: A self type T is a subtype of all selftypes of classes refernced by T. That is, a self type has to subsume all self types of its required type. Ot, otherwise said, requirements must be closed; you cannot discover new ones in following them.
1 parent 1061743 commit 1754995

File tree

3 files changed

+18
-8
lines changed

3 files changed

+18
-8
lines changed

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

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,19 +73,25 @@ object RefChecks {
7373

7474
/** Check that final and sealed restrictions on class parents
7575
* and that self type of this class conforms to self types of parents.
76+
* and required classes.
7677
*/
77-
private def checkParents(clazz: Symbol)(implicit ctx: Context): Unit = clazz.info match {
78+
private def checkParents(cls: Symbol)(implicit ctx: Context): Unit = cls.info match {
7879
case cinfo: ClassInfo =>
80+
def checkSelfConforms(other: TypeRef, category: String, relation: String) = {
81+
val otherSelf = other.givenSelfType.asSeenFrom(cls.thisType, other.classSymbol)
82+
if (otherSelf.exists && !(cinfo.selfType <:< otherSelf))
83+
ctx.error(d"$category: self type ${cinfo.selfType} of $cls does not conform to self type $otherSelf of $relation ${other.classSymbol}", cls.pos)
84+
}
7985
for (parent <- cinfo.classParents) {
8086
val pclazz = parent.classSymbol
8187
if (pclazz.is(Final))
82-
ctx.error(d"cannot extend final $pclazz", clazz.pos)
83-
if (pclazz.is(Sealed) && pclazz.associatedFile != clazz.associatedFile)
84-
ctx.error(d"cannot extend sealed $pclazz in different compilation unit", clazz.pos)
85-
val pself = parent.givenSelfType.asSeenFrom(clazz.thisType, parent.classSymbol)
86-
if (pself.exists && !(cinfo.selfType <:< pself))
87-
ctx.error(d"illegal inheritance: self type ${cinfo.selfType} of $clazz does not conform to self type $pself of parent ${parent.classSymbol}", clazz.pos)
88+
ctx.error(d"cannot extend final $pclazz", cls.pos)
89+
if (pclazz.is(Sealed) && pclazz.associatedFile != cls.associatedFile)
90+
ctx.error(d"cannot extend sealed $pclazz in different compilation unit", cls.pos)
91+
checkSelfConforms(parent, "illegal inheritance", "parent")
8892
}
93+
for (reqd <- cinfo.givenSelfType.classSymbols)
94+
checkSelfConforms(reqd.typeRef, "missing requirement", "required")
8995
case _ =>
9096
}
9197

test/dotc/tests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ class tests extends CompilerTest {
138138
@Test def neg_moduleSubtyping = compileFile(negDir, "moduleSubtyping", xerrors = 4)
139139
@Test def neg_escapingRefs = compileFile(negDir, "escapingRefs", xerrors = 2)
140140
@Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8)
141-
@Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 5)
141+
@Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 6)
142142
@Test def neg_selfreq = compileFile(negDir, "selfreq", xerrors = 4)
143143
@Test def neg_shadowedImplicits = compileFile(negDir, "arrayclone-new", xerrors = 2)
144144
@Test def neg_traitParamsTyper = compileFile(negDir, "traitParamsTyper", xerrors = 5)

tests/neg/selfInheritance.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,7 @@ object Test {
2626
object M extends C // error
2727

2828
}
29+
30+
trait X { self: Y => }
31+
trait Y { self: Z => }
32+
trait Z

0 commit comments

Comments
 (0)