Skip to content

Commit ba66bd4

Browse files
committed
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.
1 parent b77c24c commit ba66bd4

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,6 @@ object Checking {
448448
}
449449
stats.foreach(checkValueClassMember)
450450
}
451-
452451
}
453452
}
454453

@@ -601,6 +600,16 @@ trait Checking {
601600
/** Verify classes extending AnyVal meet the requirements */
602601
def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context) =
603602
Checking.checkDerivedValueClass(clazz, stats)
603+
604+
/** Given a parent `parent` of a class `cls`, if `parent` is a trait check that
605+
* the superclass of `cls` derived from the superclass of `parent`.
606+
*/
607+
def checkTraitInheritance(parent: Symbol, cls: ClassSymbol, pos: Position)(implicit ctx: Context): Unit =
608+
parent match {
609+
case parent: ClassSymbol if parent.is(Trait) && !cls.superClass.derivesFrom(parent.superClass) =>
610+
ctx.error(em"illegal trait inheritance: super${cls.superClass} does not derive from $parent's super${parent.superClass}", pos)
611+
case _ =>
612+
}
604613
}
605614

606615
trait NoChecking extends Checking {
@@ -617,4 +626,5 @@ trait NoChecking extends Checking {
617626
override def checkSimpleKinded(tpt: Tree)(implicit ctx: Context): Tree = tpt
618627
override def checkNotSingleton(tpt: Tree, where: String)(implicit ctx: Context): Tree = tpt
619628
override def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context) = ()
629+
override def checkTraitInheritance(parentSym: Symbol, cls: ClassSymbol, pos: Position)(implicit ctx: Context) = ()
620630
}

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,13 +1288,15 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
12881288
if (tree.isType) {
12891289
val result = typedType(tree)(superCtx)
12901290
val psym = result.tpe.typeSymbol
1291+
checkTraitInheritance(psym, cls, tree.pos)
12911292
if (psym.is(Trait) && !cls.is(Trait) && !cls.superClass.isSubClass(psym))
12921293
maybeCall(result, psym, psym.primaryConstructor.info)
12931294
else
12941295
result
12951296
}
12961297
else {
12971298
val result = typedExpr(tree)(superCtx)
1299+
checkTraitInheritance(result.symbol, cls, tree.pos)
12981300
checkParentCall(result, cls)
12991301
result
13001302
}

tests/neg/i1501.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class A {
2+
def foo: Int = 1
3+
}
4+
5+
trait B extends A
6+
7+
abstract class D {
8+
def foo: Int
9+
}
10+
11+
class C extends D with B // error: illegal trait inheritance
12+
trait E extends D with B // error: illegal trait inheritance
13+
14+
object Test {
15+
def main(args: Array[String]): Unit = {
16+
println(new C().foo)
17+
}
18+
}

0 commit comments

Comments
 (0)