@@ -275,12 +275,30 @@ object SpaceEngine {
275275 /** Is the unapply irrefutable?
276276 * @param unapp The unapply function reference
277277 */
278- def isIrrefutableUnapply (unapp : tpd.Tree )(implicit ctx : Context ): Boolean = {
278+ def isIrrefutableUnapply (unapp : tpd.Tree , patSize : Int )(implicit ctx : Context ): Boolean = {
279279 val unappResult = unapp.tpe.widen.finalResultType
280280 unappResult.isRef(defn.SomeClass ) ||
281- unappResult =:= ConstantType (Constant (true )) ||
282- (unapp.symbol.is(Synthetic ) && unapp.symbol.owner.linkedClass.is(Case )) ||
283- productArity(unappResult) > 0
281+ unappResult <:< ConstantType (Constant (true )) ||
282+ (unapp.symbol.is(Synthetic ) && unapp.symbol.owner.linkedClass.is(Case )) || // scala2 compatibility
283+ (patSize != - 1 && productArity(unappResult) == patSize) || {
284+ val isEmptyTp = extractorMemberType(unappResult, nme.isEmpty, unapp.sourcePos)
285+ isEmptyTp <:< ConstantType (Constant (false ))
286+ }
287+ }
288+
289+ /** Is the unapplySeq irrefutable?
290+ * @param unapp The unapplySeq function reference
291+ */
292+ def isIrrefutableUnapplySeq (unapp : tpd.Tree , patSize : Int )(implicit ctx : Context ): Boolean = {
293+ val unappResult = unapp.tpe.widen.finalResultType
294+ unappResult.isRef(defn.SomeClass ) ||
295+ (unapp.symbol.is(Synthetic ) && unapp.symbol.owner.linkedClass.is(Case )) || // scala2 compatibility
296+ unapplySeqTypeElemTp(unappResult).exists ||
297+ isProductSeqMatch(unappResult, patSize) ||
298+ {
299+ val isEmptyTp = extractorMemberType(unappResult, nme.isEmpty, unapp.sourcePos)
300+ isEmptyTp <:< ConstantType (Constant (false ))
301+ }
284302 }
285303}
286304
@@ -348,16 +366,15 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
348366 else {
349367 val (arity, elemTp, resultTp) = unapplySeqInfo(fun.tpe.widen.finalResultType, fun.sourcePos)
350368 if (elemTp.exists)
351- Prod (erase(pat.tpe.stripAnnots), fun.tpe, fun.symbol, projectSeq(pats) :: Nil , isIrrefutableUnapply (fun))
369+ Prod (erase(pat.tpe.stripAnnots), fun.tpe, fun.symbol, projectSeq(pats) :: Nil , isIrrefutableUnapplySeq (fun, pats.size ))
352370 else
353- Prod (erase(pat.tpe.stripAnnots), fun.tpe, fun.symbol, pats.take(arity - 1 ).map(project) :+ projectSeq(pats.drop(arity - 1 )),isIrrefutableUnapply (fun))
371+ Prod (erase(pat.tpe.stripAnnots), fun.tpe, fun.symbol, pats.take(arity - 1 ).map(project) :+ projectSeq(pats.drop(arity - 1 )), isIrrefutableUnapplySeq (fun, pats.size ))
354372 }
355373 else
356- Prod (erase(pat.tpe.stripAnnots), erase(fun.tpe), fun.symbol, pats.map(project), isIrrefutableUnapply(fun))
357- case Typed (expr @ Ident (nme.WILDCARD ), tpt) =>
374+ Prod (erase(pat.tpe.stripAnnots), erase(fun.tpe), fun.symbol, pats.map(project), isIrrefutableUnapply(fun, pats.length))
375+ case Typed (pat @ UnApply (_, _, _), _) => project(pat)
376+ case Typed (expr, _) =>
358377 Typ (erase(expr.tpe.stripAnnots), true )
359- case Typed (pat, _) =>
360- project(pat)
361378 case This (_) =>
362379 Typ (pat.tpe.stripAnnots, false )
363380 case EmptyTree => // default rethrow clause of try/catch, check tests/patmat/try2.scala
@@ -678,19 +695,21 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
678695 companion.findMember(nme.unapplySeq, NoPrefix , required = EmptyFlags , excluded = Synthetic ).exists
679696 }
680697
681- def doShow (s : Space , mergeList : Boolean = false ): String = s match {
698+ def doShow (s : Space , flattenList : Boolean = false ): String = s match {
682699 case Empty => " "
683700 case Typ (c : ConstantType , _) => " " + c.value.value
684- case Typ (tp : TermRef , _) => tp.symbol.showName
701+ case Typ (tp : TermRef , _) =>
702+ if (flattenList && tp <:< scalaNilType) " "
703+ else tp.symbol.showName
685704 case Typ (tp, decomposed) =>
686705 val sym = tp.widen.classSymbol
687706
688707 if (ctx.definitions.isTupleType(tp))
689708 params(tp).map(_ => " _" ).mkString(" (" , " , " , " )" )
690709 else if (scalaListType.isRef(sym))
691- if (mergeList ) " _: _*" else " _: List"
710+ if (flattenList ) " _: _*" else " _: List"
692711 else if (scalaConsType.isRef(sym))
693- if (mergeList ) " _, _: _*" else " List(_, _: _*)"
712+ if (flattenList ) " _, _: _*" else " List(_, _: _*)"
694713 else if (tp.classSymbol.is(Sealed ) && tp.classSymbol.hasAnonymousChild)
695714 " _: " + showType(tp) + " (anonymous)"
696715 else if (tp.classSymbol.is(CaseClass ) && ! hasCustomUnapply(tp.classSymbol))
@@ -702,15 +721,18 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
702721 if (ctx.definitions.isTupleType(tp))
703722 " (" + params.map(doShow(_)).mkString(" , " ) + " )"
704723 else if (tp.isRef(scalaConsType.symbol))
705- if (mergeList) params.map(doShow(_, mergeList)).mkString(" , " )
706- else params.map(doShow(_, true )).filter(_ != " Nil" ).mkString(" List(" , " , " , " )" )
707- else
708- showType(sym.owner.typeRef) + params.map(doShow(_)).mkString(" (" , " , " , " )" )
724+ if (flattenList) params.map(doShow(_, flattenList)).mkString(" , " )
725+ else params.map(doShow(_, flattenList = true )).filter(! _.isEmpty).mkString(" List(" , " , " , " )" )
726+ else {
727+ val isUnapplySeq = sym.name.eq(nme.unapplySeq)
728+ val paramsStr = params.map(doShow(_, flattenList = isUnapplySeq)).mkString(" (" , " , " , " )" )
729+ showType(sym.owner.typeRef) + paramsStr
730+ }
709731 case Or (_) =>
710732 throw new Exception (" incorrect flatten result " + s)
711733 }
712734
713- flatten(s).map(doShow(_, false )).distinct.mkString(" , " )
735+ flatten(s).map(doShow(_, flattenList = false )).distinct.mkString(" , " )
714736 }
715737
716738 private def exhaustivityCheckable (sel : Tree ): Boolean = {
0 commit comments