File tree Expand file tree Collapse file tree 5 files changed +69
-4
lines changed
compiler/src/dotty/tools/dotc Expand file tree Collapse file tree 5 files changed +69
-4
lines changed Original file line number Diff line number Diff line change @@ -19,10 +19,14 @@ import NameKinds.OuterSelectName
1919import StdNames .*
2020import config .Feature
2121import inlines .Inlines .inInlineMethod
22+ import util .Property
2223
2324object FirstTransform {
2425 val name : String = " firstTransform"
2526 val description : String = " some transformations to put trees into a canonical form"
27+
28+ /** Attachment key for named argument patterns */
29+ val WasNamedArg : Property .StickyKey [Unit ] = Property .StickyKey ()
2630}
2731
2832/** The first tree transform
@@ -38,6 +42,7 @@ object FirstTransform {
3842 */
3943class FirstTransform extends MiniPhase with SymTransformer { thisPhase =>
4044 import ast .tpd .*
45+ import FirstTransform .*
4146
4247 override def phaseName : String = FirstTransform .name
4348
@@ -156,7 +161,13 @@ class FirstTransform extends MiniPhase with SymTransformer { thisPhase =>
156161
157162 override def transformOther (tree : Tree )(using Context ): Tree = tree match {
158163 case tree : Export => EmptyTree
159- case tree : NamedArg => transformAllDeep(tree.arg)
164+ case tree : NamedArg =>
165+ val res = transformAllDeep(tree.arg)
166+ if ctx.mode.is(Mode .Pattern ) then
167+ // Need to keep NamedArg status for pattern matcher to work correctly when faced
168+ // with single-element named tuples.
169+ res.pushAttachment(WasNamedArg , ())
170+ res
160171 case tree => if (tree.isType) toTypeTree(tree) else tree
161172 }
162173
Original file line number Diff line number Diff line change @@ -386,9 +386,20 @@ object PatternMatcher {
386386 }
387387 else
388388 letAbstract(get) { getResult =>
389- val selectors =
390- if (args.tail.isEmpty) ref(getResult) :: Nil
391- else productSelectors(getResult.info).map(ref(getResult).select(_))
389+ def isUnaryNamedTupleSelectArg (arg : Tree ) =
390+ get.tpe.widenDealias.isNamedTupleType
391+ && arg.removeAttachment(FirstTransform .WasNamedArg ).isDefined
392+ // Special case: Normally, we pull out the argument wholesale if
393+ // there is only one. But if the argument is a named argument for
394+ // a single-element named tuple, we have to select the field instead.
395+ // NamedArg trees are eliminated in FirstTransform but for named arguments
396+ // of patterns we add a WasNamedArg attachment, which is used to guide the
397+ // logic here. See i22900.scala for test cases.
398+ val selectors = args match
399+ case arg :: Nil if ! isUnaryNamedTupleSelectArg(arg) =>
400+ ref(getResult) :: Nil
401+ case _ =>
402+ productSelectors(getResult.info).map(ref(getResult).select(_))
392403 matchArgsPlan(selectors, args, onSuccess)
393404 }
394405 }
Original file line number Diff line number Diff line change @@ -1040,6 +1040,8 @@ trait Checking {
10401040 pats.forall(recur(_, pt))
10411041 case Typed (arg, tpt) =>
10421042 check(pat, pt) && recur(arg, pt)
1043+ case NamedArg (name, pat) =>
1044+ recur(pat, pt)
10431045 case Ident (nme.WILDCARD ) =>
10441046 true
10451047 case pat : QuotePattern =>
Original file line number Diff line number Diff line change 1+ object NameBaseExtractor {
2+ def unapply (x : Int ): Some [(someName : Int )] = Some ((someName = x + 3 ))
3+ }
4+ object NameBaseExtractor2 {
5+ def unapply (x : Int ): Some [(someName : Int , age : Int )] = Some ((someName = x + 3 , age = x + 4 ))
6+ }
7+ @ main
8+ def Test =
9+ val x1 = 3 match
10+ case NameBaseExtractor (someName = x) => x
11+ println(x1)
12+ val NameBaseExtractor (someName = x2) = 3
13+ println(x2)
14+ val NameBaseExtractor ((someName = x3)) = 3
15+ println(x3)
16+
17+ val NameBaseExtractor2 (someName = x4, age = x5) = 3
18+ println(x4)
19+ println(x5)
20+
21+ val NameBaseExtractor2 ((someName = x6, age = x7)) = 3
22+ println(x6)
23+ println(x7)
24+
25+ val NameBaseExtractor (y1) = 3
26+ println(y1)
Original file line number Diff line number Diff line change 1+ case class C (someName : Int )
2+
3+ object NameBaseExtractor3 {
4+ def unapply (x : Int ): Some [C ] = Some (C (someName = x + 3 ))
5+ }
6+
7+ @ main
8+ def Test = {
9+ val C (someName = xx) = C (3 )
10+ println(xx)
11+ val NameBaseExtractor3 (C (someName = x)) = 3
12+ println(x)
13+ C (3 ) match
14+ case C (someName = xx) => println(xx)
15+ }
You can’t perform that action at this time.
0 commit comments