Scala 3 宏无法在范围内找到给定的

问题描述 投票:0回答:1

我正在尝试在 Scala 3 中编写一个宏,它将解析案例类中定义的类型,然后查找这些类型的给定/隐式方法。

下面是宏代码。

import scala.quoted.*

object TransformerMacro:
  inline def resolveTransformer[T] = ${ resolveTransformerImpl[T] }

  def resolveTransformerImpl[T: Type](using Quotes) =
    import quotes.reflect.*

    val tpe = TypeRepr.of[T]

    val typeMembersAll = tpe.typeSymbol.declaredTypes.map {
      case typ if typ.isType =>
        val typeName = typ.name
        val typeBound = tpe.memberType(typ)
        typeName -> typeBound
    }

    val outType = typeMembersAll.head._2
    val inType = typeMembersAll.last._2

    (outType, inType) match {
      case (TypeBounds(_, oT), TypeBounds(_, iT)) =>
        (oT.asType, iT.asType) match {
          case ('[o], '[i]) =>
            val itn = Type.show[i]
            val otn = Type.show[o]
            Expr.summon[TR[o, i]] match {
              case Some(instance) =>
                report.info(s"We might find the implicit now $itn, $otn $instance")
                '{Some(${instance})}
                
              case None =>
                report.error(s"No Implicit Found for type: \nReModel[$itn, $otn]")
                '{ None }
            }
        }
    }

斯卡斯蒂

示例:

case class Person(name: String, age: Int, email: Option[String]):
  type R = String
  type M = Int

trait TR[A, B]:
 def f(a: A) : B

object TR:
 given strToInt: TR[Int, String] with
    override def f(from: Int): String = from.toString

对于案例类 Person,宏将解析 R 和 M 的类型,并尝试在范围内找到 TR 类型的隐式。

但是宏也会进入 None 情况并给出以下错误

report.error(s"No Implicit Found for type: \nTR[$itn, $otn]")

宏的驱动程序代码

def main(args: Array[String]): Unit =
  val resolved = TransformerMacro.resolveTransformer[Person]
  println(resolved)
scala macros implicit scala-macros scala-3
1个回答
0
投票

错误在这里:

Expr.summon[TR[o, i]]

在其他地方,您使用

i
前缀作为输入,使用
o
作为输出,但在这里您将这些值交换在一起:您查找
TR[String, Int]
,失败时打印
not found TR[Int, String]
- 这就是为什么重复数据删除逻辑很有用,如果是
not found TR[String, Int]
,问题就会立即显而易见。

它可以更容易地实现:

import scala.quoted.*

object TransformerMacro:
  inline def resolveTransformer[T] = ${ resolveTransformerImpl[T] }

  def resolveTransformerImpl[T: Type](using Quotes) =
    import quotes.reflect.*

    // Help us extract member types without weird shenanigans
    type Aux[I, O] = Person { type R = O; type M = I }

    Type.of[T] match {
      case '[Aux[i, o]] => // much simpler extraction
       // reuse computed type for both summoning and printing
       def handle[A: Type] = {
          Expr.summon[A] match {
            case Some(instance) =>
              report.info(s"We might find the implicit now ${instance.asTerm.show}: ${TypeRepr.of[A].show}")
              '{Some(${instance})}
            case None =>
              report.error(s"No Implicit Found for type: \n${TypeRepr.of[A].show}")
              '{ None }
          }
       }
       handle(using Type.of[TR[i, o]])
    }
© www.soinside.com 2019 - 2024. All rights reserved.