@@ -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))
0 commit comments