Skip to content

Fix 11018 - consistency of trait parameters #11059

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/RefChecks.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package dotty.tools.dotc
package dotty.tools
package dotc
package typer

import transform._
Expand Down Expand Up @@ -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`,
Expand Down
21 changes: 21 additions & 0 deletions tests/neg/i11018.scala
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion tests/neg/i3989f.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down