simple-robot / simbot-component-onebot

一个Kotlin多平台的 OneBot SDK 实现,一个异步高效、Java 友好的 Simple Robot 组件库 ~ 🐱🐱🐱
https://simbot.forte.love/component-onebot.html
GNU Lesser General Public License v3.0
10 stars 3 forks source link

Kotlin 2.x 和编译器插件导致的泛型问题,以及进一步导致的 OneBotApiExecutable 在 Java 中不可"访问"问题 #139

Closed ForteScarlet closed 1 week ago

ForteScarlet commented 1 week ago

虽然比起“不可访问”,我觉得大概率是 IDEA 的 Kotlin 插件无法识别,强行执行大概是可以的。

大概原因: 在 Kotlin 2.x 某个版本中,编译器为泛型增加了从属性,而在所使用的编译器插件中,阻塞、异步等合成函数在基于源项目进行拷贝时,仅拷贝了源函数上的泛型参数,但没有对参数内的泛型进行覆盖。

这会导致,生成的合成函数的参数中如果包含泛型,那么它的泛型还是属于源函数的。

例如,一个源函数和其生成的合成函数:

interface Inter {
  // 源函数
  suspend fun <T> run(api: Api<T /* 1 */>): T

  // 编译器插件合成出来的函数
  fun <T> runBlocking(api: Api<T/* 2 */>): T = ...
}

虽然看上去没什么问题,但是在Kotlin的IR树中,/* 2 */ 位置的泛型 T/* 1 */ 的一样,仍然是属于 run 而不是 runBlocking 的。

此时 runBlocking 的IR树的部分内容:

FUN FAKE_OVERRIDE name:runBlocking visibility:public modality:OPEN <R> ($this:<root>.Inter, api:<root>.Api<R of <root>.Inter.run>) returnType:R of <root>.Inter.run[fake_override]

可以看到,其中有 R of <root>.Inter.run,这说明即使在 runBlocking 中,参数的泛型依旧是 run 的。 然而,这种问题似乎并不会影响到 编译 ,因为不论是兼容性检测还是打包发布都没有受到影响。 在IDEA中,如果查看 OneBotApiExecutableclass 文件,会看到:

AR%6JTAWGL(N(0T _L U1J6

参数的泛型内都是一些 Error type,这也导致了IDE无法分析,进而无法提供相关的提示。

[!note] 但是即然 class 存在且完整,而泛型又不是运行时的内容,所以我猜测,禁用IDEA的Kotlin 插件这个方法可以临时解决此问题。