scalaimplicittype-boundsscala-implicits

Can not find implicit conversion for a parameter of method with lower type bound


I have this code:

class Action[T]

class Insert[T] extends Action[T]

case class Quoted[T]()

implicit def unquote[T](q: Quoted[T]): T = {
  throw new Exception("Success")
}

def test[A <: Action[_]](a: A): A = {
  return a
}

try {
  test[Insert[String]](Quoted[Insert[String]])
  test(unquote(Quoted[Insert[String]]))
  // test(Quoted[Insert[String]]) // does not compile
} catch {
  case e: Exception => print(e.getMessage())
}

Scalafiddle

Commented line fails during compilation with:

error: inferred type arguments [ScalaFiddle.Quoted[ScalaFiddle.Insert[String]]] do not conform to method test's type parameter bounds [A <: ScalaFiddle.Action[_]]
    test(Quoted[Insert[String]])
error: type mismatch;
 found   : ScalaFiddle.Quoted[ScalaFiddle.Insert[String]]
 required: A
    test(Quoted[Insert[String]])

Is there any way to make it compile without specifying type parameter or explicitly using conversion function as in previous two lines?


Solution

  • Perhaps you could overload the test method like so:

    def test[A, B <: Action[_]](a: A)(implicit f: A => B): B = f(a)
    

    Then this does compile and work:

    test(Quoted[Insert[String]])
    

    I'm not positive about an explanation for why this is necessary, though. Perhaps if you're not explicit about the type parameter, it gets inferred and checked against bounds before any implicit conversions are applied. In your example, the implicit conversion search is triggered by a mismatch between the type parameter and the argument.