Сбой отражающего инструментария Scala из-за неразрешенного свободного типа

Попытка квазикавычек в первый раз для общего создания новых классов case:

val universe: scala.reflect.runtime.universe.type = scala.reflect.runtime.universe
import universe._
import scala.reflect.runtime.{currentMirror => m}
import scala.tools.reflect.ToolBox
val toolbox = m.mkToolBox()

trait Father
class A extends Father {
  println("I'm A")
  val a = 0
}
class B extends Father {
  println("I'm B")
  val b = 0
}

object Produce {
  def A(): A = {
    val weakT = weakTypeOf[A]
    val genTree = q"""
      case class Son() extends $weakT {
        println("I'm alive")
      }
      Son()
      """
    val compiledCode = toolbox.eval(genTree)
    compiledCode.asInstanceOf[A]
  }
  def apply[T <: Father](): T = {
    val weakT = weakTypeOf[T]
    val genTree = q"""
      case class Son() extends $weakT {
        println("I'm alive")
      }
      Son()
      """
    val compiledCode = toolbox.eval(genTree)
    compiledCode.asInstanceOf[T]
  }
}

Produce.A()

Produce[A]()

Результаты для Produce.A():

I'm A

я жив

res0: A = Сын()

Результаты для Produce[A]():

scala.tools.reflect.ToolBoxError: отказ отражающего инструментария из-за неразрешенных переменных свободного типа: T определено с помощью применения в: 32:13, вы забыли использовать аннотации TypeTag для параметров типа, внешних по отношению к reifee? если у вас возникли проблемы с отслеживанием переменных свободного типа, рассмотрите возможность использования -Xlog-free-types в scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.verify(ToolBoxFactory.scala:82) в scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal .compile(ToolBoxFactory.scala:208) в scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$$anonfun$compile$2.apply(ToolBoxFactory.scala:429) в scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$$anonfun$compile$2 .apply(ToolBoxFactory.scala:422) в scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$.liftedTree2$1(ToolBoxFactory.scala:355) в scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$.apply(ToolBoxFactory. scala:355) в scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.compile(ToolBoxFactory.scala:422) в scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.eval(ToolBoxFactory.scala:444) в Produce$.apply(:40 ) ... 34 пропущено


person Oron Port    schedule 05.07.2016    source источник
comment
Вы пробовали это? def apply[T <: Father : TypeTag](): T = {   -  person devkat    schedule 05.07.2016


Ответы (1)


Как было предложено @Andreas Jim-Hartmann, добавлен ': TypeTag' (см. комментарий ниже), и теперь этот код работает как для общего, так и для конкретного:

val universe: scala.reflect.runtime.universe.type = scala.reflect.runtime.universe
import universe._
import scala.reflect.runtime.{currentMirror => m}
import scala.tools.reflect.ToolBox
val toolbox = m.mkToolBox()

trait Father
class A extends Father {
  println("I'm A")
  val a = 0
}
class B extends Father {
  println("I'm B")
  val b = 0
}

object Produce {
  def A(): A = {
    val weakT = weakTypeOf[A]
    val genTree = q"""
      case class Son() extends $weakT {
        println("I'm alive")
      }
      Son()
      """
    val compiledCode = toolbox.eval(genTree)
    compiledCode.asInstanceOf[A]
  }
  def apply[T <: Father : TypeTag](): T = { //Fixed here
    val weakT = weakTypeOf[T]
    val genTree = q"""
      case class Son() extends $weakT {
        println("I'm alive")
      }
      Son()
      """
    val compiledCode = toolbox.eval(genTree)
    compiledCode.asInstanceOf[T]
  }
}

Produce.A()

Produce[A]()

Produce[B]()
person Oron Port    schedule 05.07.2016