diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 173d5e6b1f7e..7fd0cb940680 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -891,11 +891,15 @@ object RefChecks { * can assume invariant refinement for case classes in `constrainPatternType`. */ def checkCaseClassInheritanceInvariant() = - for (caseCls <- clazz.info.baseClasses.tail.find(_.is(Case))) - for (baseCls <- caseCls.info.baseClasses.tail) - if (baseCls.typeParams.exists(_.paramVarianceSign != 0)) - for (problem <- variantInheritanceProblems(baseCls, caseCls, "non-variant", "case ")) - report.errorOrMigrationWarning(problem, clazz.srcPos, MigrationVersion.Scala2to3) + for + caseCls <- clazz.info.baseClasses.tail.find(_.is(Case)) + baseCls <- caseCls.info.baseClasses.tail + if baseCls.typeParams.exists(_.paramVarianceSign != 0) + problem <- variantInheritanceProblems(baseCls, caseCls, i"base $baseCls", "case ") + withExplain = problem.appendExplanation: + """Refining a basetype of a case class is not allowed. + |This is a limitation that enables better GADT constraints in case class patterns""".stripMargin + do report.errorOrMigrationWarning(withExplain, clazz.srcPos, MigrationVersion.Scala2to3) checkNoAbstractMembers() if (abstractErrors.isEmpty) checkNoAbstractDecls(clazz) @@ -924,7 +928,7 @@ object RefChecks { for { cls <- clazz.info.baseClasses.tail if cls.paramAccessors.nonEmpty && !mixins.contains(cls) - problem <- variantInheritanceProblems(cls, clazz.asClass.superClass, "parameterized", "super") + problem <- variantInheritanceProblems(cls, clazz.asClass.superClass, i"parameterized base $cls", "super") } report.error(problem, clazz.srcPos) } @@ -947,7 +951,7 @@ object RefChecks { if (combinedBT =:= thisBT) None // ok else Some( - em"""illegal inheritance: $clazz inherits conflicting instances of $baseStr base $baseCls. + em"""illegal inheritance: $clazz inherits conflicting instances of $baseStr. | | Direct basetype: $thisBT | Basetype via $middleStr$middle: $combinedBT""") diff --git a/tests/neg/i18552.check b/tests/neg/i18552.check new file mode 100644 index 000000000000..a7a04ed78b47 --- /dev/null +++ b/tests/neg/i18552.check @@ -0,0 +1,13 @@ +-- Error: tests/neg/i18552.scala:9:6 ----------------------------------------------------------------------------------- +9 |class MB(id:Int) extends MA(id) with M[B] // error + | ^ + | illegal inheritance: class MB inherits conflicting instances of base trait M. + | + | Direct basetype: M[B] + | Basetype via case class MA: M[A] + |--------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Refining a basetype of a case class is not allowed. + | This is a limitation that enables better GADT constraints in case class patterns + --------------------------------------------------------------------------------------------------------------------- diff --git a/tests/neg/i18552.scala b/tests/neg/i18552.scala new file mode 100644 index 000000000000..29f928e1dcfa --- /dev/null +++ b/tests/neg/i18552.scala @@ -0,0 +1,9 @@ +//> using options -explain + +trait A +trait B extends A + +trait M[+T] + +case class MA(id:Int) extends M[A] +class MB(id:Int) extends MA(id) with M[B] // error