发现 Scala 3 宏:(x$1 : x$1².reflect.Symbol) 要求:quoted.Quotes

Scala 3 macro Found: (x$1 : x$1².reflect.Symbol) Required: quoted.Quotes

def printParamsImpl[A](using Quotes, Type[A]): Expr[() => Unit] = {
  import quotes.reflect._
    TypeRepr.of[A].typeSymbol.declaredMethods.collect {
      case m if m.paramSymss.size == 1 =>
        val params = m.paramSymss.head
        val paramNames = {
          val exprList = params.map {  p =>
            Expr(p.name)
          }
          Expr.ofList(exprList)
        }
    
        '{ 
          println(${paramNames})
        }
    }

上面的代码报错了

Found:    (x : x².reflect.Symbol)
Required: quoted.Quotes

where:    x  is a parameter in an anonymous function in method printParamsImpl
          x² is a parameter in method printParamsImpl

只是不知道错误信息是什么意思。

Live Demo

错误似乎源于对 scala.quoted.quotes 的使用,它看起来像这样:

transparent inline def quotes(using inline q: Quotes): q.type = q

这似乎有效,因为您有 (using Quotes)。但是,它似乎无法分配稳定的单一类型(q.type),因为 Quotes 未命名。

如果您将其更改为 (using q: Quotes),然后将其更改为 import q.reflect._,那么这个特定的错误就会消失(尽管它随后会显示示例中的其他一些错误)。

这是一个完成的示例,它完成了我认为您正在尝试做的事情:

  def printParamsImpl[A](using q: Quotes)(using Type[A]): Expr[() => Unit] = {
    import q.reflect._
    
    val paramNames = Expr.ofList {
      // In each declared method, get a list of the names of each parameter in the first parameter list.
      // Flatten those into a single list of String expressions
      TypeRepr.of[A].typeSymbol.declaredMethods.collect {
        case m if m.paramSymss.size == 1 =>
          val params = m.paramSymss.head
          params.map {  p =>
            Literal(StringConstant(p.name)).asExprOf[String]
          }
      }.flatten
    }

    '{
    () => println(${paramNames})
    }
  }

  inline def foo[A]: () => Unit = ${printParamsImpl[A]}

它的一个 Scastie 是 here,但它仍然不会 运行 – 您不能在定义的同一编译单元中调用宏。

但是,如果您使用主要源下的定义和测试源下的调用(例如,在 App 对象中)创建项目,您将能够 运行 它使用 sbt test:run(因为主要和测试源是单独编译 运行s)。