NoArg: Fix IllegalAccessError on instantiating sealed class child via Java reflection (KT-18245)
This commit is contained in:
@@ -44,15 +44,24 @@ class NoArgExpressionCodegenExtension(val invokeInitializers: Boolean = false) :
|
|||||||
|
|
||||||
val constructorDescriptor = createNoArgConstructorDescriptor(descriptor)
|
val constructorDescriptor = createNoArgConstructorDescriptor(descriptor)
|
||||||
|
|
||||||
|
val isParentASealedClass = (descriptor.containingDeclaration as? ClassDescriptor)?.modality == Modality.SEALED
|
||||||
|
|
||||||
functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, constructorDescriptor, object: CodegenBased(state) {
|
functionCodegen.generateMethod(JvmDeclarationOrigin.NO_ORIGIN, constructorDescriptor, object: CodegenBased(state) {
|
||||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||||
codegen.v.load(0, AsmTypes.OBJECT_TYPE)
|
codegen.v.load(0, AsmTypes.OBJECT_TYPE)
|
||||||
codegen.v.visitMethodInsn(Opcodes.INVOKESPECIAL, superClassInternalName, "<init>", "()V", false)
|
|
||||||
|
if (isParentASealedClass) {
|
||||||
|
codegen.v.aconst(null)
|
||||||
|
codegen.v.visitMethodInsn(Opcodes.INVOKESPECIAL, superClassInternalName, "<init>",
|
||||||
|
"(Lkotlin/jvm/internal/DefaultConstructorMarker;)V", false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
codegen.v.visitMethodInsn(Opcodes.INVOKESPECIAL, superClassInternalName, "<init>", "()V", false)
|
||||||
|
}
|
||||||
|
|
||||||
if (invokeInitializers) {
|
if (invokeInitializers) {
|
||||||
generateInitializers(codegen)
|
generateInitializers(codegen)
|
||||||
}
|
}
|
||||||
|
|
||||||
codegen.v.visitInsn(Opcodes.RETURN)
|
codegen.v.visitInsn(Opcodes.RETURN)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
annotation class NoArg
|
||||||
|
|
||||||
|
sealed class Test {
|
||||||
|
abstract val test: String
|
||||||
|
|
||||||
|
@NoArg
|
||||||
|
data class Test1(override val test: String) : Test()
|
||||||
|
|
||||||
|
@NoArg
|
||||||
|
data class Test2(override val test: String) : Test()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
Test::class.java.declaredConstructors.forEach { it.isAccessible = true }
|
||||||
|
Test.Test1::class.java.declaredConstructors.forEach { it.isAccessible = true }
|
||||||
|
|
||||||
|
val instance = Test.Test1::class.java.newInstance() // Error
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+6
@@ -48,6 +48,12 @@ public class BlackBoxCodegenTestForNoArgGenerated extends AbstractBlackBoxCodege
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt18245.kt")
|
||||||
|
public void testKt18245() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("plugins/noarg/noarg-cli/testData/box/kt18245.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt18667.kt")
|
@TestMetadata("kt18667.kt")
|
||||||
public void testKt18667() throws Exception {
|
public void testKt18667() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("plugins/noarg/noarg-cli/testData/box/kt18667.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("plugins/noarg/noarg-cli/testData/box/kt18667.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user