Support secondary constructors for inline classes
#KT-25614 Fixed #KT-25246 Fixed KT-25599 Will be fixed after recompilation of unsigned classes
This commit is contained in:
@@ -174,6 +174,13 @@ public class ConstructorCodegen {
|
||||
|
||||
markLineNumberForConstructor(constructorDescriptor, primaryConstructor, codegen);
|
||||
|
||||
if (OwnerKind.ERASED_INLINE_CLASS == kind) {
|
||||
Type t = typeMapper.mapType(constructorDescriptor.getContainingDeclaration());
|
||||
iv.load(0, t);
|
||||
iv.areturn(t);
|
||||
return;
|
||||
}
|
||||
|
||||
generateClosureInitialization(iv);
|
||||
|
||||
generateDelegatorToConstructorCall(
|
||||
@@ -237,7 +244,12 @@ public class ConstructorCodegen {
|
||||
codegen.gen(constructor.getBodyExpression(), Type.VOID_TYPE);
|
||||
}
|
||||
|
||||
iv.visitInsn(RETURN);
|
||||
if (OwnerKind.ERASED_INLINE_CLASS == kind) {
|
||||
iv.areturn(typeMapper.mapType(constructorDescriptor.getContainingDeclaration()));
|
||||
}
|
||||
else {
|
||||
iv.visitInsn(RETURN);
|
||||
}
|
||||
}
|
||||
|
||||
private void genCallToDelegatorByExpressionSpecifier(
|
||||
@@ -278,13 +290,16 @@ public class ConstructorCodegen {
|
||||
@NotNull ClassConstructorDescriptor constructorDescriptor,
|
||||
@NotNull ResolvedCall<ConstructorDescriptor> delegationConstructorCall
|
||||
) {
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
if (OwnerKind.ERASED_INLINE_CLASS != kind) {
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
}
|
||||
|
||||
ConstructorDescriptor delegateConstructor = SamCodegenUtil.resolveSamAdapter(codegen.getConstructorDescriptor(delegationConstructorCall));
|
||||
|
||||
KotlinTypeMapper typeMapper = state.getTypeMapper();
|
||||
|
||||
CallableMethod delegateConstructorCallable = typeMapper.mapToCallableMethod(delegateConstructor, false);
|
||||
CallableMethod callable = typeMapper.mapToCallableMethod(constructorDescriptor, false);
|
||||
CallableMethod delegateConstructorCallable = typeMapper.mapToCallableMethod(delegateConstructor, false, kind);
|
||||
CallableMethod callable = typeMapper.mapToCallableMethod(constructorDescriptor, false, kind);
|
||||
|
||||
List<JvmMethodParameterSignature> delegatingParameters = delegateConstructorCallable.getValueParameters();
|
||||
List<JvmMethodParameterSignature> parameters = callable.getValueParameters();
|
||||
|
||||
@@ -12,10 +12,12 @@ import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.resolve.InlineClassDescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.Synthetic
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
class ErasedInlineClassBodyCodegen(
|
||||
aClass: KtClass,
|
||||
@@ -24,19 +26,46 @@ class ErasedInlineClassBodyCodegen(
|
||||
state: GenerationState,
|
||||
parentCodegen: MemberCodegen<*>?
|
||||
) : ClassBodyCodegen(aClass, context, v, state, parentCodegen) {
|
||||
|
||||
private val superClassAsmType: Type by lazy {
|
||||
SuperClassInfo.getSuperClassInfo(descriptor, typeMapper).type
|
||||
}
|
||||
|
||||
private val classAsmType = typeMapper.mapErasedInlineClass(descriptor)
|
||||
|
||||
private val constructorCodegen = ConstructorCodegen(
|
||||
descriptor, context, functionCodegen, this, this, state, kind, v, classAsmType, aClass, bindingContext
|
||||
)
|
||||
|
||||
override fun generateDeclaration() {
|
||||
v.defineClass(
|
||||
myClass.psiOrParent, state.classFileVersion, Opcodes.ACC_FINAL or Opcodes.ACC_STATIC or Opcodes.ACC_PUBLIC,
|
||||
typeMapper.mapErasedInlineClass(descriptor).internalName,
|
||||
null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY
|
||||
classAsmType.internalName, null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY
|
||||
)
|
||||
v.visitSource(myClass.containingKtFile.name, null)
|
||||
}
|
||||
|
||||
override fun generateConstructors() {
|
||||
val delegationFieldsInfo = DelegationFieldsInfo(classAsmType, descriptor, state, bindingContext)
|
||||
|
||||
constructorCodegen.generatePrimaryConstructor(
|
||||
delegationFieldsInfo.getDelegationFieldsInfo(myClass.superTypeListEntries), superClassAsmType
|
||||
)
|
||||
|
||||
for (secondaryConstructor in descriptor.secondaryConstructors) {
|
||||
constructorCodegen.generateSecondaryConstructor(secondaryConstructor, superClassAsmType)
|
||||
}
|
||||
}
|
||||
|
||||
override fun generateSyntheticPartsAfterBody() {
|
||||
super.generateSyntheticPartsAfterBody()
|
||||
|
||||
generateUnboxMethod()
|
||||
}
|
||||
|
||||
private fun generateUnboxMethod() {
|
||||
val boxMethodDescriptor = InlineClassDescriptorResolver.createBoxFunctionDescriptor(descriptor) ?: return
|
||||
|
||||
functionCodegen.generateMethod(
|
||||
Synthetic(null, boxMethodDescriptor), boxMethodDescriptor, object : FunctionGenerationStrategy.CodegenBased(state) {
|
||||
override fun mapMethodSignature(
|
||||
|
||||
@@ -2152,7 +2152,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
FunctionDescriptor descriptor = accessibleFunctionDescriptor(resolvedCall);
|
||||
|
||||
if (descriptor instanceof ConstructorDescriptor) {
|
||||
if (InlineClassesUtilsKt.isInlineClass(descriptor.getContainingDeclaration())) {
|
||||
if (InlineClassesUtilsKt.isInlineClass(descriptor.getContainingDeclaration()) && ((ConstructorDescriptor) descriptor).isPrimary()) {
|
||||
// we do not call static function `constructor`, because it's empty
|
||||
return generateInlineClassConstructorCall(expression);
|
||||
}
|
||||
|
||||
@@ -4151,7 +4152,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
);
|
||||
|
||||
constructor = SamCodegenUtil.resolveSamAdapter(constructor);
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(constructor, false);
|
||||
OwnerKind inlineClassKindOrNull =
|
||||
InlineClassesUtilsKt.isInlineClass(constructor.getContainingDeclaration()) ? OwnerKind.ERASED_INLINE_CLASS : null;
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(constructor, false, inlineClassKindOrNull);
|
||||
invokeMethodWithArguments(method, resolvedCall, StackValue.none());
|
||||
|
||||
return Unit.INSTANCE;
|
||||
|
||||
@@ -780,8 +780,9 @@ public class KotlinTypeMapper {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CallableMethod mapToCallableMethod(@NotNull FunctionDescriptor descriptor, boolean superCall) {
|
||||
if (descriptor instanceof ConstructorDescriptor) {
|
||||
public CallableMethod mapToCallableMethod(@NotNull FunctionDescriptor descriptor, boolean superCall, @Nullable OwnerKind kind) {
|
||||
// we generate constructors of inline classes as usual functions
|
||||
if (descriptor instanceof ConstructorDescriptor && kind != OwnerKind.ERASED_INLINE_CLASS) {
|
||||
JvmMethodSignature method = mapSignatureSkipGeneric(descriptor.getOriginal());
|
||||
Type owner = mapOwner(descriptor);
|
||||
FunctionDescriptor originalDescriptor = descriptor.getOriginal();
|
||||
@@ -948,6 +949,11 @@ public class KotlinTypeMapper {
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CallableMethod mapToCallableMethod(@NotNull FunctionDescriptor descriptor, boolean superCall) {
|
||||
return mapToCallableMethod(descriptor, superCall, null);
|
||||
}
|
||||
|
||||
public static boolean isAccessor(@Nullable CallableMemberDescriptor descriptor) {
|
||||
return descriptor instanceof AccessorForCallableDescriptor<?> ||
|
||||
descriptor instanceof AccessorForCompanionObjectInstanceFieldDescriptor;
|
||||
@@ -978,7 +984,7 @@ public class KotlinTypeMapper {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String mapFunctionName(@NotNull FunctionDescriptor descriptor) {
|
||||
public String mapFunctionName(@NotNull FunctionDescriptor descriptor, @Nullable OwnerKind kind) {
|
||||
if (!(descriptor instanceof JavaCallableMemberDescriptor)) {
|
||||
String platformName = getJvmName(descriptor);
|
||||
if (platformName != null) return platformName;
|
||||
@@ -1021,6 +1027,9 @@ public class KotlinTypeMapper {
|
||||
else if (isLocalFunction(descriptor) || isFunctionExpression(descriptor)) {
|
||||
return OperatorNameConventions.INVOKE.asString();
|
||||
}
|
||||
else if (OwnerKind.ERASED_INLINE_CLASS == kind && descriptor instanceof ConstructorDescriptor) {
|
||||
return JvmAbi.ERASED_INLINE_CONSTRUCTOR_NAME;
|
||||
}
|
||||
else {
|
||||
return mangleMemberNameIfRequired(descriptor.getName().asString(), descriptor);
|
||||
}
|
||||
@@ -1222,7 +1231,14 @@ public class KotlinTypeMapper {
|
||||
writeParameter(sw, JvmMethodParameterKind.CONSTRUCTOR_MARKER, DEFAULT_CONSTRUCTOR_MARKER);
|
||||
}
|
||||
|
||||
writeVoidReturn(sw);
|
||||
if (OwnerKind.ERASED_INLINE_CLASS == kind) {
|
||||
sw.writeReturnType();
|
||||
sw.writeAsmType(mapType(((ClassConstructorDescriptor) f).getContainingDeclaration()));
|
||||
sw.writeReturnTypeEnd();
|
||||
}
|
||||
else {
|
||||
writeVoidReturn(sw);
|
||||
}
|
||||
}
|
||||
else {
|
||||
CallableMemberDescriptor directMember = DescriptorUtils.getDirectMember(f);
|
||||
@@ -1263,7 +1279,7 @@ public class KotlinTypeMapper {
|
||||
sw.writeReturnTypeEnd();
|
||||
}
|
||||
|
||||
JvmMethodGenericSignature signature = sw.makeJvmMethodSignature(mapFunctionName(f));
|
||||
JvmMethodGenericSignature signature = sw.makeJvmMethodSignature(mapFunctionName(f, kind));
|
||||
|
||||
if (kind != OwnerKind.DEFAULT_IMPLS && kind != OwnerKind.ERASED_INLINE_CLASS && !hasSpecialBridge) {
|
||||
SpecialSignatureInfo specialSignatureInfo = BuiltinMethodsWithSpecialGenericSignature.getSpecialSignatureInfo(f);
|
||||
|
||||
Reference in New Issue
Block a user