diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java index bc3bec0e3bcb..e2657003cba7 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java @@ -114,6 +114,7 @@ public enum ErrorMessageID { TraitIsExpectedID, TraitRedefinedFinalMethodFromAnyRefID, PackageNameAlreadyDefinedID, + UnapplyInvalidNumberOfArgumentsID, ; public int errorNumber() { diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 2a79fe54c90b..996b187b70f5 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1929,4 +1929,17 @@ object messages { val explanation = hl"An ${"object"} cannot have the same name as an existing ${"package"}. Rename either one of them." } + + case class UnapplyInvalidNumberOfArguments(qual: untpd.Tree, argTypes: List[Type])(implicit ctx: Context) + extends Message(UnapplyInvalidNumberOfArgumentsID) { + val kind = "Syntax" + val msg = hl"Wrong number of argument patterns for $qual; expected: ($argTypes%, %)" + val explanation = + hl"""The Unapply method of $qual was used with incorrect number of arguments. + |Expected usage would be something like: + |case $qual(${argTypes.map(_ => '_')}%, %) => ... + | + |where subsequent arguments would have following types: ($argTypes%, %). + |""".stripMargin + } } diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index e1a3cd830221..a7b3c601e013 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -3,7 +3,7 @@ package dotc package typer import core._ -import ast.{Trees, untpd, tpd, TreeInfo} +import ast.{TreeInfo, Trees, tpd, untpd} import util.Positions._ import util.Stats.track import Trees.Untyped @@ -26,13 +26,14 @@ import EtaExpansion._ import Inferencing._ import collection.mutable -import config.Printers.{typr, unapp, overload} +import config.Printers.{overload, typr, unapp} import TypeApplications._ import language.implicitConversions import reporting.diagnostic.Message import reporting.trace import Constants.{Constant, IntTag, LongTag} +import dotty.tools.dotc.reporting.diagnostic.messages.UnapplyInvalidNumberOfArguments import scala.collection.mutable.ListBuffer @@ -969,7 +970,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => case _ => args } if (argTypes.length != bunchedArgs.length) { - ctx.error(em"wrong number of argument patterns for $qual; expected: ($argTypes%, %)", tree.pos) + ctx.error(UnapplyInvalidNumberOfArguments(qual, argTypes), tree.pos) argTypes = argTypes.take(args.length) ++ List.fill(argTypes.length - args.length)(WildcardType) } diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala index a6bc8a46fd38..5917c0d1314c 100644 --- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala +++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala @@ -1189,7 +1189,6 @@ class ErrorMessagesTests extends ErrorMessagesTest { assertEquals("method wait", method.show) } - @Test def packageNameAlreadyDefined = checkMessagesAfter("frontend") { """ @@ -1203,4 +1202,26 @@ class ErrorMessagesTests extends ErrorMessagesTest { val PackageNameAlreadyDefined(pkg) = messages.head assertEquals(pkg.show, "object bar") } + + @Test def unapplyInvalidNumberOfArguments = + checkMessagesAfter("frontend") { + """ + |case class Boo(a: Int, b: String) + | + |object autoTuplingNeg2 { + | val z = Boo(1, "foo") + | + | z match { + | case Boo(a, b, c) => a + | } + |} + """.stripMargin + } + .expect { (ictx, messages) => + implicit val ctx: Context = ictx + assertMessageCount(1, messages) + val UnapplyInvalidNumberOfArguments(qual, argTypes) :: Nil = messages + assertEquals("Boo", qual.show) + assertEquals("(class Int, class String)", argTypes.map(_.typeSymbol).mkString("(", ", ", ")")) + } }