Skip to content

Commit aae4019

Browse files
authored
Merge pull request #1623 from ShaneDelmore/1589_Missing_error_messages
#1589: Improve error message for WrongNumberOfArgs
2 parents 0ab1217 + aaae563 commit aae4019

File tree

5 files changed

+81
-8
lines changed

5 files changed

+81
-8
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1051,7 +1051,7 @@ object desugar {
10511051
elems foreach collect
10521052
case Alternative(trees) =>
10531053
for (tree <- trees; (vble, _) <- getVariables(tree))
1054-
ctx.error("illegal variable in pattern alternative", vble.pos)
1054+
ctx.error(IllegalVariableInPatternAlternative(), vble.pos)
10551055
case Annotated(arg, _) =>
10561056
collect(arg)
10571057
case InterpolatedString(_, segments) =>

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

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ package reporting
44
package diagnostic
55

66
import dotc.core._
7-
import Contexts.Context, Decorators._, Symbols._, Names._, Types._
7+
import Contexts.Context, Decorators._, Symbols._, Names._, NameOps._, Types._
88
import ast.untpd.{Modifiers, ModuleDef}
99
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

@@ -605,4 +606,76 @@ object messages {
605606
|${"func(bool => // do something...)"}
606607
|""".stripMargin
607608
}
609+
case class WrongNumberOfArgs(fntpe: Type, argKind: String, expectedArgs: List[TypeParamInfo], actual: List[untpd.Tree])(implicit ctx: Context)
610+
extends Message(22) {
611+
val kind = "Syntax"
612+
val expectedCount = expectedArgs.length
613+
val actualCount = actual.length
614+
val msgPrefix = if (actualCount > expectedCount) "Too many" else "Not enough"
615+
616+
//TODO add def simpleParamName to TypeParamInfo
617+
val expectedArgString = fntpe.widen.typeParams.map(_.paramName.unexpandedName.show).mkString("[", ", ", "]")
618+
619+
val actualArgString = actual.map(_.show).mkString("[", ", ", "]")
620+
621+
val prettyName = fntpe.termSymbol match {
622+
case NoSymbol => fntpe.show
623+
case symbol => symbol.showFullName
624+
}
625+
626+
val msg =
627+
hl"""|${NoColor(msgPrefix)} ${argKind} arguments for $prettyName$expectedArgString
628+
|expected: $expectedArgString
629+
|actual: $actualArgString""".stripMargin
630+
631+
val explanation = {
632+
val tooManyTypeParams =
633+
"""|val tuple2: (Int, String) = (1, "one")
634+
|val list: List[(Int, String)] = List(tuple2)""".stripMargin
635+
636+
if (actualCount > expectedCount)
637+
hl"""|You have supplied too many type parameters
638+
|
639+
|For example List takes a single type parameter (List[A])
640+
|If you need to hold more types in a list then you need to combine them
641+
|into another data type that can contain the number of types you need,
642+
|In this example one solution would be to use a Tuple:
643+
|
644+
|${tooManyTypeParams}""".stripMargin
645+
else
646+
hl"""|You have not supplied enough type parameters
647+
|If you specify one type parameter then you need to specify every type parameter.""".stripMargin
648+
}
649+
}
650+
651+
case class IllegalVariableInPatternAlternative()(implicit ctx: Context)
652+
extends Message(23) {
653+
val kind = "Syntax"
654+
655+
val msg = hl"""|Variables are not allowed in alternative patterns"""
656+
657+
val explanation = {
658+
val varInAlternative =
659+
"""|def g(pair: (Int,Int)): Int = pair match {
660+
| case (1, n) | (n, 1) => n
661+
| case _ => 0
662+
|}""".stripMargin
663+
664+
val fixedVarInAlternative =
665+
"""|def g(pair: (Int,Int)): Int = pair match {
666+
| case (1, n) => n
667+
| case (n, 1) => n
668+
| case _ => 0
669+
|}""".stripMargin
670+
671+
hl"""|Variables are not allowed within alternate pattern matches.
672+
|You can workaround this issue by adding additional cases for each alternative.
673+
|For example, the illegal function:
674+
|
675+
|$varInAlternative
676+
|could be implemented by moving each alternative into a separate case:
677+
|
678+
|$fixedVarInAlternative""".stripMargin
679+
}
680+
}
608681
}

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)