tek / splain

better implicit errors for scala
MIT License
370 stars 28 forks source link

Add more verbose mode for implicits #73

Open tribbloid opened 2 years ago

tribbloid commented 2 years ago

I just come with the following observation when playing with it for different edge cases:

-Vimplicits-verbose-candidate

In the following example:

  trait F[I, O]

  trait G1[A, B]
  trait G2[A, B]

  implicit def f[I, M, O](
      implicit
      g1: G1[I, M],
      g2: G2[M, O]
  ): F[I, O] = ???

  implicit def g1: G1[Int, String] = ???

  implicitly[F[Int, Char]]

this trigger the error report:

newSource1.scala:26: error: implicit error;
!I e: F[Int, Char]
f invalid because:
!I g2: G2[M, Char]
  implicitly[F[Int, Char]]
            ^

Turns out that the default implementation of:

    def unapplyCandidate(e: ImplicitError): Tree =
      e.candidate match {
        case TypeApply(fun, _) => fun
        case a                 => a
      }

shrug off type signatures of f (it should be f[Int, String, Char]). debugging of this error becomes much harder, considering that the following line:

!I g2: G2[M, Char]

Shows only the unreified type signature, the reified version:

!I g2: G2[String, Char]

Cannot be found anywhere.

-Vimplicits-verbose-position

Since the parameter keepmodules is discarded in scala 2.13.6. Package or owner information won't be shown in the message. This means if we have multiple functions like f or g1 with similar signature, it will be difficult to determine which one is the real candidate.

This new option should display the line number for each candidate. Making it much harder to cause confusion, e.g. for the above example, the output may become:

newSource1.scala:26: error: implicit error;
!I e: F[Int, Char]
Annotation.f[Int, String, Char] invalid because ...... source-<toolbox>,line-18,offset=218
!I g2: G2[M, Char]
  implicitly[F[Int, Char]]
            ^

The source-<toolbox>,line-18,offset=218 is generated by candidate.symbol.pos.showDebug, obviously this format can be improved.

tek commented 2 years ago

regarding the second issue, this PR changed the behaviour to print full paths: https://github.com/scala/scala/pull/9767

tribbloid commented 2 years ago

Oooh, nice. So the second issue is gone

But a lot of our test will become obsolete. I haven't find a reliable way to remove those:

__wrapper$1$879dac52089e4f9bbdc32fbf51951152.XXX

package prefixes imposed by scala reflection. Any idea how it can be bypassed?

I'll add a new pipeline for scala 2.13.7-SNAPSHOT.

tek commented 2 years ago

oh, right. I think that might have been one of the reasons why I removed module names in the first place. can't think of a solution on the spot.

tribbloid commented 11 months ago

Oooh, nice. So the second issue is gone

But a lot of our test will become obsolete. I haven't find a reliable way to remove those:

__wrapper$1$879dac52089e4f9bbdc32fbf51951152.XXX

package prefixes imposed by scala reflection. Any idea how it can be bypassed?

I'll add a new pipeline for scala 2.13.7-SNAPSHOT.

This should be solved, all of our test cases have got rid of the random wrapper. So -Vimplicits-verbose-position may still be useful but it won't be a blocker

Unfortunately, I haven't figure out the implementation of -Vimplicits-verbose-candidate, will have to think about it later