Last active
August 29, 2015 14:15
-
-
Save propensive/6a47575a4bce3b17c5dc to your computer and use it in GitHub Desktop.
Providing custom type mismatch errors in Scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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