Skip to content

No import suggestions for conditional implicit conversions #8823

Open
@julienrf

Description

@julienrf

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions