2

I have some code that routinely does type checks like that:

obj match {
  case _: Foo =>
    // everything is fine
  case _ =>
    throw SomeException(...)
}

It works, but this is relatively bulky and feels like tons of duplicated code (especially given that exception requires lots of parameters), so I thought it would replace this an assertion function. However, my naïve try failed:

def assertType[T](obj: CommonType): Unit = {
  obj match {
    case _: T =>
      // everything is fine
    case _ =>
      throw SomeException(...)
  }
}

Obviously, due to JVM type erasure, this T parameter is ignored, so first case branch is always true. ⇒ Full source code demonstrating the problem

Of course, one can resort to Java's reflection methods, but that's slow, ugly, and unportable. What is the preferred way to do such assertions in Scala?

Somewhat related, but do not address this exact issue:

Community
  • 1
  • 1
GreyCat
  • 16,622
  • 18
  • 74
  • 112
  • so the point is to have a method that throws your custom exception instead of a plain `ClassCastException`? – Michal M Mar 01 '17 at 10:21
  • @MichalM Yeah, more or less so. Actually, I'm writing a compiler that needs better error messages, and the place where I'm doing all these assertions is the only place that has enough context to generate meaningful error message (i.e. with a line/column numbers, etc). – GreyCat Mar 01 '17 at 10:36
  • Apparently, _shapeless_ achieved something similar (I think it still throws ClassCastException anyway), as seen in this answer http://stackoverflow.com/a/8821911/1050787 which may be of interest to you. Unfortunately, how they did it in https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/typeable.scala is still beyond my comprehension, so I can merely give you the links... – Michal M Mar 01 '17 at 10:51

1 Answers1

3

Pass the manifest as well:

def assertType[T : Manifest](obj: CommonType): Boolean

Your example code will then work correctly:

v1 is Foo = true
v1 is Bar = false
v2 is Foo = false
v2 is Bar = true
Jon Anderson
  • 696
  • 4
  • 9
  • Thanks! That's exactly what I was looking for. Can you give me some pointers where can I read more about this `Manifest` magic? – GreyCat Mar 01 '17 at 13:41
  • 1
    This [post](http://stackoverflow.com/questions/12218641/scala-what-is-a-typetag-and-how-do-i-use-it) has some great information about TypeTags and Manifests. Manifests are eventualty going to be deprecated in favor of TypeTags,but they are simpler for your case. – Jon Anderson Mar 01 '17 at 13:53
  • It turned out that `Manifest` is indeed deprecated and not supported by Scala.js (and we are cross-compiling to JS too), but `ClassTag` seems to do the job just as fine, so I ended up using that. – GreyCat Mar 03 '17 at 07:19