Skip to content

Commit adc6c3f

Browse files
Backport "Fix parameter untupling for named tuples (#23440)" to 3.7.4 (#24225)
Backports #24152 to the 3.7.4. PR submitted by the release tooling. [skip ci]
2 parents ee8c214 + 1f54dd1 commit adc6c3f

File tree

3 files changed

+27
-12
lines changed

3 files changed

+27
-12
lines changed

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

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -140,16 +140,18 @@ object Applications {
140140

141141
def tupleComponentTypes(tp: Type)(using Context): List[Type] =
142142
tp.widenExpr.dealias.normalized match
143-
case tp: AppliedType =>
144-
if defn.isTupleClass(tp.tycon.typeSymbol) then
145-
tp.args
146-
else if tp.tycon.derivesFrom(defn.PairClass) then
147-
val List(head, tail) = tp.args
148-
head :: tupleComponentTypes(tail)
149-
else
143+
case defn.NamedTuple(_, vals) =>
144+
tupleComponentTypes(vals)
145+
case tp: AppliedType =>
146+
if defn.isTupleClass(tp.tycon.typeSymbol) then
147+
tp.args
148+
else if tp.tycon.derivesFrom(defn.PairClass) then
149+
val List(head, tail) = tp.args
150+
head :: tupleComponentTypes(tail)
151+
else
152+
Nil
153+
case _ =>
150154
Nil
151-
case _ =>
152-
Nil
153155

154156
def productArity(tp: Type, errorPos: SrcPos = NoSourcePosition)(using Context): Int =
155157
if (defn.isProductSubType(tp)) productSelectorTypes(tp, errorPos).size else -1
@@ -2558,7 +2560,7 @@ trait Applications extends Compatibility {
25582560
/** Is `formal` a product type which is elementwise compatible with `params`? */
25592561
def ptIsCorrectProduct(formal: Type, params: List[untpd.ValDef])(using Context): Boolean =
25602562
isFullyDefined(formal, ForceDegree.flipBottom)
2561-
&& defn.isProductSubType(formal)
2563+
&& (defn.isProductSubType(formal) || formal.isNamedTupleType)
25622564
&& tupleComponentTypes(formal).corresponds(params): (argType, param) =>
25632565
param.tpt.isEmpty || argType.widenExpr <:< typedAheadType(param.tpt).tpe
25642566

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1933,8 +1933,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
19331933
val firstFormal = protoFormals.head.loBound
19341934
if ptIsCorrectProduct(firstFormal, params) then
19351935
val isGenericTuple =
1936-
firstFormal.derivesFrom(defn.TupleClass)
1937-
&& !defn.isTupleClass(firstFormal.typeSymbol)
1936+
firstFormal.isNamedTupleType
1937+
|| (firstFormal.derivesFrom(defn.TupleClass)
1938+
&& !defn.isTupleClass(firstFormal.typeSymbol))
19381939
desugared = desugar.makeTupledFunction(params, fnBody, isGenericTuple)
19391940
else if protoFormals.length > 1 && params.length == 1 then
19401941
def isParamRef(scrut: untpd.Tree): Boolean = scrut match

tests/run/i23440.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
@main def Test: Unit =
2+
List((42, "asdads")) match
3+
case List((a, b)) => 1
4+
List((a = 42, b = "asdads")) match
5+
case List((a, b)) => 1
6+
val tuple_list = List((42, "asdads"))
7+
tuple_list.map((a, b) => println(s"$a $b"))
8+
val named_tuple_list = List((a = 42, b = "asdads"))
9+
named_tuple_list.foreach((a, b) => println(s"$a $b"))
10+
named_tuple_list.foreach { case (a, b) => println(s"$a $b") }
11+
val l = Seq.empty[(name: String, age: Int)]
12+
l.map((name, i) => name + i)

0 commit comments

Comments
 (0)