diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index 481b3651793c..461569388cbb 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -359,10 +359,9 @@ object PatternMatcher { * * `getResult` is a product, where the last element is a sequence of elements. */ - def unapplyProductSeqPlan(getResult: Symbol, args: List[Tree], arity: Int): Plan = { + def unapplyProductSeqPlan(selectors: List[Tree], args: List[Tree]): Plan = { + val arity = selectors.length assert(arity <= args.size + 1) - val selectors = productSelectors(getResult.info).map(ref(getResult).select(_)) - val matchSeq = letAbstract(selectors.last) { seqResult => unapplySeqPlan(seqResult, args.drop(arity - 1)) @@ -415,8 +414,8 @@ object PatternMatcher { else if isUnapplySeq && unapplySeqTypeElemTp(unappType.finalResultType).exists then unapplySeqPlan(unappResult, args) else if isUnapplySeq && isProductSeqMatch(unappType, args.length, unapp.srcPos) then - val arity = productArity(unappType, unapp.srcPos) - unapplyProductSeqPlan(unappResult, args, arity) + val selectors = productSelectors(unappType).map(ref(unappResult).select(_)) + unapplyProductSeqPlan(selectors, args) else if unappResult.info <:< defn.NonEmptyTupleTypeRef then val components = (0 until unappResult.denot.info.tupleElementTypes.getOrElse(Nil).length) @@ -426,12 +425,20 @@ object PatternMatcher { assert(isGetMatch(unappType)) val argsPlan = { val get = getOfGetMatch(ref(unappResult)) - val arity = productArity(get.tpe.stripNamedTuple, unapp.srcPos) if (isUnapplySeq) letAbstract(get) { getResult => - if unapplySeqTypeElemTp(get.tpe).exists - then unapplySeqPlan(getResult, args) - else unapplyProductSeqPlan(getResult, args, arity) + if unapplySeqTypeElemTp(get.tpe).exists then + unapplySeqPlan(getResult, args) + else if isGenericTuple(getResult.info) then + val elemTypes = getResult.info.tupleElementTypes.getOrElse(Nil) + val selectors = elemTypes.zipWithIndex.map { (tp, i) => + tupleApp(i, ref(getResult)).cast(tp) + } + unapplyProductSeqPlan(selectors, args) + else { + val selectors = productSelectors(getResult.info).map(ref(getResult).select(_)) + unapplyProductSeqPlan(selectors, args) + } } else letAbstract(get) { getResult => diff --git a/tests/pos/i25663.scala b/tests/pos/i25663.scala new file mode 100644 index 000000000000..fbbddb8e62ee --- /dev/null +++ b/tests/pos/i25663.scala @@ -0,0 +1,5 @@ +object Foo: + def unapplySeq(f: Int): Option[String *: Seq[Int] *: EmptyTuple] = ??? + +def foo(f: Int) = f match + case Foo(name, ns*) => ???