aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Checking.scala12
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Typer.scala2
-rw-r--r--tests/neg/i1501.scala18
3 files changed, 31 insertions, 1 deletions
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)
+ }
+}