Skip to content

Commit 7fa4e6c

Browse files
committed
document signature and add product pattern test
1 parent 17694b2 commit 7fa4e6c

File tree

4 files changed

+33
-11
lines changed

4 files changed

+33
-11
lines changed

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,9 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
377377
/* Whether the extractor is irrefutable */
378378
def irrefutable(unapp: tpd.Tree): Boolean = {
379379
// TODO: optionless patmat
380-
unapp.tpe.widen.resultType.isRef(scalaSomeClass) ||
381-
(unapp.symbol.is(Synthetic) && unapp.symbol.owner.linkedClass.is(Case))
380+
unapp.tpe.widen.finalResultType.isRef(scalaSomeClass) ||
381+
(unapp.symbol.is(Synthetic) && unapp.symbol.owner.linkedClass.is(Case)) ||
382+
productArity(unapp.tpe.widen.finalResultType) > 0
382383
}
383384

384385
/** Return the space that represents the pattern `pat`
@@ -457,21 +458,31 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
457458
def isSyntheticScala2Unapply(sym: Symbol) =
458459
sym.is(SyntheticCase) && sym.owner.is(Scala2x)
459460

460-
val mt@MethodType(_) = unapp.widen
461+
val mt @ MethodType(_) = unapp.widen
462+
463+
// Case unapply:
464+
// 1. return types of constructor fields if the extractor is synthesized for Scala2 case classes & length match
465+
// 2. return Nil if unapply returns Boolean (boolean pattern)
466+
// 3. return product selector types if unapply returns a product type (product pattern)
467+
// 4. return product selectors of `T` where `def get: T` is a member of the return type of unapply & length match (named-based pattern)
468+
// 5. otherwise, return `T` where `def get: T` is a member of the return type of unapply
469+
//
470+
// Case unapplySeq:
471+
// 1. return the type `List[T]` where `T` is the element type of the unapplySeq return type `Seq[T]`
461472

462473
val sig =
463474
if (isSyntheticScala2Unapply(unappSym) && caseAccessors.length == argLen)
464475
caseAccessors.map(_.info.asSeenFrom(mt.paramInfos.head, caseClass).widen)
465-
else if (mt.resultType.isRef(defn.BooleanClass))
476+
else if (mt.finalResultType.isRef(defn.BooleanClass))
466477
List()
467478
else {
468479
val isUnapplySeq = unappSym.name == nme.unapplySeq
469-
if (isProductMatch(mt.resultType, argLen) && !isUnapplySeq) {
470-
productSelectors(mt.resultType).take(argLen)
471-
.map(_.info.asSeenFrom(mt.resultType, mt.resultType.classSymbol).widen)
480+
if (isProductMatch(mt.finalResultType, argLen) && !isUnapplySeq) {
481+
productSelectors(mt.finalResultType).take(argLen)
482+
.map(_.info.asSeenFrom(mt.finalResultType, mt.resultType.classSymbol).widen)
472483
}
473484
else {
474-
val resTp = mt.resultType.select(nme.get).resultType.widen
485+
val resTp = mt.finalResultType.select(nme.get).finalResultType.widen
475486
if (isUnapplySeq) scalaListType.appliedTo(resTp.argTypes.head) :: Nil
476487
else if (argLen == 0) Nil
477488
else if (isProductMatch(resTp, argLen))

tests/patmat/optionless.check

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
20: Pattern Match Exhaustivity: _: Tree
2-
24: Pattern Match Exhaustivity: _: Tree
31
28: Pattern Match Exhaustivity: _: Tree

tests/patmat/t10502.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
5: Pattern Match Exhaustivity: Perhaps(None)
22
15: Pattern Match Exhaustivity: Nil
33
31: Pattern Match Exhaustivity: Multi(None, _)
4-
4+
44: Pattern Match Exhaustivity: Prod(None, _)

tests/patmat/t10502.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,16 @@ object Multi {
3232
case Multi(Some(i), x) =>
3333
}
3434
}
35+
36+
object Prod {
37+
def unapply(str: String): (Option[Int], Int) = ???
38+
39+
"hello" match {
40+
case Prod(Some(i), x) =>
41+
case Prod(None, x) =>
42+
}
43+
44+
"hello" match {
45+
case Prod(Some(i), x) =>
46+
}
47+
}

0 commit comments

Comments
 (0)