diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 0985d8eb326a..7ff65d5c36e3 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -1,4 +1,5 @@ -package dotty.tools.dotc +package dotty.tools +package dotc package typer import transform._ @@ -800,7 +801,34 @@ object RefChecks { report.error(problem(), clazz.srcPos) } + // check that basetype and subtype agree on types of trait parameters + // + // I.e. trait and class parameters not only need to conform to the expected + // type of the corresponding base-trait, but also to the type as seen by the + // inheriting subtype. + def checkTraitParametersOK() = for { + parent <- clazz.info.parents + parentSym = parent.classSymbol + if parentSym.isClass + cls = parentSym.asClass + if cls.paramAccessors.nonEmpty + param <- cls.paramAccessors + } { + val tpeFromParent = parent.memberInfo(param) + val tpeFromClazz = clazz.thisType.memberInfo(param) + if (!(tpeFromParent <:< tpeFromClazz)) { + val msg = + em"""illegal parameter: The types of $param do not match. + | + | $param in $cls has type: $tpeFromParent + | but $clazz expects $param to have type: $tpeFromClazz""" + + report.error(msg, clazz.srcPos) + } + } + checkParameterizedTraitsOK() + checkTraitParametersOK() } /** Check that `site` does not inherit conflicting generic instances of `baseCls`, diff --git a/tests/neg/i11018.scala b/tests/neg/i11018.scala new file mode 100644 index 000000000000..983722997582 --- /dev/null +++ b/tests/neg/i11018.scala @@ -0,0 +1,21 @@ +trait Foo { + def name: String +} +class Bar + +trait CClass[+A](val a: A) { + val b = a +} + +trait CTrait[+A](val a: A) { + val b = a +} +trait DTrait[+B] extends CTrait[B] +trait DClass[+B] extends CClass[B] + +final class F1 extends DTrait[Foo] with CTrait[Bar](new Bar) // error: illegal parameter +final class F2 extends CTrait[Bar](new Bar) with DTrait[Foo] // error: illegal parameter +final class F3 extends DClass[Foo] with CClass[Bar](new Bar) // error: illegal parameter +final class F4 extends CClass[Bar](new Bar) with DClass[Foo] // error: illegal parameter + +final class F5 extends DTrait[Foo] with CTrait[Foo & Bar](new Bar with Foo { def name = "hello"}) // ok diff --git a/tests/neg/i3989f.scala b/tests/neg/i3989f.scala index ce68f16b54b0..12738a83d282 100644 --- a/tests/neg/i3989f.scala +++ b/tests/neg/i3989f.scala @@ -3,7 +3,7 @@ object Test extends App { class B[+X](val y: X) extends A[X](y) class C extends B(5) with A[String] // error: illegal inheritance - class D extends B(5) with A[Any] // ok + class D extends B(5) with A[Any] // error: illegal parameter def f(a: A[Int]): String = a match { case c: C => c.x