@@ -108,7 +108,7 @@ trait SpaceLogic {
108
108
def decompose (tp : Type ): List [Typ ]
109
109
110
110
/** Whether the extractor covers the given type */
111
- def covers (unapp : TermRef , scrutineeTp : Type ): Boolean
111
+ def covers (unapp : TermRef , scrutineeTp : Type , argLen : Int ): Boolean
112
112
113
113
/** Display space in string format */
114
114
def show (sp : Space ): String
@@ -186,7 +186,7 @@ trait SpaceLogic {
186
186
isSubType(tp1, tp2)
187
187
case (Typ (tp1, _), Prod (tp2, fun, ss)) =>
188
188
isSubType(tp1, tp2)
189
- && covers(fun, tp1)
189
+ && covers(fun, tp1, ss.length )
190
190
&& isSubspace(Prod (tp2, fun, signature(fun, tp2, ss.length).map(Typ (_, false ))), b)
191
191
case (Prod (_, fun1, ss1), Prod (_, fun2, ss2)) =>
192
192
isSameUnapply(fun1, fun2) && ss1.zip(ss2).forall((isSubspace _).tupled)
@@ -240,7 +240,7 @@ trait SpaceLogic {
240
240
else a
241
241
case (Typ (tp1, _), Prod (tp2, fun, ss)) =>
242
242
// rationale: every instance of `tp1` is covered by `tp2(_)`
243
- if isSubType(tp1, tp2) && covers(fun, tp1) then
243
+ if isSubType(tp1, tp2) && covers(fun, tp1, ss.length ) then
244
244
minus(Prod (tp1, fun, signature(fun, tp1, ss.length).map(Typ (_, false ))), b)
245
245
else if canDecompose(tp1) then
246
246
tryDecompose1(tp1)
@@ -262,6 +262,7 @@ trait SpaceLogic {
262
262
a
263
263
case (Prod (tp1, fun1, ss1), Prod (tp2, fun2, ss2)) =>
264
264
if (! isSameUnapply(fun1, fun2)) return a
265
+ if (fun1.symbol.name == nme.unapply && ss1.length != ss2.length) return a
265
266
266
267
val range = (0 until ss1.size).toList
267
268
val cache = Array .fill[Space ](ss2.length)(null )
@@ -288,13 +289,13 @@ object SpaceEngine {
288
289
/** Is the unapply or unapplySeq irrefutable?
289
290
* @param unapp The unapply function reference
290
291
*/
291
- def isIrrefutable (unapp : TermRef )(using Context ): Boolean = {
292
+ def isIrrefutable (unapp : TermRef , argLen : Int )(using Context ): Boolean = {
292
293
val unappResult = unapp.widen.finalResultType
293
294
unappResult.isRef(defn.SomeClass )
294
295
|| unappResult <:< ConstantType (Constant (true )) // only for unapply
295
296
|| (unapp.symbol.is(Synthetic ) && unapp.symbol.owner.linkedClass.is(Case )) // scala2 compatibility
296
297
|| unapplySeqTypeElemTp(unappResult).exists // only for unapplySeq
297
- || productArity (unappResult) > 0
298
+ || isProductMatch (unappResult, argLen)
298
299
|| {
299
300
val isEmptyTp = extractorMemberType(unappResult, nme.isEmpty, NoSourcePosition )
300
301
isEmptyTp <:< ConstantType (Constant (false ))
@@ -304,10 +305,10 @@ object SpaceEngine {
304
305
/** Is the unapply or unapplySeq irrefutable?
305
306
* @param unapp The unapply function tree
306
307
*/
307
- def isIrrefutable (unapp : tpd.Tree )(using Context ): Boolean = {
308
+ def isIrrefutable (unapp : tpd.Tree , argLen : Int )(using Context ): Boolean = {
308
309
val fun1 = tpd.funPart(unapp)
309
310
val funRef = fun1.tpe.asInstanceOf [TermRef ]
310
- isIrrefutable(funRef)
311
+ isIrrefutable(funRef, argLen )
311
312
}
312
313
}
313
314
@@ -606,8 +607,8 @@ class SpaceEngine(using Context) extends SpaceLogic {
606
607
}
607
608
608
609
/** Whether the extractor covers the given type */
609
- def covers (unapp : TermRef , scrutineeTp : Type ): Boolean =
610
- SpaceEngine .isIrrefutable(unapp) || unapp.symbol == defn.TypeTest_unapply && {
610
+ def covers (unapp : TermRef , scrutineeTp : Type , argLen : Int ): Boolean =
611
+ SpaceEngine .isIrrefutable(unapp, argLen ) || unapp.symbol == defn.TypeTest_unapply && {
611
612
val AppliedType (_, _ :: tp :: Nil ) = unapp.prefix.widen.dealias
612
613
scrutineeTp <:< tp
613
614
}
0 commit comments