Skip to content

Commit 04a970b

Browse files
committed
Fix parameter untupling for named tuples (#23440)
1 parent 5b02216 commit 04a970b

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
@@ -153,16 +153,18 @@ object Applications {
153153

154154
def tupleComponentTypes(tp: Type)(using Context): List[Type] =
155155
tp.widenExpr.dealias.normalized match
156-
case tp: AppliedType =>
157-
if defn.isTupleClass(tp.tycon.typeSymbol) then
158-
tp.args
159-
else if tp.tycon.derivesFrom(defn.PairClass) then
160-
val List(head, tail) = tp.args
161-
head :: tupleComponentTypes(tail)
162-
else
156+
case defn.NamedTuple(_, vals) =>
157+
tupleComponentTypes(vals)
158+
case tp: AppliedType =>
159+
if defn.isTupleClass(tp.tycon.typeSymbol) then
160+
tp.args
161+
else if tp.tycon.derivesFrom(defn.PairClass) then
162+
val List(head, tail) = tp.args
163+
head :: tupleComponentTypes(tail)
164+
else
165+
Nil
166+
case _ =>
163167
Nil
164-
case _ =>
165-
Nil
166168

167169
def productArity(tp: Type, errorPos: SrcPos = NoSourcePosition)(using Context): Int =
168170
if (defn.isProductSubType(tp)) productSelectorTypes(tp, errorPos).size else -1
@@ -2585,7 +2587,7 @@ trait Applications extends Compatibility {
25852587
/** Is `formal` a product type which is elementwise compatible with `params`? */
25862588
def ptIsCorrectProduct(formal: Type, params: List[untpd.ValDef])(using Context): Boolean =
25872589
isFullyDefined(formal, ForceDegree.flipBottom)
2588-
&& defn.isProductSubType(formal)
2590+
&& (defn.isProductSubType(formal) || formal.isNamedTupleType)
25892591
&& tupleComponentTypes(formal).corresponds(params): (argType, param) =>
25902592
param.tpt.isEmpty || argType.widenExpr <:< typedAheadType(param.tpt).tpe
25912593

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1943,8 +1943,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
19431943
val firstFormal = protoFormals.head.loBound
19441944
if ptIsCorrectProduct(firstFormal, params) then
19451945
val isGenericTuple =
1946-
firstFormal.derivesFrom(defn.TupleClass)
1947-
&& !defn.isTupleClass(firstFormal.typeSymbol)
1946+
firstFormal.isNamedTupleType
1947+
|| (firstFormal.derivesFrom(defn.TupleClass)
1948+
&& !defn.isTupleClass(firstFormal.typeSymbol))
19481949
desugared = desugar.makeTupledFunction(params, fnBody, isGenericTuple)
19491950
else if protoFormals.length > 1 && params.length == 1 then
19501951
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)