kotlin编译失败_聊两个 Kotlin 编译器的 bug
歡迎大家支持原文。
最近在使用 Kotlin 開發一個 IDE 插件,遇到了一些 Kotlin 編譯器的 bug ,就在博客里分享一下。
Java 交互問題
首先, Kotlin 編譯器在遇到接口自帶實現的情況時,會生成一個 DefaultImpls ,大概長這樣:
@Metadata(
mv = {1, 1, 9},
bv = {1, 0, 2},
k = 3
)
public static final class DefaultImpls {
@NotNull
public static FShapeQuad getDefaultActiveArea(final FriceGame $this) {
return (FShapeQuad)(new FShapeQuad() { // ... });
}
@NotNull
public static FShapeQuad getBox(FriceGame $this) {
FShapeQuad var10000 = $this.getActiveArea();
if (var10000 == null) {
var10000 = $this.getDefaultActiveArea();
}
return var10000;
}
// ...
然后生成的子類中還是會有這些抽象方法的實現, 只是實現都會調用這個 DefaultImpls 里的方法(也就是說, 它對 Java8 的 default 一無所知
)。
因此,如果有一個 Java 的子類實現這個接口, 那么這些在 Kotlin 里有默認實現的方法其實都還是抽象的, 只是你可以直接在里面寫 return DefaultImpls.xxx() 而已。
我遇到這個問題的 case ,是有這樣的代碼的繼承關系:
interface IJuliaSymbol : PsiElement { fun rua() = 233 }
abstract class JuliaSymbolMixin : JuliaSymbol
interface JuliaSymbol extends IJuliaSymbol { }
class JuliaSymbolImpl extends JuliaSymbolMixin { }
我以為 rua 的實現會在 JuliaSymbolMixin 中被自動插入, 于是 JuliaSymbolImpl 就可以使用了。
結果我太年輕,編譯器直接拋異常。
錯誤信息:
Error:Kotlin: [Internal Error] java.lang.AssertionError: Could not generate LightClass for org.ice1000.julia.lang.psi.impl declared in
System: Linux 4.13.0-32-generic Java Runtime: 1.8.0_151-8u151-b12-0ubuntu0.16.04.2-b12
元數據和實際代碼不符的問題
一開始我遇到這個問題是懵逼的,因為我只是調用了一個 inline reified 的方法而已,我犯了什么錯呢。
get() = parentOfType() ?: parent
實際上是這樣的, Kotlin 在查找方法之類的東西的定義的時候, 是進入類文件的元數據進行查找的, 因此如果元數據和方法本身不匹配的話就可以崩掉編譯器。
而這里就是一個道理,生成的類被混淆了,而元數據保持不變, 于是編譯器找到的合法定義變得不存在了,就拋異常。
這也是一開始 Alex 沒有成功復現這個 bug 的原因,因為在他的電腦里, gradle 是通過下載 IntelliJ Community 的最新版來解決的依賴問題, 而這個就沒有被混淆,所以編譯正常通過。
錯誤信息:
e: org.jetbrains.kotlin.codegen.CompilationException: Back-end (JVM) Internal error: Couldn't inline method call 'parentOfType' into
public open val startPoint: com.intellij.psi.PsiElement defined in org.ice1000.julia.lang.psi.impl.JuliaDeclaration
open val startPoint: PsiElement get() = parentOfType() ?: parent
Cause: Not generated
Cause: Couldn't obtain compiled function body for public inline fun com.intellij.psi.PsiElement.parentOfType(): T? defined in com.intellij.psi.util[DeserializedSimpleFunctionDescriptor@676ab4f3]
File being compiled and position: (29,42) in /home/ice1000/git-repos/julia-intellij/src/org/ice1000/julia/lang/psi/impl/julia-psi-mixin.kt
The root cause was thrown at: InlineCodegen.kt:529
希望這些 bug 都早日得到修復。
最后再唾棄一次:
第二次用 Emacs 寫這么多中文,感覺好不習慣【x
總結
以上是生活随笔為你收集整理的kotlin编译失败_聊两个 Kotlin 编译器的 bug的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用Spring3+Quartz实现定时
- 下一篇: B端产品如何寻找竞品?