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

Scala 3编译器插件添加混入特质后方法未生效的解决方法

问题:编译器阶段混入特质后方法无法生效的解决办法

问题代码

class ExpPhase extends PluginPhase {
  import tpd._

  val phaseName = "expPhase"

  override val runsAfter = Set("typer")

  override def transformTypeDef(tree: TypeDef)(implicit ctx: Context): Tree =
    if tree.isClassDef && !tree.rhs.symbol.isStatic then  // only look at classes & traits, not objects
      val c2 = QuotesCache.init(ctx.fresh)
      implicit val quotes = scala.quoted.runtime.impl.QuotesImpl()(using c2)
      import quotes.reflect.*

      // Add new parent, SJ_Serialize, so class Person becomes class Person extends SJ_Serialize
      val cd = ClassDef.copy(classDef)(
        name = classDef.name,
        constr = classDef.constructor,
        parents = classDef.parents :+ TypeTree.of[SJ_Serialize],  // SJ_Serialize is a trait having methods
        selfOpt = classDef.self,
        body = classDef.body
      )
      val newCd = cd.asInstanceOf[dotty.tools.dotc.ast.tpd.Tree] 
      println(QuotesImpl.showDecompiledTree(newCd)) // see if class modified successfully
      newCd
    else
      tree
}

问题描述

上述代码在编译器阶段尝试给目标类混入SJ_Serialize特质,打印结果显示语法树已修改成功,但后续流程中该特质的实现方法未被复制到目标类,导致无法调用这些方法。

解决办法

  • 更新类符号的父类信息:仅修改语法树不足以让编译器识别新增的特质父类,必须同步更新类符号的父类列表。可以通过类符号的addParent方法将SJ_Serialize的符号添加进去,示例代码如下(需适配Dotty的符号API):
    val serializeSymbol = ctx.definitions.getClass("SJ_Serialize").symbol
    tree.symbol.addParent(serializeSymbol)
    
  • 触发特质方法的混入逻辑:Dotty中特质的方法合成是在mixin阶段完成的,你需要确保修改后的类能被该阶段处理。可以在修改语法树后,手动触发符号的成员计算,或者确保你的阶段运行在mixin阶段之前(调整runsAfter或runsBefore),让mixin阶段自动处理新增的特质父类,将特质方法复制到目标类中。
  • 避免混用Quotes与Dotty内部API:当前代码混用了Quotes的语法树操作和Dotty的tpd.Tree,容易导致语法树结构不兼容。建议直接使用Dotty内部的ClassDef节点操作来修改父类,比如:
    val cd = tree.asInstanceOf[ClassDef]
    val newParents = cd.parents :+ TypeTree.of[SJ_Serialize](using ctx)
    val newCd = cd.copy(parents = newParents)
    
  • 验证阶段执行顺序:确保你的expPhase运行在typer之后、mixin之前。可以通过override val runsBefore = Set("mixin")来明确阶段顺序,保证修改后的语法树能被后续的混入逻辑处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 13:25:33