Search code examples
scalaspecs2shapeless

Possible to test for exhaustivity of match of macro-generated types


I've written a macro which generates an ADT, and would like to be able to write a test proving that I've done so in a manner which allows exhaustivity checking to work. Both specs2 (via typecheck) and Shapeless (via illTyped) allow one to test whether code is well typed or not, however this doesn't seem to get me anywhere for detecting a non-exhaustive pattern match (even when compiling with -Xfatal-warnings).

Is there a way to detect a non-exhaustive pattern match that I can use in my test?


Solution

  • As far as I understand it, exhaustivity checking is not really a feature of the type system, i.e. if you look at the typing rules, its not part of them, but something done on top of a type-checked program.

    I guess what you could do, is to use a macro to generate code as part of your test cases. Your tests would then fail during compilation of the test suit. Or you use the compiler api to compile the code during test execution. It should be possible to get those warnings there.

    I figured out that you can do this using the toolbox API:

    import scala.reflect.runtime.currentMirror
    import scala.tools.reflect.ToolBox
    import scala.reflect.runtime.universe._
    
    val code = q"""
      val s: Option[Int] = Some(1)
      s match{case Some(x)=>}
    """
    
    val toolbox = currentMirror.mkToolBox(new tools.reflect.FrontEnd {
      override def display(info: Info) = println(info)
      override def interactive() {}
    })
    toolbox.eval(code)
    

    This prints the following warning

    Info(NoPosition,match may not be exhaustive. It would fail on the following input: None,WARNING)

    You can also parse the code you want to test-compile from some string or build the AST up splicing parts into quasiquotes or whatever else suits you.