Skip to content

Commit ef085d5

Browse files
committed
Improve error message for WrongNumberOfArgs
1 parent 56731e4 commit ef085d5

File tree

4 files changed

+41
-6
lines changed

4 files changed

+41
-6
lines changed

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import util.{SourceFile, NoSource}
1010
import util.{SourcePosition, NoSourcePosition}
1111
import config.Settings.Setting
1212
import interfaces.Diagnostic.{ERROR, WARNING, INFO}
13+
import dotty.tools.dotc.ast.tpd
1314
import printing.Highlighting._
1415
import printing.Formatting
1516

@@ -512,4 +513,38 @@ object messages {
512513
|}""".stripMargin
513514
}
514515

516+
case class WrongNumberOfArgs(fntpe: Type, argKind: String, expectedArgs: List[TypeParamInfo], actual: List[untpd.Tree])(implicit ctx: Context)
517+
extends Message(18) {
518+
val kind = "Syntax"
519+
val expectedCount = expectedArgs.length
520+
val actualCount = actual.length
521+
val msgPrefix = if (actualCount > expectedCount) "Too many" else "Not enough"
522+
523+
val expectedArgString = (fntpe.widen match {
524+
case pt: MethodOrPoly => pt //ensure we return a type that will have useful typeParms
525+
case _ => fntpe
526+
}).typeParams.map(_.paramName.show.split("\\$").last).mkString("[", ", ", "]")
527+
528+
val actualArgString = actual.map(_.show.split("\\.").last).mkString("[", ", ", "]")
529+
530+
val msg =
531+
hl"""|$msgPrefix ${argKind} arguments for $fntpe
532+
|expected: $expectedArgString
533+
|actual: $actualArgString""".stripMargin
534+
535+
val explanation = {
536+
if (actualCount > expectedCount)
537+
hl"""|You have supplied too many type parameters
538+
|
539+
|For example List takes a single type parameter (List[A])
540+
| If you need to hold more types in a list then you need to combine them
541+
| into another data type that can contain the number of types you need,
542+
| In this example one solution would be to use a Tuple:
543+
| val tuple2: Tuple2[Int, String = (1, "one)
544+
| List[(Int, String)] = List(tuple2)""".stripMargin
545+
else
546+
hl"""|You have not supplied enough type parameters
547+
| If you specify one type parameter then you need to specify every type parameter.""".stripMargin
548+
}
549+
}
515550
}

src/dotty/tools/dotc/typer/ErrorReporting.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ object ErrorReporting {
4949
errorMsg(ex.show, ctx)
5050
}
5151

52-
def wrongNumberOfArgs(fntpe: Type, kind: String, expected: Int, pos: Position)(implicit ctx: Context) =
53-
errorType(em"wrong number of ${kind}arguments for $fntpe, expected: $expected", pos)
52+
def wrongNumberOfArgs(fntpe: Type, kind: String, expectedArgs: List[TypeParamInfo], actual: List[untpd.Tree], pos: Position)(implicit ctx: Context) =
53+
errorType(WrongNumberOfArgs(fntpe, kind, expectedArgs, actual)(ctx), pos)
5454

5555
class Errors(implicit ctx: Context) {
5656

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ trait TypeAssigner {
314314
val ownType = fn.tpe.widen match {
315315
case fntpe @ MethodType(_, ptypes) =>
316316
if (sameLength(ptypes, args) || ctx.phase.prev.relaxedTyping) fntpe.instantiate(args.tpes)
317-
else wrongNumberOfArgs(fn.tpe, "", ptypes.length, tree.pos)
317+
else wrongNumberOfArgs(fn.tpe, "", fntpe.typeParams, args, tree.pos)
318318
case t =>
319319
errorType(i"${err.exprStr(fn)} does not take parameters", tree.pos)
320320
}
@@ -369,7 +369,7 @@ trait TypeAssigner {
369369
else {
370370
val argTypes = args.tpes
371371
if (sameLength(argTypes, paramNames) || ctx.phase.prev.relaxedTyping) pt.instantiate(argTypes)
372-
else wrongNumberOfArgs(fn.tpe, "type ", pt.paramNames.length, tree.pos)
372+
else wrongNumberOfArgs(fn.tpe, "type", pt.typeParams, args, tree.pos)
373373
}
374374
case _ =>
375375
errorType(i"${err.exprStr(fn)} does not take type parameters", tree.pos)
@@ -451,7 +451,7 @@ trait TypeAssigner {
451451
val ownType =
452452
if (hasNamedArg(args)) (tycon.tpe /: args)(refineNamed)
453453
else if (sameLength(tparams, args)) tycon.tpe.appliedTo(args.tpes)
454-
else wrongNumberOfArgs(tycon.tpe, "type ", tparams.length, tree.pos)
454+
else wrongNumberOfArgs(tycon.tpe, "type", tparams, args, tree.pos)
455455
tree.withType(ownType)
456456
}
457457

src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
10351035
if (hasNamedArg(args)) typedNamedArgs(args)
10361036
else {
10371037
if (args.length != tparams.length) {
1038-
wrongNumberOfArgs(tpt1.tpe, "type ", tparams.length, tree.pos)
1038+
wrongNumberOfArgs(tpt1.tpe, "type", tparams, args, tree.pos)
10391039
args = args.take(tparams.length)
10401040
}
10411041
def typedArg(arg: untpd.Tree, tparam: TypeParamInfo) = {

0 commit comments

Comments
 (0)