@@ -2774,6 +2774,20 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
2774
2774
if ! isFullyDefined(pt, ForceDegree .all) then
2775
2775
return errorTree(tree, em " expected type of $tree is not fully defined " )
2776
2776
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
+
2777
2791
body1 match {
2778
2792
case UnApply (fn, Nil , arg :: Nil )
2779
2793
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
2799
2813
body1.isInstanceOf [RefTree ] && ! isWildcardArg(body1)
2800
2814
|| body1.isInstanceOf [Literal ]
2801
2815
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
2804
2817
else if isWildcardStarArg(body1)
2805
2818
|| pt == defn.ImplicitScrutineeTypeRef
2806
2819
|| body1.tpe <:< pt // There is some strange interaction with gadt matching.
0 commit comments