Scala 3 类已删除仍被宏找到:Gradle 增量编译可能留下 TASTy
Gradle 9.7.1 增量 compileScala 后,删除的类可能只清掉 class,留下 tasty。先对照产物,再用一次完整重建恢复一致性。
删除一个 Scala 3 类后,增量 compileScala 看起来成功,宏生成的代码却仍引用它,运行时再报 NoClassDefFoundError。先比较 .class 与 .tasty,不要马上把已删除类重新放回源码。
Gradle 9.7.1、Scala 3.6.3 的明确场景中,删除 Removed.scala 再增量编译,Removed.class 被移除,build/classes/scala/main/Removed.tasty 却仍在。下游编译器可以通过 TASTy 元数据看到旧类型,宏枚举包成员时就可能继续引用它。
从同一个输出目录核对
确认失败模块确实使用 Scala 3,记录 Wrapper、Scala 版本和输出目录。默认主源码产物通常位于 build/classes/scala/main,自定义 source set 或插件可能改变位置。
查找被删类对应的 .class、.tasty 与打包内容,同时检查依赖 JAR 是否也带有同名类。如果 class 与 tasty 都存在,应继续确认是否有旧源码生成器或另一份依赖;如果两者都没有,再查运行时 classpath,不要把任何缺类都归到本题。
用一次完整重建恢复输出一致
先停止 IDE 和终端对同一个 build 目录的并发写入。保留失败产物、日志及源码差异,用项目原有清理方式删除可再生输出,再重新编译。标准插件项目可在确认 build 目录内没有需要保留的手工文件后使用:
./gradlew clean compileScala
多模块项目应限定到受影响模块,并按依赖关系重建下游。clean 会删除构建输出;不要对自定义存有业务文件的目录直接套用。它不会修改源码,但不能代替输出备份或重现记录。
完整重建后,已删除类的 class 与 tasty 都应消失。再运行触发宏的编译、测试和最终打包,检查新产物中没有旧类型,并确认运行时不再引用它。仅重新运行报错程序,可能仍使用旧 JAR。
保留删除源码的增量回归
清理是恢复当前输出的一种办法,不证明工具链已经修复增量清理。后续在隔离分支覆盖“新增类、构建、删除类、再次增量构建”的完整过程,同时检查两个文件是否一起移除。
不要编辑 .tasty 内容或把它当普通缓存提交到仓库。也不宜靠永久关闭宏扫描或捕获 NoClassDefFoundError 来掩盖过期产物。若项目仍受影响,可在该发布流程明确做干净构建,接受额外编译成本;升级后再用删除类的用例验证是否能移除这条绕行。


