Discuss the role and use of the 'implicit not found' annotation in Scala.
Instruction: Explain the '@implicitNotFound' annotation, including its purpose and how it's used.
Updated
@implicitNotFound customizes the compiler diagnostic when it cannot supply a contextual argument of the annotated type. This makes a missing type-class instance easier for an API user to diagnose.
import scala.annotation.implicitNotFound
@implicitNotFound("No Show[${T}]; provide a Show instance for this type")
trait Show[T] { def show(value: T): String }
object Show {
given Show[Int] with {
def show(value: Int): String = value.toString
}
}
def showValue[T](value: T)(using instance: Show[T]): String =
instance.show(value)
@main def diagnosticExample(): Unit = {
assert(showValue(42) == "42")
}
Calling showValue(true) without a Show[Boolean] instance fails to compile with the customized message, substituting Boolean for ${T}. The parameter name in the placeholder must refer to a type parameter in the relevant declaration. An annotation on an implicit parameter can override the type-level diagnostic for that parameter. Annotation contract
Write a message that states the missing capability and a realistic remedy, such as defining or importing the required instance. The annotation does not create an instance, change implicit resolution or validate runtime data. Ambiguous candidates are a different failure; @implicitAmbiguous addresses that diagnostic.