From ba66bd47f08e1adf3d44f578452a5113948cb988 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 2 Feb 2017 14:55:06 +1100 Subject: Fix #1501 - Check trait inheritance condition We need to check a coherence condition between the superclass of a trait and the superclass of an inheriting class or trait. --- compiler/src/dotty/tools/dotc/typer/Checking.scala | 12 +++++++++++- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 ++ tests/neg/i1501.scala | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/neg/i1501.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index ca62ed0a9..f4625cbfd 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -448,7 +448,6 @@ object Checking { } stats.foreach(checkValueClassMember) } - } } @@ -601,6 +600,16 @@ trait Checking { /** Verify classes extending AnyVal meet the requirements */ def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context) = Checking.checkDerivedValueClass(clazz, stats) + + /** Given a parent `parent` of a class `cls`, if `parent` is a trait check that + * the superclass of `cls` derived from the superclass of `parent`. + */ + def checkTraitInheritance(parent: Symbol, cls: ClassSymbol, pos: Position)(implicit ctx: Context): Unit = + parent match { + case parent: ClassSymbol if parent.is(Trait) && !cls.superClass.derivesFrom(parent.superClass) => + ctx.error(em"illegal trait inheritance: super${cls.superClass} does not derive from $parent's super${parent.superClass}", pos) + case _ => + } } trait NoChecking extends Checking { @@ -617,4 +626,5 @@ trait NoChecking extends Checking { override def checkSimpleKinded(tpt: Tree)(implicit ctx: Context): Tree = tpt override def checkNotSingleton(tpt: Tree, where: String)(implicit ctx: Context): Tree = tpt override def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context) = () + override def checkTraitInheritance(parentSym: Symbol, cls: ClassSymbol, pos: Position)(implicit ctx: Context) = () } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 18ae790b7..4f9d96c70 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1288,6 +1288,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit if (tree.isType) { val result = typedType(tree)(superCtx) val psym = result.tpe.typeSymbol + checkTraitInheritance(psym, cls, tree.pos) if (psym.is(Trait) && !cls.is(Trait) && !cls.superClass.isSubClass(psym)) maybeCall(result, psym, psym.primaryConstructor.info) else @@ -1295,6 +1296,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } else { val result = typedExpr(tree)(superCtx) + checkTraitInheritance(result.symbol, cls, tree.pos) checkParentCall(result, cls) result } diff --git a/tests/neg/i1501.scala b/tests/neg/i1501.scala new file mode 100644 index 000000000..045f2be1d --- /dev/null +++ b/tests/neg/i1501.scala @@ -0,0 +1,18 @@ +class A { + def foo: Int = 1 +} + +trait B extends A + +abstract class D { + def foo: Int +} + +class C extends D with B // error: illegal trait inheritance +trait E extends D with B // error: illegal trait inheritance + +object Test { + def main(args: Array[String]): Unit = { + println(new C().foo) + } +} -- cgit v1.2.3