Dotty: Extension method in scope not found

Created on 15 Jun 2020  路  4Comments  路  Source: lampepfl/dotty

Minimized code

On the REPL:

trait A[F[_]] {}
object A {
  def [A](x: A).pure: List[A] = List(x)
  val a = "ola".pure[List]
}

Output

4 |  val a = "ola".pure[List]
  |          ^^^^^^^^^^
  |value pure is not a member of String, but could be made available as an extension method.
  |
  |The following import might fix the problem:
  |
  |  import A.pure
  |

Expectation

I would expect it to compile.

Also if we have a package object like:

package object p {
  trait A[F[_]] {}
  object A {
    def [A](x: A).pure: List[A] = List(x)
    val a = "ola".pure[List]
  }
}

The error has a double suggestion.
I don't expect to see the second suggestion.
Furthermore, the suggestion with reserved keywords should have those words on backticks.

|    val a = "ola".pure[List]
|            ^^^^^^^^^^
|value pure is not a member of String, but could be made available as an extension method.
|
|One of the following imports might fix the problem:
|
|  import p.A.pure
|  import p.package.A.pure
bug

Most helpful comment

Works without type parameter if "ola".pure[List] is changed to "ola".pure.
Note that List in this position is ill-kinded and also not the correct type, "ola".pure[String] also works. However, the error message could possibly mention a type mismatch instead of a missing method.

All 4 comments

Fyi @smarter here is the ticket

Works without type parameter if "ola".pure[List] is changed to "ola".pure.
Note that List in this position is ill-kinded and also not the correct type, "ola".pure[String] also works. However, the error message could possibly mention a type mismatch instead of a missing method.

@neko-kai That makes a lot of sense. Thanks for point that out.
Helped me with other stuff that I was playing around.

So now I redefine my dot pure syntax like

trait M[F[_]] { def pure[A](x: A): F[A] }                                                                                                                                                                                              
object M {
  def [A, F[A]](x: A).pure(using m: M[F]): F[A] = m.pure(x)
  given listMonad as M[List] { def pure[A](x: A): List[A] = List(x) }
  given optionMonad as M[Option] { def pure[A](x: A): Option[A] = Some(x) }
  val value1: List[String] = "ola".pure
  val value2 = "ola".pure
}

The value2 will give an error and suggest to import M.pure. The scope of M.pure is already available and should never be suggested.
The problem now is that we have ambiguity from listMonad and optionMonad.
The suggestion is completely misleading.

I think this is an important thing to improve!
Imagine that you have a piece of code that compiles. After making the given optionMonad available. Your code stops to compile because of ambiguity but the compiler doesn't tell you about that.
It will cause you to inspire little confidence in the language. I can already see the memes =P

The error message we get is:

7 |  val value2 = "ola".pure
  |               ^^^^^^^^^^
  |               value pure is not a member of String

If we change make pure a prefix method, we get something more informative:

-- Error: i9185.scala:8:26 -----------------------------------------------------
8 |  val value3 = pure("ola")
  |                          ^
  |ambiguous implicit arguments: both object listMonad in object M and object optionMonad in object M match type M[F] of parameter m of method pure in object M

It's a general problem of being several steps away from where the pure error happened. This is not easy to fix, since we risk generating avalanches of useless information if we record all the branches that were tried but failed.

But in this case it might be doable. If in a selection a.b if b is known as an extension method, print any errors why it did not apply. We do that already with the "an extension method was tried but could not be fully constructed addendum, but that one works only for extension methods known as givens I believe.

Was this page helpful?
0 / 5 - 0 ratings