I have a parameterized class like
class Test[T]{
//...
}
object Test{
implicit def materializeTest[T]: Test[T] = macro impl[T]
def impl[T: c.WeakTypeTag](c: blackbox.Context) = //...
}
If using the materialized implicit from the same module it throws an error:
macro implementation not found
But the problem is extracting a single class into a separate module looks absolutely ugly and cumbersome. Maybe there is some "well-known workaround" to avoid that? Maybe shapeless can be helpful here?
UPD:
scalaVersion in ThisBuild := "2.13.2"
Here is my minimal example:
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
object Main {
sealed trait Adt
case object Adt1 extends Adt
case object Adt2 extends Adt
trait Test[Adtt <: Adt] {
def restrict(restrictions: List[Int]): List[Int]
}
object Test {
def apply[Adtt <: Adt](implicit ev: Test[Adtt]): Test[Adtt] = ev
implicit def implicitMaterializer[
Adtt <: Adt
]: Test[Adtt] = macro impl[Adtt]
def impl[Adtt <: Adt: c.WeakTypeTag](
c: blackbox.Context
): c.Expr[Test[Adtt]] = {
import c.universe._
c.Expr[Test[Adtt]](q"""???""")
}
}
def main(args: Array[String]): Unit = {
Test[Adt1.type].restrict(List(1, 2, 3))
}
}
which results in the following error:
[error] Main.scala:32:9: macro implementation not found: implicitMaterializer
[error] (the most common reason for that is that you cannot use macro implementations in the same compilation run that defines them)
You can extract to a separate module not Test
but TestMacro
core
import scala.language.experimental.macros
class Test[T]
object Test {
implicit def materializeTest[T]: Test[T] = macro TestMacro.impl[T]
}
implicitly[Test[Int]] // compiles
macros
import scala.reflect.macros.blackbox
object TestMacro {
def impl[T: c.WeakTypeTag](c: blackbox.Context) = {
import c.universe._
q"new Test[${weakTypeOf[T]}]"
}
}
Ugly or not but macro implementations must be compiled before they are applied (but Is there any trick to use macros in the same file they are defined?).
This is improved in Scala 3
Shapeless just hides some predefined set of standard macros, it can't help with your own macros.