aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/typer/RefChecks.scala12
-rw-r--r--test/dotc/tests.scala1
-rw-r--r--tests/neg/selfInheritance.scala28
3 files changed, 41 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/typer/RefChecks.scala b/src/dotty/tools/dotc/typer/RefChecks.scala
index 9b14fffc0..6a1f3652b 100644
--- a/src/dotty/tools/dotc/typer/RefChecks.scala
+++ b/src/dotty/tools/dotc/typer/RefChecks.scala
@@ -71,6 +71,17 @@ object RefChecks {
}
}
+ /** Check that self type of this class conforms to self types of parents */
+ private def checkSelfType(clazz: Symbol)(implicit ctx: Context): Unit = clazz.info match {
+ case cinfo: ClassInfo =>
+ for (parent <- cinfo.classParents) {
+ val pself = parent.givenSelfType.asSeenFrom(clazz.thisType, parent.classSymbol)
+ if (pself.exists && !(cinfo.selfType <:< pself))
+ ctx.error(d"illegal inheritance: self type ${cinfo.selfType} of $clazz does not conform to self type $pself of parent ${parent.classSymbol}", clazz.pos)
+ }
+ case _ =>
+ }
+
// Override checking ------------------------------------------------------------
/** 1. Check all members of class `clazz` for overriding conditions.
@@ -770,6 +781,7 @@ class RefChecks extends MiniPhase with SymTransformer { thisTransformer =>
override def transformTemplate(tree: Template)(implicit ctx: Context, info: TransformerInfo) = {
val cls = ctx.owner
checkOverloadedRestrictions(cls)
+ checkSelfType(cls)
checkAllOverrides(cls)
checkAnyValSubclass(cls)
tree
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index a015b9efe..c3f501a52 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -126,6 +126,7 @@ class tests extends CompilerTest {
@Test def neg_i0281 = compileFile(negDir, "i0281-null-primitive-conforms", xerrors = 3)
@Test def neg_moduleSubtyping = compileFile(negDir, "moduleSubtyping", xerrors = 4)
@Test def neg_escapingRefs = compileFile(negDir, "escapingRefs", xerrors = 2)
+ @Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 5)
@Test def dotc = compileDir(dotcDir + "tools/dotc", failedOther)(allowDeepSubtypes ++ twice) // see dotc_core
@Test def dotc_ast = compileDir(dotcDir + "tools/dotc/ast", failedOther ++ twice)
diff --git a/tests/neg/selfInheritance.scala b/tests/neg/selfInheritance.scala
new file mode 100644
index 000000000..5f61c5bbb
--- /dev/null
+++ b/tests/neg/selfInheritance.scala
@@ -0,0 +1,28 @@
+trait T { self: B => }
+
+abstract class A { self: B =>
+
+}
+
+class B extends A with T {
+}
+
+class C { self: B =>
+
+}
+
+class D extends A // error
+
+class E extends T // error
+
+object Test {
+
+ new B() {}
+
+ new A() {} // error
+
+ object O extends A // error
+
+ object M extends C // error
+
+}