Skip to content

Commit

Permalink
Merge pull request #9162 from dwijnand/patmat-custom-unapply
Browse files Browse the repository at this point in the history
Teach patmat that unapplies can be customised
  • Loading branch information
lrytz committed Aug 18, 2020
2 parents dd32fe7 + 8c5eb73 commit 8e107bb
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
Expand Up @@ -97,7 +97,9 @@ trait PatternTypers {
// Dueling test cases: pos/overloaded-unapply.scala, run/case-class-23.scala, pos/t5022.scala
// A case class with 23+ params has no unapply method.
// A case class constructor may be overloaded with unapply methods in the companion.
else if (canElide && caseClass.isCase && !member.isOverloaded)
// A case class maybe have its own custom unapply (so non-synthetic) scala/bug#11252
// Unapply methods aren't `isCaseApplyOrUnapply` in Scala 3 tasty/run/src-2/tastytest/TestColour.scala
else if (canElide && caseClass.isCase && !member.isOverloaded && (member == NoSymbol || member.isSynthetic))
logResult(s"convertToCaseConstructor($fun, $caseClass, pt=$pt)")(convertToCaseConstructor(fun, caseClass, pt))
else if (!reallyExists(member))
CaseClassConstructorError(fun, s"${fun.symbol} is not a case class, nor does it have a valid unapply/unapplySeq member")
Expand Down
1 change: 1 addition & 0 deletions src/reflect/scala/reflect/internal/Symbols.scala
Expand Up @@ -960,6 +960,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>

/** Is this symbol a synthetic apply or unapply method in a companion object of a case class? */
// xeno-by: why this obscure use of the CASE flag? why not simply compare name with nme.apply and nme.unapply?
// dnw: "fixed in Dotty"? In Scala 3 unapply methods don't use the CASE flag.
final def isCaseApplyOrUnapply =
isMethod && isCase && isSynthetic

Expand Down
13 changes: 13 additions & 0 deletions test/files/pos/t11252.scala
@@ -0,0 +1,13 @@
final case class Ttl(duration: Int, other: Boolean)

object Ttl {
def apply(duration: Int) = new Ttl(duration, false)

def unapply(x: Ttl): Option[Int] = if (x eq null) None else Some(x.duration)
}

object Test {
def main(args: Array[String]): Unit = {
Ttl(1) match { case Ttl(y) => println(y) }
}
}

0 comments on commit 8e107bb

Please sign in to comment.