From 6defc385ea2060e31d805dcd1b4bc4fd7e4c930a Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 7 Oct 2023 19:31:31 +0200 Subject: [PATCH] Add better explanation to error message Fixes #18657 --- .../dotty/tools/dotc/reporting/messages.scala | 18 ++++++++++++++---- .../src/dotty/tools/dotc/typer/Typer.scala | 2 +- tests/neg/i18657.check | 17 +++++++++++++++++ tests/neg/i18657.scala | 2 ++ 4 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 tests/neg/i18657.check create mode 100644 tests/neg/i18657.scala diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index 673e3dcc243d..3819a2bbe187 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -876,7 +876,7 @@ extends Message(PatternMatchExhaustivityID) { val pathes = List( ActionPatch( - srcPos = endPos, + srcPos = endPos, replacement = uncoveredCases.map(c => indent(s"case $c => ???", startColumn)) .mkString("\n", "\n", "") ), @@ -1806,10 +1806,20 @@ class NotAPath(tp: Type, usage: String)(using Context) extends TypeMsg(NotAPathI | - a reference to `this`, or | - a selection of an immutable path with an immutable value.""" -class WrongNumberOfParameters(expected: Int)(using Context) +class WrongNumberOfParameters(tree: untpd.Tree, foundCount: Int, pt: Type, expectedCount: Int)(using Context) extends SyntaxMsg(WrongNumberOfParametersID) { - def msg(using Context) = s"Wrong number of parameters, expected: $expected" - def explain(using Context) = "" + def msg(using Context) = s"Wrong number of parameters, expected: $expectedCount" + def explain(using Context) = + val ending = if foundCount == 1 then "" else "s" + i"""The function literal + | + | $tree + | + |has $foundCount parameter$ending. But the expected type + | + | $pt + | + |requires a function with $expectedCount parameters.""" } class DuplicatePrivateProtectedQualifier()(using Context) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 431e863f85d2..500d7e8bde9a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1574,7 +1574,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer /** Returns the type and whether the parameter is erased */ def protoFormal(i: Int): (Type, Boolean) = if (protoFormals.length == params.length) (protoFormals(i), isDefinedErased(i)) - else (errorType(WrongNumberOfParameters(protoFormals.length), tree.srcPos), false) + else (errorType(WrongNumberOfParameters(tree, params.length, pt, protoFormals.length), tree.srcPos), false) /** Is `formal` a product type which is elementwise compatible with `params`? */ def ptIsCorrectProduct(formal: Type) = diff --git a/tests/neg/i18657.check b/tests/neg/i18657.check new file mode 100644 index 000000000000..a873239bfe9d --- /dev/null +++ b/tests/neg/i18657.check @@ -0,0 +1,17 @@ +-- [E086] Syntax Error: tests/neg/i18657.scala:2:27 -------------------------------------------------------------------- +2 |val f: (Int, Int) => Int = Integer.compare(_ + 1, _) // error + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | Wrong number of parameters, expected: 2 + |--------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The function literal + | + | _$2 => Integer.compare(_$1 => _$1 + 1, _$2) + | + | has 1 parameter. But the expected type + | + | (Int, Int) => Int + | + | requires a function with 2 parameters. + --------------------------------------------------------------------------------------------------------------------- diff --git a/tests/neg/i18657.scala b/tests/neg/i18657.scala new file mode 100644 index 000000000000..393982a5ea14 --- /dev/null +++ b/tests/neg/i18657.scala @@ -0,0 +1,2 @@ +//> using options -explain +val f: (Int, Int) => Int = Integer.compare(_ + 1, _) // error