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

Improve message for missing parameter type if no method takes a function #11517

Open
som-snytt opened this issue May 5, 2019 · 3 comments

Comments

Projects
None yet
3 participants
@som-snytt
Copy link

commented May 5, 2019

As requested by tpolecat:

scala 2.13.0-RC1> "abc".indexOf(_ + 1)
                                ^
                  error: missing parameter type for expanded function ((<x$1: error>) => x$1.$plus(1))

scala 2.13.0-RC1> "abc".indexOf((x: Int) => x + 1)
java.lang.StackOverflowError
  at scala.collection.immutable.WrappedString.indexOf(WrappedString.scala:75)
  at scala.collection.SeqOps.indexOf(Seq.scala:381)
  at scala.collection.SeqOps.indexOf$(Seq.scala:381)
  at scala.collection.immutable.WrappedString.indexOf(WrappedString.scala:75)
  at scala.collection.SeqOps.indexOf(Seq.scala:381)
  at scala.collection.SeqOps.indexOf$(Seq.scala:381)

Oops, that's not what I meant to demonstrate. It looks like a runtime issue with WrappedString, not a compiler bug. I think tpolecat actually used substring. This is the dance he'd like avoid, which is especially confusing for beginners but annoying to all:

scala 2.13.0-RC1> "abc".substring(_ + 1)
                                  ^
                  error: missing parameter type for expanded function ((<x$1: error>) => x$1.$plus(1))

scala 2.13.0-RC1> "abc".substring((x: Int) => x + 1)
                                           ^
                  error: type mismatch;
                   found   : Int => Int
                   required: Int

Maybe for indexOf, I meant indexWhere.

scala 2.13.0-RC1> "abc".index(_ == 'b')
                        ^
                  error: value index is not a member of String
                  did you mean indexOf?

scala 2.13.0-RC1> "abc".indexOf(_ == 'b')
                                ^
                  error: missing parameter type for expanded function ((<x$1: error>) => x$1.$eq$eq('b'))

It would be amazing if both messages recommended indexWhere, as a method that has a similar name and takes a function.

I do read the amazing scaladocs, but this would also be amazing.

Worth adding that -Xlint adds:

scala 2.13.0-RC1> def f = "abc".indexOf((x: Char) => x == 'b')
                                ^
                  warning: a type was inferred to be `Any`; this may indicate a programming error.
f: Int

With improved inference in the face of overloads, maybe messaging can be improved despite overloads.

@tpolecat

This comment has been minimized.

Copy link

commented May 5, 2019

To be clear, what I to avoid is the situation where Scala says "missing parameter type" for a function in a position where no function type can possibly work, because when this happens you have to make the function typecheck first, before the compiler will tell you what the expected type was. I realize it's a special case but it's a common special case. "I expected a woozle but I found a function literal of some type that I don't know right now, but it doesn't matter because you can't put a function there."

@som-snytt som-snytt changed the title Improve message for missing parameter type if no function applies Improve message for missing parameter type if no method takes a function May 5, 2019

@som-snytt som-snytt self-assigned this May 6, 2019

@adriaanm

This comment has been minimized.

Copy link
Member

commented May 15, 2019

With a patch along the following lines, you will get the more friendly error about the unexpected function while expecting a woozle, as well as the missing parameter times:

--- i/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ w/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3057,7 +3057,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
                 issuedMissingParameterTypeError = true
               }
 
-              setError(fun)
+              // Improve error reporting: propagate what we know about the function's type -- we'll fail
+              fun setType appliedType(FunctionClass(vparams.length), vparams.map(param => if (param.tpt.isEmpty) WildcardType else silent(_.typedType(param.tpt).tpe).fold(WildcardType: Type){ case ErrorType => WildcardType case tp => tp }) :+ WildcardType)
             }
           } else {
             fun.body match {

It's trickier to not complain about the missing parameter types -- it's not clear to me how you know which of those errors is the most important (note that implicit conversions or other adaptations could apply after we type check the function literal against an expected type it at first doesn't meet, or perhaps never will -- the difference is not known at this point)

adriaanm added a commit to adriaanm/scala that referenced this issue May 15, 2019

@som-snytt

This comment has been minimized.

Copy link
Author

commented May 15, 2019

Thanks, Adriaan. This must be a busy time.

I might have expected that erroring out of doTypedApply one could notice that an erroneous arg has the wrong shape. But actually, looking at your check files, just seeing the mismatch between something with an arrow and something without is pretty good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.