@@ -377,8 +377,9 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
377
377
/* Whether the extractor is irrefutable */
378
378
def irrefutable (unapp : tpd.Tree ): Boolean = {
379
379
// 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
382
383
}
383
384
384
385
/** Return the space that represents the pattern `pat`
@@ -451,30 +452,48 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
451
452
/** Parameter types of the case class type `tp`. Adapted from `unapplyPlan` in patternMatcher */
452
453
def signature (unapp : Type , unappSym : Symbol , argLen : Int ): List [Type ] = {
453
454
def caseClass = unappSym.owner.linkedClass
455
+
454
456
lazy val caseAccessors = caseClass.caseAccessors.filter(_.is(Method ))
455
457
456
458
def isSyntheticScala2Unapply (sym : Symbol ) =
457
459
sym.is(SyntheticCase ) && sym.owner.is(Scala2x )
458
460
459
461
val mt @ MethodType (_) = unapp.widen
460
462
461
- if (isSyntheticScala2Unapply(unappSym) && caseAccessors.length == argLen)
462
- caseAccessors.map(_.info.asSeenFrom(mt.paramInfos.head, caseClass).widen)
463
- else if (mt.resultType.isRef(defn.BooleanClass ))
464
- List ()
465
- else {
466
- val isUnapplySeq = unappSym.name == nme.unapplySeq
467
- if (isProductMatch(mt.resultType, argLen) && ! isUnapplySeq) {
468
- productSelectors(mt.resultType).take(argLen)
469
- .map(_.info.asSeenFrom(mt.resultType, mt.resultType.classSymbol).widen)
470
- }
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]`
472
+
473
+ val sig =
474
+ if (isSyntheticScala2Unapply(unappSym) && caseAccessors.length == argLen)
475
+ caseAccessors.map(_.info.asSeenFrom(mt.paramInfos.head, caseClass).widen)
476
+ else if (mt.finalResultType.isRef(defn.BooleanClass ))
477
+ List ()
471
478
else {
472
- val resTp = mt.resultType.select(nme.get).resultType.widen
473
- if (isUnapplySeq) scalaListType.appliedTo(resTp.argTypes.head) :: Nil
474
- else if (argLen == 0 ) Nil
475
- else productSelectors(resTp).map(_.info.asSeenFrom(resTp, resTp.classSymbol).widen)
479
+ val isUnapplySeq = unappSym.name == nme.unapplySeq
480
+ if (isProductMatch(mt.finalResultType, argLen) && ! isUnapplySeq) {
481
+ productSelectors(mt.finalResultType).take(argLen)
482
+ .map(_.info.asSeenFrom(mt.finalResultType, mt.resultType.classSymbol).widen)
483
+ }
484
+ else {
485
+ val resTp = mt.finalResultType.select(nme.get).finalResultType.widen
486
+ if (isUnapplySeq) scalaListType.appliedTo(resTp.argTypes.head) :: Nil
487
+ else if (argLen == 0 ) Nil
488
+ else if (isProductMatch(resTp, argLen))
489
+ productSelectors(resTp).map(_.info.asSeenFrom(resTp, resTp.classSymbol).widen)
490
+ else resTp :: Nil
491
+ }
476
492
}
477
- }
493
+
494
+ debug.println(s " signature of ${unappSym.showFullName} ----> ${sig.map(_.show).mkString(" , " )}" )
495
+
496
+ sig
478
497
}
479
498
480
499
/** Decompose a type into subspaces -- assume the type can be decomposed */
@@ -705,14 +724,14 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
705
724
showType(tp) + params(tp).map(_ => " _" ).mkString(" (" , " , " , " )" )
706
725
else if (decomposed) " _: " + showType(tp)
707
726
else " _"
708
- case Prod (tp, fun, _ , params, _) =>
727
+ case Prod (tp, fun, sym , params, _) =>
709
728
if (ctx.definitions.isTupleType(tp))
710
729
" (" + params.map(doShow(_)).mkString(" , " ) + " )"
711
730
else if (tp.isRef(scalaConsType.symbol))
712
731
if (mergeList) params.map(doShow(_, mergeList)).mkString(" , " )
713
732
else params.map(doShow(_, true )).filter(_ != " Nil" ).mkString(" List(" , " , " , " )" )
714
733
else
715
- showType(tp ) + params.map(doShow(_)).mkString(" (" , " , " , " )" )
734
+ showType(sym.owner.typeRef ) + params.map(doShow(_)).mkString(" (" , " , " , " )" )
716
735
case Or (_) =>
717
736
throw new Exception (" incorrect flatten result " + s)
718
737
}
0 commit comments