diff options
-rw-r--r-- | src/dotty/tools/dotc/typer/RefChecks.scala | 12 | ||||
-rw-r--r-- | test/dotc/tests.scala | 1 | ||||
-rw-r--r-- | tests/neg/selfInheritance.scala | 28 |
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 + +} |