Search code examples
scalascala-2.10

Scala 2.10 "No implicit view available" error on type parameter that asks for a view


I have reduced this example from something encountered in a much larger project; the fundamental issue seems to be that Scala 2.10 has weird or possibly broken handling of view constraints:

trait Nameish {
  def name: String
}

abstract class Namer[A <% Nameish](e: Class[A]) {
  def doNameThing(x: A) = println("argument is named " + x.name)
}
class SubNamer[A <% Nameish](e: Class[A]) extends Namer(e) {
}

object TestViews extends App {
  import scala.language.implicitConversions
  implicit def nameStr(x: String): Nameish = new StringNamer(x);

  class StringNamer(x: String) extends Nameish {
    def name = x
  }

  println(new SubNamer(classOf[String]).doNameThing("foo"))
}

When I try to compile this, in scala 2.10 I get the errors:

TestViews.scala:8: error: No implicit view available from A => Nameish.
class SubNamer[A <% Nameish](e: Class[A]) extends Namer(e) {
                 ^
TestViews.scala:18: error: value doNameThing is not a member of SubNamer[String]
  println(new SubNamer(classOf[String]).doNameThing("foo"))
                                        ^
two errors found

Note that Scala 2.11 is fine with this code.

Unfortunately, re-tooling this code to a newer scala version would make this task explode in size. I need to find a way to make the existing scala accept a class hierarchy with a type parameter that has a view constraint.


Another attempt at a way around this has uncovered a different scala-2.10-only error case:

trait Nameish {
  def name: String
}

abstract class Namer[A](e: Class[A])(implicit view: A => Nameish) {
  def doNameThing(x: A) = println("argument is named " + x.name)
}
class SubNamer[A](e: Class[A])(implicit view: A => Nameish) extends Namer(e)(view) {
}

object TestViews extends App {
  import scala.language.implicitConversions
  implicit def nameStr(x: String): Nameish = new StringNamer(x);

  class StringNamer(x: String) extends Nameish {
    def name = x
  }

  println(new SubNamer(classOf[String]).doNameThing("foo"))
}

This is just replacing the view constraints with implicit arguments.

With this code, it again compiles just fine with Scala 2.11, but on Scala 2.10:

TestViews.scala:8: error: `implicit' modifier cannot be used for top-level objects
class SubNamer[A](e: Class[A])(implicit view: A => Nameish) extends Namer(e)(view) {
                                        ^
one error found

I don't understand what's going on here: I'm not trying to declare an implicit object, I'm trying to declare that the class takes an implicit parameter. Why is it fine for the first class, but not the second one?


Solution

  • Adding parameter type parameter A to Namer (in the Subnamer inheritance) worked for me (Scala version 2.10.7):

    class SubNamer[A <% Nameish](e: Class[A]) extends Namer[A](e)
    

    By the way your example without modification worked for me only from the Scala version 2.11.5.

    Hope this helps.