scala / scala3

The Scala 3 compiler, also known as Dotty.
https://dotty.epfl.ch
Apache License 2.0
5.86k stars 1.06k forks source link

custom `implicitNotFound` ignored when unrelated default argument is inserted #19594

Closed valencik closed 8 months ago

valencik commented 8 months ago

Compiler version

3.1.3+ (3.1.2 is the last version where the implicitNotFound is not ignored)

Minimized code

import scala.annotation.implicitNotFound
import scala.compiletime.testing.*

@implicitNotFound("Can you see me?!")
trait Compare[A, B]

object minimunit {

  def assertEquals[A, B](
    a: A,
    b: B,
    // The presence of the below default argument prevents the `implicitNotFound` message from appearing
    // in the error output of `typeCheckErrors` in Scala +3.1.3
    clue: => Any = "values are not the same"
  )(implicit comp: Compare[A, B]): Unit = ()

  transparent inline def compileErrors(inline code: String): List[Error] =
    typeCheckErrors(code)
}

object example extends App {
  val errors = minimunit.compileErrors("minimunit.assertEquals(true, 1)")
  println(errors)
}

Output

Scala 3.1.3

scala-cli run --scala-version 3.1.3 minimunit.scala

List(Error(missing argument for parameter comp of method assertEquals in object minimunit: (implicit comp: Compare[Boolean, Int]): Unit,minimunit.assertEquals(true, 1),22,Typer))

Scala 3.1.2

scala-cli run --scala-version 3.1.2 minimunit.scala

List(Error(Can you see me?!,minimunit.assertEquals(true, 1),31,Typer))

Expectation

The implicitNotFound message should appear whether or not there is a default argument involved.

If we remove the clue: => Any = "values are not the same" line, the implicitNotFound message is again returned on Scala versions greater than 3.1.2

I encountered this issue when trying to upgrade munit to Scala 3.3.1 https://github.com/scalameta/munit/pull/733

Gedochao commented 8 months ago

Happens also on 3.4.1-RC1-bin-20240131-2b40f55-NIGHTLY

valencik commented 8 months ago

I should add that you don't need the typeCheckErrors to get this behaviour.

Given the following:

import scala.annotation.implicitNotFound

@implicitNotFound("Can you see me?!")
trait Compare[A, B]

object minimunit {

  def assertEquals[A, B](
    a: A,
    b: B,
    // The presence of the below default argument prevents the `implicitNotFound` message from appearing
    // in the error output of `typeCheckErrors` in Scala +3.1.3
    clue: => Any = "values are not the same"
  )(implicit comp: Compare[A, B]): Unit = ()
}

object example extends App {
  minimunit.assertEquals(true, 1)
}

On +3.1.3 we get a compile error:

[error] missing argument for parameter comp of method assertEquals in object minimunit: (implicit comp: Compare[Boolean, Int]): Unit
[error]   minimunit.assertEquals(true, 1)
[error]   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

And on 3.1.2 we see the implicitNotFound instead:

[error] Can you see me?!
[error]   minimunit.assertEquals(true, 1)
[error]                                  ^
valencik commented 6 months ago

@Kordyjan should I open another issue for the solution in https://github.com/scala/scala3/pull/19737 to be back ported to a Scala LTS version?