Use correct class file version when copying anonymous objects in inliner
Generally, using state.classFileVersion would be enough because we report an error when inlining bytecode into a class file with a lower target version (see INLINE_FROM_HIGHER_PLATFORM). However, we take maxOf with the original version of the class file, _just in case_ the user has suppressed this error (for example, to workaround some other corner case in the compiler). #KT-30744 Fixed
This commit is contained in:
+1
-1
@@ -59,7 +59,7 @@ class AnonymousObjectTransformer(
|
|||||||
|
|
||||||
createClassReader().accept(object : ClassVisitor(Opcodes.API_VERSION, classBuilder.visitor) {
|
createClassReader().accept(object : ClassVisitor(Opcodes.API_VERSION, classBuilder.visitor) {
|
||||||
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
|
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
|
||||||
classBuilder.defineClass(null, version, access, name, signature, superName, interfaces)
|
classBuilder.defineClass(null, maxOf(version, state.classFileVersion), access, name, signature, superName, interfaces)
|
||||||
if (languageVersionSettings.isCoroutineSuperClass(superName)) {
|
if (languageVersionSettings.isCoroutineSuperClass(superName)) {
|
||||||
inliningContext.isContinuation = true
|
inliningContext.isContinuation = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ class WhenMappingTransformer(
|
|||||||
val fieldNode = transformationInfo.fieldNode
|
val fieldNode = transformationInfo.fieldNode
|
||||||
classReader.accept(object : ClassVisitor(Opcodes.API_VERSION, classBuilder.visitor) {
|
classReader.accept(object : ClassVisitor(Opcodes.API_VERSION, classBuilder.visitor) {
|
||||||
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
|
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
|
||||||
classBuilder.defineClass(null, version, access, name, signature, superName, interfaces)
|
classBuilder.defineClass(null, maxOf(version, state.classFileVersion), access, name, signature, superName, interfaces)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? {
|
override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? {
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ class SamWrapperTransformer(transformationInfo: SamWrapperTransformationInfo, pr
|
|||||||
|
|
||||||
classReader.accept(object : ClassVisitor(Opcodes.API_VERSION, classBuilder.visitor) {
|
classReader.accept(object : ClassVisitor(Opcodes.API_VERSION, classBuilder.visitor) {
|
||||||
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
|
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
|
||||||
classBuilder.defineClass(null, version, access, name, signature, superName, interfaces)
|
classBuilder.defineClass(null, maxOf(version, state.classFileVersion), access, name, signature, superName, interfaces)
|
||||||
}
|
}
|
||||||
|
|
||||||
}, ClassReader.SKIP_FRAMES)
|
}, ClassReader.SKIP_FRAMES)
|
||||||
@@ -69,4 +69,4 @@ class SamWrapperTransformer(transformationInfo: SamWrapperTransformationInfo, pr
|
|||||||
|
|
||||||
return transformationResult
|
return transformationResult
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
public interface A {
|
||||||
|
public static void method() {}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
inline fun foo(crossinline x: () -> Unit): Any = object {
|
||||||
|
init {
|
||||||
|
x()
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
OK
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
fun main() {
|
||||||
|
foo {
|
||||||
|
A.method()
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
@@ -588,6 +588,14 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testInlineAnonymousObjectWithDifferentTarget() {
|
||||||
|
val library = compileLibrary("library", additionalOptions = listOf("-jvm-target", "1.6"))
|
||||||
|
compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-jvm-target", "1.8"))
|
||||||
|
val classLoader =
|
||||||
|
URLClassLoader(arrayOf(library.toURI().toURL(), tmpdir.toURI().toURL()), ForTestCompileRuntime.runtimeJarClassLoader())
|
||||||
|
classLoader.loadClass("SourceKt").getDeclaredMethod("main").invoke(null)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// compiler before 1.1.4 version did not include suspension marks into bytecode.
|
// compiler before 1.1.4 version did not include suspension marks into bytecode.
|
||||||
private fun stripSuspensionMarksToImitateLegacyCompiler(bytes: ByteArray): Pair<ByteArray, Int> {
|
private fun stripSuspensionMarksToImitateLegacyCompiler(bytes: ByteArray): Pair<ByteArray, Int> {
|
||||||
|
|||||||
Reference in New Issue
Block a user