Skip to content

Commit cd0f546

Browse files
committed
Refactoring: keep unapplySeq
1 parent da39571 commit cd0f546

File tree

3 files changed

+56
-49
lines changed

3 files changed

+56
-49
lines changed

compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,7 @@ object PatternMatcher {
286286
matchElemsPlan(getResult, args, exact = true, onSuccess)
287287
}
288288

289-
/** Plan for matching the sequence in `getResult` against sequence elements
290-
* and a possible last varargs argument `args`.
289+
/** Plan for matching the sequence in `getResult`
291290
*
292291
* `getResult` is a product, where the last element is a sequence of elements.
293292
*/
@@ -322,7 +321,7 @@ object PatternMatcher {
322321
.map(ref(unappResult).select(_))
323322
matchArgsPlan(selectors, args, onSuccess)
324323
}
325-
else if (isProductSeqMatch(unapp.tpe.widen, args.length, unapp.sourcePos) && !isUnapplySeq) {
324+
else if (isProductSeqMatch(unapp.tpe.widen, args.length, unapp.sourcePos) && isUnapplySeq) {
326325
val arity = productArity(unapp.tpe.widen, unapp.sourcePos)
327326
unapplyProductSeqPlan(unappResult, args, arity)
328327
}
@@ -338,15 +337,13 @@ object PatternMatcher {
338337
}
339338
else
340339
letAbstract(get) { getResult =>
341-
if (args.tail.isEmpty) // Single pattern takes precedence
340+
if (args.tail.isEmpty)
342341
matchArgsPlan(ref(getResult) :: Nil, args, onSuccess)
343342
else if (isProductMatch(get.tpe, args.length, unapp.sourcePos)) {
344343
val sels = productSelectors(get.tpe).map(ref(getResult).select(_))
345344
matchArgsPlan(sels, args, onSuccess)
346345
}
347-
else if (isProductSeqMatch(get.tpe, args.length, unapp.sourcePos))
348-
unapplyProductSeqPlan(getResult, args, arity)
349-
else { // name-based
346+
else {
350347
val sels = productSelectors(get.tpe).map(ref(getResult).select(_))
351348
matchArgsPlan(sels, args, onSuccess)
352349
}

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -335,25 +335,26 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
335335
case Bind(_, pat) => project(pat)
336336
case SeqLiteral(pats, _) => projectSeq(pats)
337337
case UnApply(fun, _, pats) =>
338-
if (fun.symbol.owner == scalaSeqFactoryClass && fun.symbol.name == nme.unapplySeq)
339-
projectSeq(pats)
340-
else {
341-
var tp = fun.tpe.widen.finalResultType
342-
var arity = productArity(tp, fun.sourcePos)
343-
if (arity <= 0) {
344-
tp = fun.tpe.widen.finalResultType.select(nme.get).finalResultType.widen
345-
if (pats.length == 1)
346-
return Prod(erase(pat.tpe.stripAnnots), fun.tpe, fun.symbol, pats.map(project), irrefutable(fun))
347-
arity = productSelectorTypes(tp, fun.sourcePos).size
348-
}
338+
if (fun.symbol.name == nme.unapplySeq)
339+
if (fun.symbol.owner == scalaSeqFactoryClass)
340+
projectSeq(pats)
341+
else {
342+
val resultTp = fun.tpe.widen.finalResultType
343+
var elemTp = unapplySeqTypeElemTp(resultTp)
344+
var arity = productArity(resultTp, fun.sourcePos)
345+
if (!elemTp.exists && arity <= 0) {
346+
val resultTp = fun.tpe.widen.finalResultType.select(nme.get).finalResultType
347+
elemTp = unapplySeqTypeElemTp(resultTp.widen)
348+
arity = productSelectorTypes(resultTp, fun.sourcePos).size
349+
}
349350

350-
if (arity > 0 && arity != pats.length)
351-
Prod(erase(pat.tpe.stripAnnots), fun.tpe, fun.symbol, pats.take(arity - 1).map(project) :+ projectSeq(pats.drop(arity - 1)), irrefutable(fun))
352-
else if (arity <= 0 && unapplySeqTypeElemTp(tp).exists)
353-
Prod(erase(pat.tpe.stripAnnots), fun.tpe, fun.symbol, projectSeq(pats) :: Nil, irrefutable(fun))
354-
else
355-
Prod(erase(pat.tpe.stripAnnots), fun.tpe, fun.symbol, pats.map(project), irrefutable(fun))
356-
}
351+
if (elemTp.exists)
352+
Prod(erase(pat.tpe.stripAnnots), fun.tpe, fun.symbol, projectSeq(pats) :: Nil, irrefutable(fun))
353+
else
354+
Prod(erase(pat.tpe.stripAnnots), fun.tpe, fun.symbol, pats.take(arity - 1).map(project) :+ projectSeq(pats.drop(arity - 1)), irrefutable(fun))
355+
}
356+
else
357+
Prod(erase(pat.tpe.stripAnnots), fun.tpe, fun.symbol, pats.map(project), irrefutable(fun))
357358
case Typed(pat @ UnApply(_, _, _), _) => project(pat)
358359
case Typed(expr, tpt) =>
359360
Typ(erase(expr.tpe.stripAnnots), true)
@@ -436,27 +437,34 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
436437
List()
437438
else {
438439
val isUnapplySeq = unappSym.name == nme.unapplySeq
439-
val arity = productArity(mt.finalResultType, unappSym.sourcePos)
440-
if (arity > 0 && !isUnapplySeq) {
441-
if (arity != argLen) {
442-
val sels = productSeqSelectors(mt.finalResultType, arity, unappSym.sourcePos)
440+
441+
if (isUnapplySeq) {
442+
var resultTp = mt.finalResultType
443+
var elemTp = unapplySeqTypeElemTp(resultTp)
444+
var arity = productArity(resultTp, unappSym.sourcePos)
445+
if (!elemTp.exists && arity <= 0) {
446+
resultTp = mt.finalResultType.select(nme.get).finalResultType
447+
elemTp = unapplySeqTypeElemTp(resultTp.widen)
448+
arity = productSelectorTypes(resultTp, unappSym.sourcePos).size
449+
}
450+
451+
if (elemTp.exists) scalaListType.appliedTo(elemTp) :: Nil
452+
else {
453+
val sels = productSeqSelectors(resultTp, arity, unappSym.sourcePos)
443454
sels.init :+ scalaListType.appliedTo(sels.last)
444455
}
445-
else
446-
productSelectors(mt.finalResultType)
447-
.map(_.info.asSeenFrom(mt.finalResultType, mt.resultType.classSymbol).widenExpr)
448456
}
449457
else {
450-
val resTp = mt.finalResultType.select(nme.get).finalResultType.widen
451-
val arity = productArity(resTp, unappSym.sourcePos)
452-
if (isUnapplySeq && arity < 0) scalaListType.appliedTo(resTp.argTypes.head) :: Nil
453-
else if (argLen == 1) resTp :: Nil
454-
else if (arity > 0 && arity != argLen) {
455-
val sels = productSeqSelectors(resTp, arity, unappSym.sourcePos)
456-
sels.init :+ scalaListType.appliedTo(sels.last)
458+
val arity = productArity(mt.finalResultType, unappSym.sourcePos)
459+
if (arity > 0)
460+
productSelectors(mt.finalResultType)
461+
.map(_.info.asSeenFrom(mt.finalResultType, mt.resultType.classSymbol).widenExpr)
462+
else {
463+
val resTp = mt.finalResultType.select(nme.get).finalResultType.widen
464+
val arity = productArity(resTp, unappSym.sourcePos)
465+
if (argLen == 1) resTp :: Nil
466+
else productSelectors(resTp).map(_.info.asSeenFrom(resTp, resTp.classSymbol).widenExpr)
457467
}
458-
else
459-
productSelectors(resTp).map(_.info.asSeenFrom(resTp, resTp.classSymbol).widenExpr)
460468
}
461469
}
462470

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -155,21 +155,23 @@ object Applications {
155155
Nil
156156
}
157157

158-
if (unapplyName == nme.unapplySeq) { // && ctx.scala2Mode
159-
if (isGetMatch(unapplyResult, pos)) {
160-
val elemTp = unapplySeqTypeElemTp(getTp)
161-
if (elemTp.exists) args.map(Function.const(elemTp))
162-
else if (isProductSeqMatch(getTp, args.length, pos)) productSeqSelectors(getTp, args.length, pos)
158+
def unapplySeq(tp: Type)(fallback: => List[Type]): List[Type] = {
159+
val elemTp = unapplySeqTypeElemTp(tp)
160+
if (elemTp.exists) args.map(Function.const(elemTp))
161+
else if (isProductSeqMatch(tp, args.length, pos)) productSeqSelectors(tp, args.length, pos)
162+
else fallback
163+
}
164+
165+
if (unapplyName == nme.unapplySeq) {
166+
unapplySeq(unapplyResult) {
167+
if (isGetMatch(unapplyResult, pos)) unapplySeq(getTp)(fail)
163168
else fail
164169
}
165-
else fail
166170
}
167171
else {
168172
assert(unapplyName == nme.unapply)
169173
if (isProductMatch(unapplyResult, args.length, pos))
170174
productSelectorTypes(unapplyResult, pos)
171-
else if (isProductSeqMatch(unapplyResult, args.length, pos))
172-
productSeqSelectors(unapplyResult, args.length, pos)
173175
else if (isGetMatch(unapplyResult, pos))
174176
getUnapplySelectors(getTp, args, pos)
175177
else if (unapplyResult.widenSingleton isRef defn.BooleanClass)

0 commit comments

Comments
 (0)