我甚至不知道该怎么问这个问题。
我有一个为T类型创建IsEnum[T]实例的宏。
我正在对它进行测试,并希望确保不会为未密封的类型找到隐式类型,或者通常不满足枚举的要求。
所以我创建了这个方法来测试
def enumOf[T](implicit isEnum:IsEnum[T] = null) = isEnum然后我要确保enumOf[NotAnEnum] == null
但相反,它会在编译时失败。
一件事就是宏的错误。另一件事是宏并不适用于给定的情况。如何在创建宏时进行区分?
编辑:我使用了c.abort和c.error,它们给我的结果都是一样的。
发布于 2020-09-30 07:43:33
听起来你没有把你的宏物化类型类设为IsEnum白盒。通常情况下,隐式宏应该是白盒。
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
trait IsEnum[T]
object IsEnum {
implicit def mkIsEnum[T]: IsEnum[T] = macro mkIsEnumImpl[T]
def mkIsEnumImpl[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = {
import c.universe._
val typ = weakTypeOf[T]
val classSymbol = typ.typeSymbol.asClass
if (!classSymbol.isTrait || !classSymbol.isSealed) c.abort(c.enclosingPosition, s"$typ must be sealed trait")
val symbols = classSymbol.knownDirectSubclasses
symbols.collectFirst {
case symbol if !symbol.isModuleClass || !symbol.asClass.isCaseClass =>
c.abort(c.enclosingPosition, s"${symbol.asClass.toType} must be case object")
}
q"new IsEnum[$typ] {}"
}
}
def enumOf[T](implicit isEnum: IsEnum[T] = null) = isEnum用法:
sealed trait A
object A {
case object B extends A
case object C extends A
case class D() extends A
}
enumOf[A] //null
sealed trait A
object A {
case object B extends A
case object C extends A
class D extends A
}
enumOf[A] //null
sealed trait A
object A {
case object B extends A
object C extends A
}
enumOf[A] //null
trait A
object A {
case object B extends A
case object C extends A
}
enumOf[A] //null
sealed trait A
object A {
case object B extends A
case object C extends A
}
enumOf[A] //App$$anon$1@47f37ef1宏的运行时是主代码的编译时间。如果一个黑箱宏(甚至是隐式的黑箱宏)抛出一个异常,那么在主代码编译期间它将是一个编译错误。如果白盒隐式宏抛出异常,那么在主代码编译期间,隐式宏将从候选代码中悄悄删除。
https://docs.scala-lang.org/overviews/macros/blackbox-whitebox.html
https://stackoverflow.com/questions/64122310
复制相似问题