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.

Context: This question is designed to test the candidate's knowledge on Scala's implicits and compile-time checks, focusing on enhancing the developer experience with meaningful error messages.

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.

Related Questions