diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index 9875c508c9fd..31932fd15966 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -1962,7 +1962,11 @@ class UnapplyInvalidReturnType(unapplyResult: Type, unapplyName: Name)(using Con |To be used as an extractor, an unapply method has to return a type that either: | - has members ${Magenta("isEmpty: Boolean")} and ${Magenta("get: S")} (usually an ${Green("Option[S]")}) | - is a ${Green("Boolean")} - | - is a ${Green("Product")} (like a ${Magenta("Tuple2[T1, T2]")}) + | - is a ${Green("Product")} (like a ${Magenta("Tuple2[T1, T2]")}) of arity i with i >= 1, and has members _ 1 to _i + | + |See: https://docs.scala-lang.org/scala3/reference/changed-features/pattern-matching.html#fixed-arity-extractors + | + |Examples: | |class A(val i: Int) | diff --git a/tests/neg/17077.scala b/tests/neg/17077.scala new file mode 100644 index 000000000000..452343ccfc6f --- /dev/null +++ b/tests/neg/17077.scala @@ -0,0 +1,14 @@ +case class IsIntResult() + +object IsInt: + def unapply(x: Int): IsIntResult = IsIntResult + +@main def test = + val v: String | Int = "Blop" + val res = + v match + case IsInt() => 43 // error: cannot use a product of arity zero as a return type for unapply + // see UnapplyInvalidReturnType in messages.scala + // and https://docs.scala-lang.org/scala3/reference/changed-features/pattern-matching.html#fixed-arity-extractors + case _ => 42 + println(res) diff --git a/tests/pos/17077.scala b/tests/pos/17077.scala new file mode 100644 index 000000000000..a3317fbfbeab --- /dev/null +++ b/tests/pos/17077.scala @@ -0,0 +1,22 @@ + + +class MyProduct extends Product: + def foo = ??? + override def productArity: Int = 1 + override def productElement(n: Int): Any = 42 + override def canEqual(that: Any): Boolean = that.isInstanceOf[MyProduct] + def _1 = 42 + +object MyProductUnapply: + def unapply(x: Int): MyProduct = MyProduct() + +@main def test = + val v: String | Int = "Blop" + val res = + v match + case MyProductUnapply(y) => y // works: a product of arity 1 is accepted as the return type of unapply + // see UnapplyInvalidReturnType in messages.scala + // and https://docs.scala-lang.org/scala3/reference/changed-features/pattern-matching.html#fixed-arity-extractors + case _ => 42 + println(res) +