Skip to content

Commit 0a1bb70

Browse files
author
Marc Karassev
committed
Add an error message for "invalid unapply return type" error.
Part of #1589.
1 parent 31a2f52 commit 0a1bb70

File tree

4 files changed

+52
-1
lines changed

4 files changed

+52
-1
lines changed

compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ public enum ErrorMessageID {
112112
UndefinedNamedTypeParameterID,
113113
IllegalStartOfStatementID,
114114
TraitIsExpectedID,
115+
InvalidUnapplyReturnTypeID,
115116
;
116117

117118
public int errorNumber() {

compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,4 +1916,32 @@ object messages {
19161916
|"""
19171917
}
19181918
}
1919+
1920+
case class InvalidUnapplyReturnType(unapplyResult: Type, unapplyName: Symbol#ThisName)(implicit ctx: Context)
1921+
extends Message(InvalidUnapplyReturnTypeID) {
1922+
val kind = "Type Mismatch"
1923+
val msg = hl"""| ${Red(i"$unapplyResult")} is not a valid result type of an $unapplyName method of an ${Magenta("extractor")}."""
1924+
val explanation =
1925+
hl"""
1926+
|To be used as an ${Magenta("extractor")}, an unapply method has to return an ${Green("Option[T]")} or a ${Green("Boolean")}:
1927+
|
1928+
|class A(val i: Int)
1929+
|
1930+
|object B {
1931+
| def unapply(a: A): ${Green("Option[Int]")} = Some(a.i)
1932+
|}
1933+
|
1934+
|object C {
1935+
| def unapply(a: A): ${Green("Boolean")} = a.i == 2
1936+
|}
1937+
|
1938+
|object Test {
1939+
| def test(a: A) = a match {
1940+
| ${Magenta("case B(1)")} => 1
1941+
| ${Magenta("case a @ C()")} => 2
1942+
| }
1943+
|}
1944+
""".stripMargin
1945+
}
1946+
19191947
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import language.implicitConversions
3333
import reporting.diagnostic.Message
3434
import reporting.trace
3535
import Constants.{Constant, IntTag, LongTag}
36+
import dotty.tools.dotc.reporting.diagnostic.messages.InvalidUnapplyReturnType
3637

3738
import scala.collection.mutable.ListBuffer
3839

@@ -92,7 +93,7 @@ object Applications {
9293
def getTp = extractorMemberType(unapplyResult, nme.get, pos)
9394

9495
def fail = {
95-
ctx.error(i"$unapplyResult is not a valid result type of an $unapplyName method of an extractor", pos)
96+
ctx.error(InvalidUnapplyReturnType(unapplyResult, unapplyName))
9697
Nil
9798
}
9899

compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,4 +1172,25 @@ class ErrorMessagesTests extends ErrorMessagesTest {
11721172
val TraitIsExpected(symbol) :: Nil = messages
11731173
assertEquals("class B", symbol.show)
11741174
}
1175+
1176+
@Test def invalidUnapplyReturnType =
1177+
checkMessagesAfter("frontend") {
1178+
"""
1179+
|class A(val i: Int)
1180+
|
1181+
|object A {
1182+
| def unapply(a: A): Int = a.i
1183+
| def test(a: A) = a match {
1184+
| case A() => 1
1185+
| }
1186+
|}
1187+
""".stripMargin
1188+
}.expect { (ictx, messages) =>
1189+
implicit val ctx: Context = ictx
1190+
assertMessageCount(1, messages)
1191+
val InvalidUnapplyReturnType(unapplyResult, unapplyName) :: Nil = messages
1192+
assertEquals("Int", unapplyResult.show)
1193+
assertEquals("unapply", unapplyName.show)
1194+
}
1195+
11751196
}

0 commit comments

Comments
 (0)