Providing custom type mismatch errors in Scala
| import language.experimental.macros | |
| import language.implicitConversions | |
| import scala.reflect.macros._ | |
| // We are going to provide a custom error message for when users use the wrong variant of some | |
| // type, `Foo`. Note that `Foo` needs to be invariant or contravariant in its type parameter! | |
| case class Foo[T]() | |
| object Foo { | |
| implicit def reportError[T, U](value: Foo[T]): Foo[U] = macro Macros.reportErrorMacro[T, U] | |
| } | |
| object Macros { | |
| def reportErrorMacro[T: c.WeakTypeTag, U: c.WeakTypeTag](c: Context)(value: c.Expr[Foo[T]]): c.Expr[Foo[U]] = { | |
| import c.universe._ | |
| val (t, u) = (weakTypeOf[T], weakTypeOf[U]) | |
| c.abort(c.enclosingPosition, s"You tried to use a Foo of type $t, when you should have used a $u!") | |
| } | |
| } | |
| // We have created an implicit which will convert from any specific type of `Foo` to any other | |
| // type of `Foo`, then we've implemented that with a macro which will always fail (at compile | |
| // time) with our custom error. | |
| // Let's demonstrate it in the REPL by providing a `Foo[String]` where a `Foo[Int]` is expected: | |
| scala> def foo[T](f: Foo[T]) = () | |
| foo: [T](f: Foo[T])Unit | |
| scala> foo[String](Foo[Int]()) | |
| <console>:18: error: You tried to use a Foo of type Int, when you should have used a String! | |
| foo[String](Foo[Int]()) | |
| ^ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment