Closed
Description
Compiler version
3.0.0-RC3
Minimized example
In a macro, I want to generate a pattern match for a sealed trait/enum, covering each case and performing some actions. The code I've got is the following:
import scala.quoted.*
object MatchTest {
inline def test[T](inline obj: T): Unit = ${testImpl('obj)}
def testImpl[T](objExpr: Expr[T])(using qctx: Quotes, t: Type[T]): Expr[Unit] = {
import qctx.reflect.*
val obj = objExpr.asTerm
val cases = obj.tpe.typeSymbol.children.map { child =>
val subtype = TypeIdent(child)
val bind = Symbol.newBind(Symbol.spliceOwner, "c", Flags.EmptyFlags, subtype.tpe)
CaseDef(Bind(bind, Typed(Ref(bind), subtype)), None, '{()}.asTerm)
}
val bind = Symbol.newBind(Symbol.spliceOwner, "o", Flags.EmptyFlags, obj.tpe)
val result = Match(obj, cases)
println(result.show(using Printer.TreeAnsiCode))
result.asExprOf[Unit]
}
}
Tested using:
sealed trait P
case class PC1(a: String) extends P
case class PC2(b: Int) extends P
MatchTest.test(PC2(10): P)
Output
(PC2.apply(10): P) match {
case c @ (c: PC1) =>
()
case c @ (`c₂`: PC2) =>
()
}
[warn] -- [E029] Pattern Match Exhaustivity Warning: Test.scala:25:17
[warn] 25 | MatchTest.test(PC2(10): P)
[warn] | ^^^^^^^^^^
[warn] | match may not be exhaustive.
[warn] |
[warn] | It would fail on pattern case: PC1(_), PC2(_)
[warn] | This location contains code that was inlined from Test.scala:25
Expectation
I wouldn't expect an exhaustivity warning, as all cases are covered.
I know that the match isn't perfect, but I don't know how to generate a better one. Specifically, instead of c @ (c: PC1)
, I'd like to generate c @ (_: PC1)
, but I can't find a way to create a _
using the current macro API. A candidate would be Ident(TermRef(NoPrefix, "_"))
, but then I don't know how to get a NoPrefix
instance.
I also tried adding a third branch with an : Any
case, but this didn't help - got the same exhaustivity warning