@@ -2774,6 +2774,20 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
27742774 if ! isFullyDefined(pt, ForceDegree .all) then
27752775 return errorTree(tree, em " expected type of $tree is not fully defined " )
27762776 val body1 = typed(tree.body, pt)
2777+
2778+ // When we pattern match a named tuple, both the named tuple pattern and the
2779+ // regular tuple pattern are desugared to a regular tuple unapply.
2780+ // If the pattern (body) is a named tuple pattern, we give the binding
2781+ // a named tuple type using pt; otherwise we give it the regular tuple type.
2782+ // For example, in `case x @ (a = 1, b = 2)`, the type of `x` will be `(a: Int, b: Int)`;
2783+ // in `case x @ (a, b)`, the type of `x` will be `(Int, Int)`.
2784+ def isNamedTuplePattern =
2785+ ctx.mode.is(Mode .Pattern )
2786+ && pt.dealias.isNamedTupleType
2787+ && tree.body.match
2788+ case untpd.Tuple ((_ : NamedArg ) :: _) => true
2789+ case _ => false
2790+
27772791 body1 match {
27782792 case UnApply (fn, Nil , arg :: Nil )
27792793 if fn.symbol.exists && (fn.symbol.owner.derivesFrom(defn.TypeTestClass ) || fn.symbol.owner == defn.ClassTagClass ) && ! body1.tpe.isError =>
@@ -2799,8 +2813,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
27992813 body1.isInstanceOf [RefTree ] && ! isWildcardArg(body1)
28002814 || body1.isInstanceOf [Literal ]
28012815 val symTp =
2802- if isStableIdentifierOrLiteral || pt.dealias.isNamedTupleType then pt
2803- // need to combine tuple element types with expected named type
2816+ if isStableIdentifierOrLiteral || isNamedTuplePattern then pt
28042817 else if isWildcardStarArg(body1)
28052818 || pt == defn.ImplicitScrutineeTypeRef
28062819 || body1.tpe <:< pt // There is some strange interaction with gadt matching.
0 commit comments