@@ -275,12 +275,30 @@ object SpaceEngine {
275
275
/** Is the unapply irrefutable?
276
276
* @param unapp The unapply function reference
277
277
*/
278
- def isIrrefutableUnapply (unapp : tpd.Tree )(implicit ctx : Context ): Boolean = {
278
+ def isIrrefutableUnapply (unapp : tpd.Tree , patSize : Int )(implicit ctx : Context ): Boolean = {
279
279
val unappResult = unapp.tpe.widen.finalResultType
280
280
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
+ }
284
302
}
285
303
}
286
304
@@ -348,16 +366,15 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
348
366
else {
349
367
val (arity, elemTp, resultTp) = unapplySeqInfo(fun.tpe.widen.finalResultType, fun.sourcePos)
350
368
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 ))
352
370
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 ))
354
372
}
355
373
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, _) =>
358
377
Typ (erase(expr.tpe.stripAnnots), true )
359
- case Typed (pat, _) =>
360
- project(pat)
361
378
case This (_) =>
362
379
Typ (pat.tpe.stripAnnots, false )
363
380
case EmptyTree => // default rethrow clause of try/catch, check tests/patmat/try2.scala
@@ -678,19 +695,21 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
678
695
companion.findMember(nme.unapplySeq, NoPrefix , required = EmptyFlags , excluded = Synthetic ).exists
679
696
}
680
697
681
- def doShow (s : Space , mergeList : Boolean = false ): String = s match {
698
+ def doShow (s : Space , flattenList : Boolean = false ): String = s match {
682
699
case Empty => " "
683
700
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
685
704
case Typ (tp, decomposed) =>
686
705
val sym = tp.widen.classSymbol
687
706
688
707
if (ctx.definitions.isTupleType(tp))
689
708
params(tp).map(_ => " _" ).mkString(" (" , " , " , " )" )
690
709
else if (scalaListType.isRef(sym))
691
- if (mergeList ) " _: _*" else " _: List"
710
+ if (flattenList ) " _: _*" else " _: List"
692
711
else if (scalaConsType.isRef(sym))
693
- if (mergeList ) " _, _: _*" else " List(_, _: _*)"
712
+ if (flattenList ) " _, _: _*" else " List(_, _: _*)"
694
713
else if (tp.classSymbol.is(Sealed ) && tp.classSymbol.hasAnonymousChild)
695
714
" _: " + showType(tp) + " (anonymous)"
696
715
else if (tp.classSymbol.is(CaseClass ) && ! hasCustomUnapply(tp.classSymbol))
@@ -702,15 +721,18 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
702
721
if (ctx.definitions.isTupleType(tp))
703
722
" (" + params.map(doShow(_)).mkString(" , " ) + " )"
704
723
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
+ }
709
731
case Or (_) =>
710
732
throw new Exception (" incorrect flatten result " + s)
711
733
}
712
734
713
- flatten(s).map(doShow(_, false )).distinct.mkString(" , " )
735
+ flatten(s).map(doShow(_, flattenList = false )).distinct.mkString(" , " )
714
736
}
715
737
716
738
private def exhaustivityCheckable (sel : Tree ): Boolean = {
0 commit comments