Skip to content

No import suggestions for conditional implicit conversions #8823

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

Open
julienrf opened this issue Apr 28, 2020 · 0 comments
Open

No import suggestions for conditional implicit conversions #8823

julienrf opened this issue Apr 28, 2020 · 0 comments
Labels

Comments

@julienrf
Copy link
Contributor

julienrf commented Apr 28, 2020

Scala 2-style implicit conversions that take implicit parameters (let’s call them “conditional conversions”) don’t suggest imports if their implicit parameter can’t be found. Instead, a “value bar is not a member of Foo” error is reported.

Minimized code

  trait Foo[A]
  class FooOps[A](self: A)(implicit foo: Foo[A]) {
    def bar: Unit = ()
  }
  object Implicits {
    implicit def fooOps[A](a: A)(implicit foo: Foo[A]): FooOps[A] = new FooOps(a)
    implicit def fooInt: Foo[Int] = new Foo[Int] {}
  }

  object Usage {
    import Implicits.fooOps
    42.bar
  }

Output

[error] -- [E008] Not Found Error:
[error] 44 |    42.bar
[error]    |    ^^^^^^
[error]    |    value bar is not a member of Int

Expectation

We should suggest importing Implicits.fooInt.

Discussion

Note that if we omit the import Implicits.fooOps clause, we get the following error message:

[error] -- [E008] Not Found Error:
[error] 44 |    42.bar
[error]    |    ^^^^^^
[error]    |value bar is not a member of Int, but could be made available as an extension method.
[error]    |
[error]    |The following import might make progress towards fixing the problem:
[error]    |
[error]    |  import Implicits.fooOps

However, following the import suggestion leads to the error reported above!

It is worth noting that a similar example but using extension methods instead of conditional implicit conversions provides a better developer experience:

  trait Foo[A] {
    def (self: A).bar: Unit = ()
  }
  object Implicits {
    implicit def fooInt: Foo[Int] = new Foo[Int] {}
  }

  object Usage {
    42.bar
  }

Gives the following compilation error:

[error] -- [E008] Not Found Error:
[error] 55 |    42.bar
[error]    |    ^^^^^^
[error]    |value bar is not a member of Int, but could be made available as an extension method.
[error]    |
[error]    |The following import might fix the problem:
[error]    |
[error]    |  import Implicits.fooInt

And adding the suggested import fixes the compilation error.

Unfortunately, many Scala libraries (e.g., cats) still use conditional implicit conversions. I wish they could migrate to extension methods but this is not realistic because they couldn’t be called as methods from Scala 2 codebases.

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

No branches or pull requests

2 participants