Skip to content

Commit 0b97399

Browse files
committed
Named patterns for case clasees should be validated
1 parent 91063dd commit 0b97399

File tree

4 files changed

+44
-10
lines changed

4 files changed

+44
-10
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1654,7 +1654,7 @@ object desugar {
16541654
AppliedTypeTree(
16551655
TypeTree(defn.throwsAlias.typeRef).withSpan(op.span), tpt :: excepts :: Nil)
16561656

1657-
private def checkWellFormedTupleElems(elems: List[Tree])(using Context): List[Tree] =
1657+
def checkWellFormedTupleElems(elems: List[Tree])(using Context): List[Tree] =
16581658
val seen = mutable.Set[Name]()
16591659
for case arg @ NamedArg(name, _) <- elems do
16601660
if seen.contains(name) then

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -199,20 +199,22 @@ object Applications {
199199
else tp :: Nil
200200

201201
private def productUnapplySelectors(tp: Type)(using Context): Option[List[Type]] =
202+
val validatedTupleElements = desugar.checkWellFormedTupleElems(args)
203+
202204
if defn.isProductSubType(tp) then
203-
tryAdaptPatternArgs(args, tp) match
205+
tryAdaptPatternArgs(validatedTupleElements, tp) match
204206
case Some(args1) if isProductMatch(tp, args1.length, pos) =>
205207
args = args1
206208
Some(productSelectorTypes(tp, pos))
207209
case _ => None
208-
else tp.widen.normalized.dealias match
209-
case tp @ defn.NamedTuple(_, tt) =>
210-
tryAdaptPatternArgs(args, tp) match
211-
case Some(args1) =>
212-
args = args1
213-
tt.tupleElementTypes
214-
case _ => None
215-
case _ => None
210+
else tp.widen.normalized.dealias match
211+
case tp @ defn.NamedTuple(_, tt) =>
212+
tryAdaptPatternArgs(validatedTupleElements, tp) match
213+
case Some(args1) =>
214+
args = args1
215+
tt.tupleElementTypes
216+
case _ => None
217+
case _ => None
216218

217219
/** The computed argument types which will be the scutinees of the sub-patterns. */
218220
val argTypes: List[Type] =

tests/neg/named-tuples-4.check

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
-- Error: tests/neg/named-tuples-4.scala:10:35 -------------------------------------------------------------------------
2+
10 | case PersonCaseClass(name = n, age) => () // error
3+
| ^^^
4+
| Illegal combination of named and unnamed tuple elements
5+
-- Error: tests/neg/named-tuples-4.scala:11:31 -------------------------------------------------------------------------
6+
11 | case PersonCaseClass(name, age = a) => () // error
7+
| ^^^^^^^
8+
| Illegal combination of named and unnamed tuple elements
9+
-- Error: tests/neg/named-tuples-4.scala:15:20 -------------------------------------------------------------------------
10+
15 | case (name = n, age) => () // error
11+
| ^^^
12+
| Illegal combination of named and unnamed tuple elements
13+
-- Error: tests/neg/named-tuples-4.scala:16:16 -------------------------------------------------------------------------
14+
16 | case (name, age = a) => () // error
15+
| ^^^^^^^
16+
| Illegal combination of named and unnamed tuple elements

tests/neg/named-tuples-4.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import language.experimental.namedTuples
2+
import scala.annotation.experimental
3+
4+
@experimental object Test:
5+
6+
case class PersonCaseClass(name: String, age: Int)
7+
8+
val personCaseClass = PersonCaseClass("Bob", 33)
9+
personCaseClass match
10+
case PersonCaseClass(name = n, age) => () // error
11+
case PersonCaseClass(name, age = a) => () // error
12+
13+
val person = (name = "Bob", age = 33): (name: String, age: Int)
14+
person match
15+
case (name = n, age) => () // error
16+
case (name, age = a) => () // error

0 commit comments

Comments
 (0)