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

Invalid error message on missing given instance #11493

Open
kubukoz opened this issue Feb 21, 2021 · 9 comments
Open

Invalid error message on missing given instance #11493

kubukoz opened this issue Feb 21, 2021 · 9 comments
Assignees
Labels
area:reporting Error reporting including formatting, implicit suggestions, etc better-errors Issues concerned with improving confusing/unhelpful diagnostic messages discussion itype:bug stat:needs minimization Needs a self contained minimization

Comments

@kubukoz
Copy link
Contributor

kubukoz commented Feb 21, 2021

Compiler version

3.0.0-RC1

Minimized code

https://github.com/kubukoz/given-repro

// requires cats-effect 3.0.0-RC2 or 2.3.3
// "org.typelevel" %% "cats-effect" % "2.3.3"

import cats.MonadError
import cats.effect.IO

sealed trait Failure extends Throwable

def demo[F[_]](using MonadError[F, Failure]) = ???

def demo2 = demo[IO]

Output

[E] [E1] src/main/scala/Main.scala:8:21
[E]      Could not find an instance of Monad for cats.effect.IO
[E]      L8: def demo2 = demo[IO]
[E]                              ^
[E] src/main/scala/Main.scala: L8 [E1]

Expectation

Something along the lines of

Could not find an instance of MonadError[[a] =>> F[a], Failure] for cats.effect.IO

More context

The typeclass hierarchy is: MonadError[F[_], E] <: Monad[F]. Cats IO has MonadError[IO, Throwable], so Monad[IO] is definitely there.

@kubukoz
Copy link
Contributor Author

kubukoz commented Feb 21, 2021

I wasn't able to reproduce this without the dependency (with fake types for MonadError etc.), so it might have something to do with implicit priority etc.

@smarter
Copy link
Member

smarter commented Feb 21, 2021

This message comes from the @implicitNotFound of Monad: https://github.com/typelevel/cats/blob/6bd3e00c50ad1d30a3cd4b55fc967ea0c1c1310c/core/src/main/scala/cats/Monad.scala#L15
We intentionally look for @implicitNotFound in parents, but I guess Scala 2 doesn't? Maybe we should revert to the Scala 2 behavior here to avoid confusion /cc @prolativ

@smarter smarter added the area:reporting Error reporting including formatting, implicit suggestions, etc label Feb 21, 2021
@kubukoz kubukoz changed the title Invalid error message on missign given instance Invalid error message on missing given instance Feb 21, 2021
@kubukoz
Copy link
Contributor Author

kubukoz commented Feb 21, 2021

oh, that would explain why I wasn't getting it to work. I think that behavior of looking up the annotation in parents would be quite confusing if someone didn't know this is happening. And I'm not entirely sure it's helpful if you know 😅 after all, in this case the message is a lie.

@djspiewak
Copy link

I think there's also a fair argument to be made that the implicitNotFound in question is doing more harm than good even on Scala 2.

@prolativ
Copy link
Contributor

Scala 2 does look for implicitNotFound in parents and we decided to keep consistent with this behaviour #10098.
The difference is that in Scala 2 the message from implicitNotFound does not override the default error message but is appended to it so for a Scala 2 version of the reported snippet the error is something like

could not find implicit value for parameter ev: cats.MonadError[cats.effect.IO,Failure] (Could not find an instance of Monad for cats.effect.IO)

So the questions are:

  1. Should we prepend the default error message as Scala 2 does? This gives you some additional information if you know how this message is constructed but might be quite confusing otherwise, as in the example above. I believe the intention of displaying only the message from the annotation was that if as the author of a library you consistently annotate all the types that are used as implicit parameters, the users of the library might not even need to (fully) understand what an implicit is (especially that we now use given/using instead in most places) - the custom message can contain information about what needs to be done to make the code compile (e.g. add a specific import).
  2. Should we revert to the previous behaviour and not inherit the implicitNotFound annotation? Or maybe we should require that if a parent class is annotated its children should be always explicitly annotated as well. Java seems to have some generic mechanisms for controlling inheritance of annotations (@Inherited meta-annotation) but I'm not sure if/how this currently works for scala as well

@smarter
Copy link
Member

smarter commented Feb 25, 2021

Should we prepend the default error message as Scala 2 does?

Because existing implicitNotFound messages are designed with this behavior in mind, I think it makes sense to replicate it yes, we can revisit this later.

@som-snytt
Copy link
Contributor

There is a suggestion for future linting scala/bug#11653 (comment)

I think the idea was to detect whether the parent message applies (type params align).

I don't know whether messages are designed with this behavior in mind. It is more of a back-up to report "as much info as possible" when annotations are missing. Lukas suggested warning when the "overriding" annotation is omitted. fthomas/refined#661 (comment)

@kubukoz
Copy link
Contributor Author

kubukoz commented May 5, 2021

1. Should we prepend the default error message as Scala 2 does? This gives you some additional information if you know how this message is constructed but might be quite confusing otherwise, as in the example above. I believe the intention of displaying only the message from the annotation was that if as the author of a library you consistently annotate all the types that are used as implicit parameters, the users of the library might not even need to (fully) understand what an implicit is (especially that we now use `given`/`using` instead in most places) - the custom message can contain information about what needs to be done to make the code compile (e.g. add a specific import).

@prolativ

I think this makes the most sense.

@kubukoz
Copy link
Contributor Author

kubukoz commented May 28, 2021

Got bit by this again, it's super confusing - any chance we can get this prioritized?

@anatoliykmetyuk anatoliykmetyuk added discussion stat:needs minimization Needs a self contained minimization labels Jul 21, 2021
@anatoliykmetyuk anatoliykmetyuk added the Spree Suitable for a future Spree label Oct 15, 2021
@bishabosha bishabosha added the better-errors Issues concerned with improving confusing/unhelpful diagnostic messages label Oct 12, 2023
@mbovel mbovel removed the Spree Suitable for a future Spree label May 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:reporting Error reporting including formatting, implicit suggestions, etc better-errors Issues concerned with improving confusing/unhelpful diagnostic messages discussion itype:bug stat:needs minimization Needs a self contained minimization
Projects
None yet
Development

No branches or pull requests

8 participants