Skip to content

Commit 808ba77

Browse files
committed
Report member that doesn't support named arguments
1 parent a278df9 commit 808ba77

File tree

3 files changed

+36
-32
lines changed

3 files changed

+36
-32
lines changed

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

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,29 +1393,31 @@ trait Applications extends Compatibility {
13931393
.memberDenots(typeNameFilter, (name, buf) => if (name.toString == "Names") buf += typeInfoOfGetMethod.member(name).asSingleDenotation)
13941394
.headOption
13951395

1396+
val positionOfStringNames: Map[String, Int] =
1397+
if names.isDefined then
1398+
// TODO: Don't use regular expression to deconstruct tuples
1399+
val reg = "\"([^\"]+)\"".r
1400+
reg.findAllMatchIn(names.get.showDcl)
1401+
.map(_.group(1))
1402+
.zipWithIndex
1403+
.toMap
1404+
// TODO: The test should actually be: is unapplyFn generated by the compiler because we have a case class?
1405+
else if unapplyFn.tpe.widen.paramInfoss.head.head.typeSymbol.is(CaseClass) then
1406+
unapplyFn.tpe.widen.paramInfoss.head.head.fields.map(_.name.toString).zipWithIndex.toMap
1407+
else
1408+
report.error(i"'${qual}' doesn't support named patterns", qual)
1409+
Map.empty
1410+
13961411
val positionOfName: PartialFunction[Name, Int] =
1397-
if names.isDefined then
1398-
// TODO: Don't use regular expression to deconstruct tuples
1399-
val reg = "\"([^\"]+)\"".r
1400-
reg.findAllMatchIn(names.get.showDcl)
1401-
.map(_.group(1))
1402-
.zipWithIndex
1403-
.toMap
1404-
// TODO: The test should actually be: is unapplyFn generated by the compiler because we have a case class?
1405-
else if unapplyFn.tpe.widen.paramInfoss.head.head.typeSymbol.is(CaseClass) then
1406-
unapplyFn.tpe.widen.paramInfoss.head.head.fields.map(_.name.toString).zipWithIndex.toMap
1407-
else
1408-
// TODO: Report member
1409-
report.error("Doesn't support named patterns")
1410-
Map.empty
14111412
// TODO: Is is necessary to convert names to strings?
1412-
.compose{ case name: Name => name.show }
1413+
positionOfStringNames.compose(_.show)
14131414

14141415
val namedArgs = bunchedArgs
14151416
.flatMap {
14161417
case pattern @ NamedArg(positionOfName(_), _) => Seq(pattern)
14171418
case pattern @ NamedArg(unknownName, _) =>
1418-
report.error(s"'${unknownName.show}' is unknown", pattern)
1419+
if (positionOfStringNames.nonEmpty)
1420+
report.error(s"'${unknownName.show}' is unknown", pattern)
14191421
Seq.empty
14201422
case unnamedArgument =>
14211423
report.error("Only named arguments allowed here", unnamedArgument)
Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1-
-- Error: tests/neg/negNamedPatternMatching.scala:21:20 ----------------------------------------------------------------
2-
21 | case User(names = "Tom", city = city) => ??? // error
1+
-- Error: tests/neg/negNamedPatternMatching.scala:18:20 ----------------------------------------------------------------
2+
18 | case User(names = "Tom", city = city) => ??? // error
33
| ^^^^^
44
| 'names' is unknown
5-
-- Error: tests/neg/negNamedPatternMatching.scala:22:22 ----------------------------------------------------------------
6-
22 | case User(city = _, 10) => null // error
5+
-- Error: tests/neg/negNamedPatternMatching.scala:19:22 ----------------------------------------------------------------
6+
19 | case User(city = _, 10) => null // error
77
| ^^
88
| Only named arguments allowed here
9-
-- Error: tests/neg/negNamedPatternMatching.scala:25:11 ----------------------------------------------------------------
10-
25 | name = "Tom 2", // error
9+
-- Error: tests/neg/negNamedPatternMatching.scala:20:18 ----------------------------------------------------------------
10+
20 | case User(age = Age(years = 10)) => null // error
11+
| ^^^
12+
| 'patterns.Age' doesn't support named patterns
13+
-- Error: tests/neg/negNamedPatternMatching.scala:23:11 ----------------------------------------------------------------
14+
23 | name = "Tom 2", // error
1115
| ^^^^^^^
1216
| 'name' was already used before
13-
-- Error: tests/neg/negNamedPatternMatching.scala:26:11 ----------------------------------------------------------------
14-
26 | name = "Tom 3" // error
17+
-- Error: tests/neg/negNamedPatternMatching.scala:24:11 ----------------------------------------------------------------
18+
24 | name = "Tom 3" // error
1519
| ^^^^^^^
1620
| 'name' was already used before

tests/neg/negNamedPatternMatching.scala

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
package patterns
22

3-
class Age(val hidden: Int)
3+
type Age = Age.Age
44

55
object Age:
6-
def apply(years: Int): Age = new Age(years)
6+
opaque type Age = Int
77

8-
// TODO: Describe alternative encoding with tagged tuples
9-
def unapply(age: Age): Some[Int & { type Names = "years" *: EmptyTuple }] =
10-
Some(age.hidden.asInstanceOf)
8+
def apply(years: Int): Age = years
119

12-
object StringExample:
13-
def unapply(str: String): Option[(Char, Char) & { type Names = "first" *: "last" *: EmptyTuple }] =
14-
Some((str.head, str.last)).asInstanceOf
10+
def unapply(age: Age): Some[Int] =
11+
Some(age)
1512

1613
case class User(name: String, age: Age, city: String)
1714

@@ -20,6 +17,7 @@ val user = User(name = "Anna", age = Age(10), city = "Berlin")
2017
val annasCity = user match
2118
case User(names = "Tom", city = city) => ??? // error
2219
case User(city = _, 10) => null // error
20+
case User(age = Age(years = 10)) => null // error
2321
case User(
2422
name = "Tom",
2523
name = "Tom 2", // error

0 commit comments

Comments
 (0)