NoArg: Fix compatibility with sealed classes with non-zero-parameter constructors (KT-19687)
Also check if a class has a sealed super class properly.
This commit is contained in:
committed by
Yan Zhulanow
parent
cea891c754
commit
187ca71dc6
@@ -44,13 +44,18 @@ class NoArgExpressionCodegenExtension(val invokeInitializers: Boolean = false) :
|
|||||||
|
|
||||||
val constructorDescriptor = createNoArgConstructorDescriptor(descriptor)
|
val constructorDescriptor = createNoArgConstructorDescriptor(descriptor)
|
||||||
|
|
||||||
val isParentASealedClass = (descriptor.containingDeclaration as? ClassDescriptor)?.modality == Modality.SEALED
|
val superClass = descriptor.getSuperClassOrAny()
|
||||||
|
|
||||||
|
// If a parent sealed class has not a zero-parameter constructor, user must write @NoArg annotation for the parent class as well,
|
||||||
|
// and then we generate <init>()V
|
||||||
|
val isParentASealedClassWithDefaultConstructor =
|
||||||
|
superClass.modality == Modality.SEALED && superClass.constructors.any { it.isZeroParameterConstructor() }
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
if (isParentASealedClass) {
|
if (isParentASealedClassWithDefaultConstructor) {
|
||||||
codegen.v.aconst(null)
|
codegen.v.aconst(null)
|
||||||
codegen.v.visitMethodInsn(Opcodes.INVOKESPECIAL, superClassInternalName, "<init>",
|
codegen.v.visitMethodInsn(Opcodes.INVOKESPECIAL, superClassInternalName, "<init>",
|
||||||
"(Lkotlin/jvm/internal/DefaultConstructorMarker;)V", false)
|
"(Lkotlin/jvm/internal/DefaultConstructorMarker;)V", false)
|
||||||
|
|||||||
+23
@@ -18,5 +18,28 @@ fun box(): String {
|
|||||||
|
|
||||||
val instance = Test.Test1::class.java.newInstance() // Error
|
val instance = Test.Test1::class.java.newInstance() // Error
|
||||||
|
|
||||||
|
Demo.Foo::class.java.newInstance()
|
||||||
|
Demo.Free::class.java.newInstance()
|
||||||
|
|
||||||
|
A.Free::class.java.newInstance()
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NoArg
|
||||||
|
sealed class Demo(val name : String) {
|
||||||
|
@NoArg
|
||||||
|
class Free(name: String)
|
||||||
|
|
||||||
|
@NoArg
|
||||||
|
class Foo(name: String) : Demo(name)
|
||||||
|
|
||||||
|
@NoArg
|
||||||
|
class Bar(name: String) : Demo(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
@NoArg
|
||||||
|
abstract class A(val name: String) {
|
||||||
|
@NoArg
|
||||||
|
class Free(name: String) : A(name)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user