Skip to content

Commit 952b866

Browse files
Backport "Skip bypassing unapply for scala 2 case classes to allow for single-element named tuple in unapply" to 3.7.3 (#23645)
Backports #23603 to the 3.7.3-RC1. PR submitted by the release tooling. [skip ci]
2 parents d8f2102 + 0fa203f commit 952b866

File tree

2 files changed

+15
-6
lines changed

2 files changed

+15
-6
lines changed

compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,13 @@ object PatternMatcher {
343343
receiver.ensureConforms(defn.NonEmptyTupleTypeRef), // If scrutinee is a named tuple, cast to underlying tuple
344344
Literal(Constant(i)))
345345

346-
if (isSyntheticScala2Unapply(unapp.symbol) && caseAccessors.length == args.length)
346+
def getOfGetMatch(gm: Tree) = gm.select(nme.get, _.info.isParameterless)
347+
// Disable Scala2Unapply optimization if the argument is a named argument for a single-element named tuple to
348+
// enable selecting the field. See i23131.scala for test cases.
349+
val wasUnaryNamedTupleSelectArgForNamedTuple =
350+
args.length == 1 && args.head.removeAttachment(FirstTransform.WasNamedArg).isDefined &&
351+
isGetMatch(unappType) && getOfGetMatch(unapp).tpe.widenDealias.isNamedTupleType
352+
if (isSyntheticScala2Unapply(unapp.symbol) && caseAccessors.length == args.length && !wasUnaryNamedTupleSelectArgForNamedTuple)
347353
def tupleSel(sym: Symbol) =
348354
// If scrutinee is a named tuple, cast to underlying tuple, so that we can
349355
// continue to select with _1, _2, ...
@@ -376,7 +382,7 @@ object PatternMatcher {
376382
else {
377383
assert(isGetMatch(unappType))
378384
val argsPlan = {
379-
val get = ref(unappResult).select(nme.get, _.info.isParameterless)
385+
val get = getOfGetMatch(ref(unappResult))
380386
val arity = productArity(get.tpe.stripNamedTuple, unapp.srcPos)
381387
if (isUnapplySeq)
382388
letAbstract(get) { getResult =>
@@ -386,17 +392,14 @@ object PatternMatcher {
386392
}
387393
else
388394
letAbstract(get) { getResult =>
389-
def isUnaryNamedTupleSelectArg(arg: Tree) =
390-
get.tpe.widenDealias.isNamedTupleType
391-
&& arg.removeAttachment(FirstTransform.WasNamedArg).isDefined
392395
// Special case: Normally, we pull out the argument wholesale if
393396
// there is only one. But if the argument is a named argument for
394397
// a single-element named tuple, we have to select the field instead.
395398
// NamedArg trees are eliminated in FirstTransform but for named arguments
396399
// of patterns we add a WasNamedArg attachment, which is used to guide the
397400
// logic here. See i22900.scala for test cases.
398401
val selectors = args match
399-
case arg :: Nil if !isUnaryNamedTupleSelectArg(arg) =>
402+
case arg :: Nil if !wasUnaryNamedTupleSelectArgForNamedTuple =>
400403
ref(getResult) :: Nil
401404
case _ =>
402405
productSelectors(getResult.info).map(ref(getResult).select(_))

tests/run/i23131.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import scala.NamedTuple
2+
@main
3+
def Test =
4+
Some((name = "Bob")) match {
5+
case Some(name = a) => println(a)
6+
}

0 commit comments

Comments
 (0)