Skip to content

Commit 960742b

Browse files
b-studiossmarter
authored andcommitted
Check conformance of trait and class parameters of base types
1 parent 45d0678 commit 960742b

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
package dotty.tools.dotc
1+
package dotty.tools
2+
package dotc
23
package typer
34

45
import transform._
@@ -800,7 +801,34 @@ object RefChecks {
800801
report.error(problem(), clazz.srcPos)
801802
}
802803

804+
// check that basetype and subtype agree on types of trait parameters
805+
//
806+
// I.e. trait and class parameters not only need to conform to the expected
807+
// type of the corresponding base-trait, but also to the type as seen by the
808+
// inheriting subtype.
809+
def checkTraitParametersOK() = for {
810+
parent <- clazz.info.parents
811+
parentSym = parent.classSymbol
812+
if parentSym.isClass
813+
cls = parentSym.asClass
814+
if cls.paramAccessors.nonEmpty
815+
param <- cls.paramAccessors
816+
} {
817+
val tpeFromParent = parent.memberInfo(param)
818+
val tpeFromClazz = clazz.thisType.memberInfo(param)
819+
if (!(tpeFromParent <:< tpeFromClazz)) {
820+
val msg =
821+
em"""illegal parameter: The types of $param do not match.
822+
|
823+
| $param in $cls has type: $tpeFromParent
824+
| but $clazz expects $param to have type: $tpeFromClazz"""
825+
826+
report.error(msg, clazz.srcPos)
827+
}
828+
}
829+
803830
checkParameterizedTraitsOK()
831+
checkTraitParametersOK()
804832
}
805833

806834
/** Check that `site` does not inherit conflicting generic instances of `baseCls`,

tests/neg/i11018.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
trait Foo {
2+
def name: String
3+
}
4+
class Bar
5+
6+
trait CClass[+A](val a: A) {
7+
val b = a
8+
}
9+
10+
trait CTrait[+A](val a: A) {
11+
val b = a
12+
}
13+
trait DTrait[+B] extends CTrait[B]
14+
trait DClass[+B] extends CClass[B]
15+
16+
final class F1 extends DTrait[Foo] with CTrait[Bar](new Bar) // error: illegal parameter
17+
final class F2 extends CTrait[Bar](new Bar) with DTrait[Foo] // error: illegal parameter
18+
final class F3 extends DClass[Foo] with CClass[Bar](new Bar) // error: illegal parameter
19+
final class F4 extends CClass[Bar](new Bar) with DClass[Foo] // error: illegal parameter
20+
21+
final class F5 extends DTrait[Foo] with CTrait[Foo & Bar](new Bar with Foo { def name = "hello"}) // ok

tests/neg/i3989f.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ object Test extends App {
33
class B[+X](val y: X) extends A[X](y)
44
class C extends B(5) with A[String] // error: illegal inheritance
55

6-
class D extends B(5) with A[Any] // ok
6+
class D extends B(5) with A[Any] // error: illegal parameter
77

88
def f(a: A[Int]): String = a match {
99
case c: C => c.x

0 commit comments

Comments
 (0)