Skip to content

Commit cbb481c

Browse files
DSouzaMallanrenucci
authored andcommitted
Add error message for named type parameter errors (#3419)
1 parent a549dd1 commit cbb481c

File tree

4 files changed

+63
-3
lines changed

4 files changed

+63
-3
lines changed

compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,9 @@ public enum ErrorMessageID {
107107
TailrecNotApplicableID,
108108
FailureToEliminateExistentialID,
109109
OnlyFunctionsCanBeFollowedByUnderscoreID,
110-
MissingEmptyArgumentListID
110+
MissingEmptyArgumentListID,
111+
DuplicateNamedTypeParameterID,
112+
UndefinedNamedTypeParameterID
111113
;
112114

113115
public int errorNumber() {

compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala

+14
Original file line numberDiff line numberDiff line change
@@ -1865,4 +1865,18 @@ object messages {
18651865
|Excluded from this rule are methods that are defined in Java or that override methods defined in Java."""
18661866
}
18671867
}
1868+
1869+
case class DuplicateNamedTypeParameter(name: Name)(implicit ctx: Context)
1870+
extends Message(DuplicateNamedTypeParameterID) {
1871+
val kind = "Syntax"
1872+
val msg = hl"Type parameter $name was defined multiple times."
1873+
val explanation = ""
1874+
}
1875+
1876+
case class UndefinedNamedTypeParameter(undefinedName: Name, definedNames: List[Name])(implicit ctx: Context)
1877+
extends Message(UndefinedNamedTypeParameterID) {
1878+
val kind = "Syntax"
1879+
val msg = hl"Type parameter $undefinedName is undefined. Expected one of ${definedNames.map(_.show).mkString(", ")}."
1880+
val explanation = ""
1881+
}
18681882
}

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -371,9 +371,9 @@ trait TypeAssigner {
371371
val namedArgMap = new mutable.HashMap[Name, Type]
372372
for (NamedArg(name, arg) <- args)
373373
if (namedArgMap.contains(name))
374-
ctx.error("duplicate name", arg.pos)
374+
ctx.error(DuplicateNamedTypeParameter(name), arg.pos)
375375
else if (!paramNames.contains(name))
376-
ctx.error(s"undefined parameter name, required: ${paramNames.mkString(" or ")}", arg.pos)
376+
ctx.error(UndefinedNamedTypeParameter(name, paramNames), arg.pos)
377377
else
378378
namedArgMap(name) = preCheckKind(arg, paramBoundsByName(name.asTypeName)).tpe
379379

compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala

+44
Original file line numberDiff line numberDiff line change
@@ -1088,4 +1088,48 @@ class ErrorMessagesTests extends ErrorMessagesTest {
10881088
val MissingEmptyArgumentList(method) :: Nil = messages
10891089
assertEquals("method greet", method.show)
10901090
}
1091+
1092+
@Test def duplicateNamedTypeParameter =
1093+
checkMessagesAfter("frontend") {
1094+
"""
1095+
|object Test {
1096+
| def f[A, B]() = ???
1097+
| f[A=Any, A=Any]()
1098+
| f[B=Any, B=Any]()
1099+
|}
1100+
|
1101+
""".stripMargin
1102+
}
1103+
.expect { (ictx, messages) =>
1104+
implicit val ctx: Context = ictx
1105+
1106+
assertMessageCount(2, messages)
1107+
val DuplicateNamedTypeParameter(n2) :: DuplicateNamedTypeParameter(n1) :: Nil = messages
1108+
assertEquals("A", n1.show)
1109+
assertEquals("B", n2.show)
1110+
}
1111+
1112+
@Test def undefinedNamedTypeParameter =
1113+
checkMessagesAfter("frontend") {
1114+
"""
1115+
|object Test {
1116+
| def f[A, B]() = ???
1117+
| f[A=Any, C=Any]()
1118+
| f[C=Any, B=Any]()
1119+
|}
1120+
|
1121+
""".stripMargin
1122+
}
1123+
.expect { (ictx, messages) =>
1124+
implicit val ctx: Context = ictx
1125+
1126+
assertMessageCount(2, messages)
1127+
val UndefinedNamedTypeParameter(n2, l2) :: UndefinedNamedTypeParameter(n1, l1) :: Nil = messages
1128+
val tpParams = List("A", "B")
1129+
assertEquals("C", n1.show)
1130+
assertEquals(tpParams, l1.map(_.show))
1131+
assertEquals("C", n2.show)
1132+
assertEquals(tpParams, l2.map(_.show))
1133+
1134+
}
10911135
}

0 commit comments

Comments
 (0)