You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala 3.6.4宏中如何调用inline方法?

解决Scala 3宏中调用inline transparent类型类方法的编译错误

问题场景

我在开发Scala 3.6.4序列化库时,定义了DiscriminatorCriteria类型类,用于为求和类型S的每个变体P生成对应的判别值。该类型类的核心方法discriminator被声明为:

  • inline:以支持scala.compiletime.erasedValue等编译期API
  • transparent:确保返回常量单例类型,让编译器能在编译期确定返回值的具体类型

在实现序列化/反序列化的派生宏时,我最初通过Expr.summon[DiscriminatorCriteria[S, P]]获取类型类实例,并在quote代码块中调用其discriminator方法,但编译时触发错误:

Deferred inline method discriminator in trait DiscriminatorCriteria cannot be invoked

我尝试了@DmytroMitin提出的summonDiscriminator封装方案,但仍然遇到相同的错误,最终通过直接使用Scala宏的底层Implicits.search方法解决了该问题。

问题原因

Expr.summon是Scala宏API中封装好的隐式实例获取方式,但对于包含inline方法的类型类,它无法正确解析方法的具体实现逻辑,导致编译器认为discriminator是一个未实现的延迟方法(deferred inline method),从而拒绝调用。

解决方案

直接使用宏反射层的Implicits.search方法来获取类型类实例,它能直接获取到隐式实例的语法树节点,让编译器正确识别并内联展开inline方法。

代码示例

首先定义一个底层的隐式实例获取工具:

import scala.quoted.*

def summonDiscriminator[S: Type, P: Type](using Quotes): Expr[DiscriminatorCriteria[S, P]] = {
  import quotes.reflect.*
  Implicits.search(TypeRepr.of[DiscriminatorCriteria[S, P]]) match {
    case success: ImplicitSearchSuccess => success.tree.asExprOf[DiscriminatorCriteria[S, P]]
    case failure: ImplicitSearchFailure => report.errorAndAbort(failure.explanation)
  }
}

然后在派生宏中调用该工具并使用discriminator方法:

def deriveSerializer[S: Type](using Quotes): Expr[Serializer[S]] = {
  '{
    new Serializer[S] {
      override def serialize(value: S): String = {
        // 针对求和类型的每个变体P获取判别值
        ${
          // 省略变体遍历逻辑,仅展示核心调用方式
          val discriminatorExpr = summonDiscriminator[S, P].map(dc => '{ $dc.discriminator })
          discriminatorExpr.getOrElse(report.errorAndAbort("No DiscriminatorCriteria instance found"))
        }
        // 后续序列化逻辑
      }
    }
  }
}

说明

通过Implicits.search获取的隐式实例语法树,能够让编译器正确处理inline方法的内联展开,同时保留transparent方法带来的常量单例类型推导能力,完美适配序列化库中对编译期常量判别值的需求。

内容的提问来源于stack exchange,提问作者Readren

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 04:12:33