Materializzazione implicita nello stesso modulo
Ho una classe parametrizzata come
class Test[T]{
//...
}
object Test{
implicit def materializeTest[T]: Test[T] = macro impl[T]
def impl[T: c.WeakTypeTag](c: blackbox.Context) = //...
}
Se si utilizza l'implicito materializzato dallo stesso modulo, viene generato un errore:
macro implementation not found
Ma il problema è che estrarre una singola classe in un modulo separato sembra assolutamente brutto e macchinoso. Forse c'è qualche "soluzione alternativa ben nota" per evitarlo? Forse l'informe può essere utile qui?
UPD:
scalaVersion in ThisBuild := "2.13.2"
Ecco il mio esempio minimo:
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))
}
}
che si traduce nel seguente errore:
[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)
Risposte
Puoi estrarre in un modulo separato non TestmaTestMacro
nucleo
import scala.language.experimental.macros
class Test[T]
object Test {
implicit def materializeTest[T]: Test[T] = macro TestMacro.impl[T]
}
implicitly[Test[Int]] // compiles
macro
import scala.reflect.macros.blackbox
object TestMacro {
def impl[T: c.WeakTypeTag](c: blackbox.Context) = {
import c.universe._
q"new Test[${weakTypeOf[T]}]"
}
}
Brutto o no, ma le implementazioni macro devono essere compilate prima di essere applicate.
Questo è migliorato in Scala 3
http://dotty.epfl.ch/docs/reference/metaprogramming/macros.html#defining-a-macro-and-using-it-in-a-single-project
Shapeless nasconde solo un set predefinito di macro standard, non può aiutare con le tue macro.