Skip to content

Commit 04eea24

Browse files
committed
Self type inheritance check
Check that the self type of a class conforms to the self types of its parent classes.
1 parent d4dc78c commit 04eea24

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ object RefChecks {
7171
}
7272
}
7373

74+
/** Check that self type of this class conforms to self types of parents */
75+
private def checkSelfType(clazz: Symbol)(implicit ctx: Context): Unit = clazz.info match {
76+
case cinfo: ClassInfo =>
77+
for (parent <- cinfo.classParents) {
78+
val pself = parent.givenSelfType.asSeenFrom(clazz.thisType, parent.classSymbol)
79+
if (pself.exists && !(cinfo.selfType <:< pself))
80+
ctx.error(d"illegal inheritance: self type ${cinfo.selfType} of $clazz does not conform to self type $pself of parent ${parent.classSymbol}", clazz.pos)
81+
}
82+
case _ =>
83+
}
84+
7485
// Override checking ------------------------------------------------------------
7586

7687
/** 1. Check all members of class `clazz` for overriding conditions.
@@ -770,6 +781,7 @@ class RefChecks extends MiniPhase with SymTransformer { thisTransformer =>
770781
override def transformTemplate(tree: Template)(implicit ctx: Context, info: TransformerInfo) = {
771782
val cls = ctx.owner
772783
checkOverloadedRestrictions(cls)
784+
checkSelfType(cls)
773785
checkAllOverrides(cls)
774786
checkAnyValSubclass(cls)
775787
tree

test/dotc/tests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class tests extends CompilerTest {
126126
@Test def neg_i0281 = compileFile(negDir, "i0281-null-primitive-conforms", xerrors = 3)
127127
@Test def neg_moduleSubtyping = compileFile(negDir, "moduleSubtyping", xerrors = 4)
128128
@Test def neg_escapingRefs = compileFile(negDir, "escapingRefs", xerrors = 2)
129+
@Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 5)
129130

130131
@Test def dotc = compileDir(dotcDir + "tools/dotc", failedOther)(allowDeepSubtypes ++ twice) // see dotc_core
131132
@Test def dotc_ast = compileDir(dotcDir + "tools/dotc/ast", failedOther ++ twice)

tests/neg/selfInheritance.scala

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
trait T { self: B => }
2+
3+
abstract class A { self: B =>
4+
5+
}
6+
7+
class B extends A with T {
8+
}
9+
10+
class C { self: B =>
11+
12+
}
13+
14+
class D extends A // error
15+
16+
class E extends T // error
17+
18+
object Test {
19+
20+
new B() {}
21+
22+
new A() {} // error
23+
24+
object O extends A // error
25+
26+
object M extends C // error
27+
28+
}

0 commit comments

Comments
 (0)