Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nicer error messages on argument list / tuple mismatch #668

Open
jiribenes opened this issue Nov 5, 2024 · 1 comment
Open

Nicer error messages on argument list / tuple mismatch #668

jiribenes opened this issue Nov 5, 2024 · 1 comment
Labels
errormessage feature New feature or request

Comments

@jiribenes
Copy link
Contributor

jiribenes commented Nov 5, 2024

There are two general situations where the users confuse argument lists with tuples.
We could potentially special-case the messages here:

1. Want a tuple, got an argument list

def foo { f: (Int, Int) => Bool }: Unit = <>

def main() = foo { case (x, y) => true }
//                 ~~~~~~~~~~~~~~~~~~~
// Wrong number of value arguments, given 1, but function expects 2.
// ~> Did you mean `(x, y) => true`?

2. Want two arguments, got a tuple

def bar { f: ((Int, Int)) => Bool }: Unit = <>

def main() = bar { (x, y) => true }
//                 ~~~~~~~~~~~~~~~
// Wrong number of value arguments, given 2, but function expects 1.
// ~> Did you mean `case (x, y) => true`

Of course, there's an issue with baz((1, 2)) vs baz(1, 2) as well :)

@jiribenes jiribenes added feature New feature or request errormessage labels Nov 5, 2024
@jiribenes
Copy link
Contributor Author

jiribenes commented Nov 8, 2024

A truly rudimentary and extraordinarily hacky fix for the two explicit cases presented above is:

diff --git i/effekt/shared/src/main/scala/effekt/Typer.scala w/effekt/shared/src/main/scala/effekt/Typer.scala
index 48849181..04eadc5e 100644
--- i/effekt/shared/src/main/scala/effekt/Typer.scala
+++ w/effekt/shared/src/main/scala/effekt/Typer.scala
@@ -893,8 +893,24 @@ object Typer extends Phase[NameResolved, Typechecked] {
       if (tps.size != tparams.size)
         Context.abort(s"Wrong number of type arguments, given ${tparams.size}, but function expects ${tps.size}.")
 
-      if (vps.size != vparams.size)
+      if (vps.size != vparams.size) {
+        vps match
+          case (tuptpe @ ValueTypeApp(TypeConstructor.Record(name, tupparams, _), _)) :: Nil
+            if name.name.startsWith("Tuple") && tupparams.size == vparams.size =>
+              Context.abort(
+                pretty"Wrong number of value arguments, given ${vparams.size}, but function expects a single tuple argument of type ${tuptpe}.\nHint: Try using `case (x, y) => ...` instead of `(x, y) => ...`.")
+          case _ => ()
+
+        vparams match {
+          // A *very* bad heuristic: we translate `case ... =>` into a match and bind it to a `__tmpRes`.
+          case source.ValueParam(source.IdDef("__tmpRes"), None) :: Nil =>
+            Context.abort(
+              pretty"Wrong number of value arguments, given a lambda `case`, but function expects ${vps.size} arguments.\nHint: Try using `(x, y) => ...` instead of `case (x, y) => ...`.")
+          case _ => ()
+        }
+
         Context.abort(s"Wrong number of value arguments, given ${vparams.size}, but function expects ${vps.size}.")
+      }
 
       if (bps.size != bparams.size)
         Context.abort(s"Wrong number of block arguments, given ${bparams.size}, but function expects ${bps.size}.")

... resulting in the following error messages:
Screenshot 2024-11-08 at 13 56 48

Screenshot 2024-11-08 at 13 57 00

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
errormessage feature New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant