Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions compiler/src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -153,16 +153,18 @@ object Applications {

def tupleComponentTypes(tp: Type)(using Context): List[Type] =
tp.widenExpr.dealias.normalized match
case tp: AppliedType =>
if defn.isTupleClass(tp.tycon.typeSymbol) then
tp.args
else if tp.tycon.derivesFrom(defn.PairClass) then
val List(head, tail) = tp.args
head :: tupleComponentTypes(tail)
else
case defn.NamedTuple(_, vals) =>
tupleComponentTypes(vals)
case tp: AppliedType =>
if defn.isTupleClass(tp.tycon.typeSymbol) then
tp.args
else if tp.tycon.derivesFrom(defn.PairClass) then
val List(head, tail) = tp.args
head :: tupleComponentTypes(tail)
else
Nil
case _ =>
Nil
case _ =>
Nil

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

Expand Down
5 changes: 3 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1943,8 +1943,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
val firstFormal = protoFormals.head.loBound
if ptIsCorrectProduct(firstFormal, params) then
val isGenericTuple =
firstFormal.derivesFrom(defn.TupleClass)
&& !defn.isTupleClass(firstFormal.typeSymbol)
firstFormal.isNamedTupleType
|| (firstFormal.derivesFrom(defn.TupleClass)
&& !defn.isTupleClass(firstFormal.typeSymbol))
desugared = desugar.makeTupledFunction(params, fnBody, isGenericTuple)
else if protoFormals.length > 1 && params.length == 1 then
def isParamRef(scrut: untpd.Tree): Boolean = scrut match
Expand Down
12 changes: 12 additions & 0 deletions tests/run/i23440.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@main def Test: Unit =
List((42, "asdads")) match
case List((a, b)) => 1
List((a = 42, b = "asdads")) match
case List((a, b)) => 1
val tuple_list = List((42, "asdads"))
tuple_list.map((a, b) => println(s"$a $b"))
val named_tuple_list = List((a = 42, b = "asdads"))
named_tuple_list.foreach((a, b) => println(s"$a $b"))
named_tuple_list.foreach { case (a, b) => println(s"$a $b") }
val l = Seq.empty[(name: String, age: Int)]
l.map((name, i) => name + i)
Loading