Skip to content

Commit d684972

Browse files
committed
Fix type in tupleApp by indexing the generic tuple components
1 parent 203c94d commit d684972

File tree

2 files changed

+9
-4
lines changed

2 files changed

+9
-4
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -328,11 +328,11 @@ object PatternMatcher {
328328
def isSyntheticScala2Unapply(sym: Symbol) =
329329
sym.isAllOf(SyntheticCase) && sym.owner.is(Scala2x)
330330

331-
def tupleApp(i: Int, receiver: Tree) = // manually inlining the call to NonEmptyTuple#apply, because it's an inline method
331+
def tupleApp(tuple: Type, i: Int, receiver: Tree) = // manually inlining the call to NonEmptyTuple#apply, because it's an inline method
332332
ref(defn.RuntimeTuplesModule)
333333
.select(defn.RuntimeTuples_apply)
334334
.appliedTo(receiver, Literal(Constant(i)))
335-
.cast(scrutinee.info.memberInfo(caseAccessors(i)).widen)
335+
.cast(indexTupleType(tuple, i))
336336

337337
if (isSyntheticScala2Unapply(unapp.symbol) && caseAccessors.length == args.length)
338338
def tupleSel(sym: Symbol) = ref(scrutinee).select(sym)
@@ -342,7 +342,7 @@ object PatternMatcher {
342342
case tp => tp
343343
!defn.isTupleNType(tp)
344344
}
345-
val components = if isGenericTuple then caseAccessors.indices.toList.map(tupleApp(_, ref(scrutinee))) else caseAccessors.map(tupleSel)
345+
val components = if isGenericTuple then caseAccessors.indices.toList.map(tupleApp(unapp.tpe.finalResultType, _, ref(scrutinee))) else caseAccessors.map(tupleSel)
346346
matchArgsPlan(components, args, onSuccess)
347347
else if (unapp.tpe <:< (defn.BooleanType))
348348
TestPlan(GuardTest, unapp, unapp.span, onSuccess)
@@ -362,7 +362,7 @@ object PatternMatcher {
362362
unapplySeqPlan(unappResult, args)
363363
}
364364
else if unappResult.info <:< defn.NonEmptyTupleTypeRef then
365-
val components = (0 until foldApplyTupleType(unappResult.denot.info).length).toList.map(tupleApp(_, ref(unappResult)))
365+
val components = (0 until foldApplyTupleType(unappResult.denot.info).length).toList.map(tupleApp(unappResult.info, _, ref(unappResult)))
366366
matchArgsPlan(components, args, onSuccess)
367367
else {
368368
assert(isGetMatch(unapp.tpe))

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,11 @@ object Applications {
207207
end tupleFold
208208
tupleFold(Nil, tp).reverse
209209

210+
/** The component type of a generic tuple at index `idx`. For example, `indexTupleType(A *: B *: EmptyTuple, 1) = B`. */
211+
def indexTupleType(tp: Type, idx: Int)(using Context): Type = tp.widen match
212+
case AppliedType(tycon, List(l, r)) if tycon.typeSymbol == defn.PairClass => if idx == 0 then l else indexTupleType(r, idx - 1)
213+
case t => NoType
214+
210215
def wrapDefs(defs: mutable.ListBuffer[Tree], tree: Tree)(using Context): Tree =
211216
if (defs != null && defs.nonEmpty) tpd.Block(defs.toList, tree) else tree
212217

0 commit comments

Comments
 (0)