Hide constructors accepting inline class parameters

This commit is contained in:
Dmitry Petrov
2018-09-07 14:16:20 +03:00
parent 8a5dbe1c6b
commit 006c0aa740
28 changed files with 663 additions and 4 deletions
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.codegen.context.CodegenContext;
import org.jetbrains.kotlin.codegen.intrinsics.HashCode;
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.InlineClassManglingUtilsKt;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.config.JvmTarget;
import org.jetbrains.kotlin.descriptors.*;
@@ -402,6 +403,14 @@ public class AsmUtil {
return ACC_PRIVATE;
}
if (kind != OwnerKind.ERASED_INLINE_CLASS &&
memberDescriptor instanceof ConstructorDescriptor &&
!(memberDescriptor instanceof AccessorForConstructorDescriptor) &&
InlineClassManglingUtilsKt.shouldHideConstructorDueToInlineClassTypeValueParameters((ConstructorDescriptor) memberDescriptor)
) {
return ACC_PRIVATE;
}
if (isEffectivelyInlineOnly(memberDescriptor)) {
return ACC_PRIVATE;
}
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.codegen.context.ConstructorContext;
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext;
import org.jetbrains.kotlin.codegen.context.MethodContext;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.InlineClassManglingUtilsKt;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.psi.*;
@@ -108,9 +109,16 @@ public class ConstructorCodegen {
functionCodegen.generateDefaultIfNeeded(constructorContext, constructorDescriptor, OwnerKind.IMPLEMENTATION,
DefaultParameterValueLoader.DEFAULT, null);
registerAccessorForHiddenConstructorIfNeeded(constructorDescriptor);
new DefaultParameterValueSubstitutor(state).generatePrimaryConstructorOverloadsIfNeeded(constructorDescriptor, v, memberCodegen, kind, myClass);
}
private void registerAccessorForHiddenConstructorIfNeeded(ClassConstructorDescriptor descriptor) {
if (!InlineClassManglingUtilsKt.shouldHideConstructorDueToInlineClassTypeValueParameters(descriptor)) return;
context.getAccessor(descriptor, AccessorKind.NORMAL, null, null);
}
public void generateSecondaryConstructor(
@NotNull ClassConstructorDescriptor constructorDescriptor,
@NotNull Type superClassAsmType
@@ -138,6 +146,8 @@ public class ConstructorCodegen {
new DefaultParameterValueSubstitutor(state).generateOverloadsIfNeeded(
constructor, constructorDescriptor, constructorDescriptor, kind, v, memberCodegen
);
registerAccessorForHiddenConstructorIfNeeded(constructorDescriptor);
}
private void generateDelegatorToConstructorCall(
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator;
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.InlineClassManglingUtilsKt;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.codegen.when.SwitchCodegen;
import org.jetbrains.kotlin.codegen.when.SwitchCodegenProvider;
@@ -2256,10 +2257,23 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
descriptor = CoroutineCodegenUtilKt.unwrapInitialDescriptorForSuspendFunction(descriptor);
// $default method is not private, so you need no accessor to call it
return CallUtilKt.usesDefaultArguments(resolvedCall)
? descriptor
: context.accessibleDescriptor(descriptor, getSuperCallTarget(resolvedCall.getCall()));
if (CallUtilKt.usesDefaultArguments(resolvedCall)) {
// $default method is not private, so you need no accessor to call it
return descriptor;
}
else if (InlineClassManglingUtilsKt.shouldHideConstructorDueToInlineClassTypeValueParameters(descriptor)) {
// Constructors with inline class type value parameters should always be called using an accessor.
// NB this will require accessors even if the constructor itself is in a different module.
return new AccessorForConstructorDescriptor(
(ClassConstructorDescriptor) descriptor,
descriptor.getContainingDeclaration(),
getSuperCallTarget(resolvedCall.getCall()),
AccessorKind.NORMAL
);
}
else {
return context.accessibleDescriptor(descriptor, getSuperCallTarget(resolvedCall.getCall()));
}
}
@NotNull
@@ -27,6 +27,16 @@ fun getInlineClassSignatureManglingSuffix(descriptor: CallableMemberDescriptor):
return getInlineClassSignatureManglingSuffix(actualValueParameterTypes)
}
fun shouldHideConstructorDueToInlineClassTypeValueParameters(descriptor: CallableMemberDescriptor): Boolean {
if (descriptor !is ClassConstructorDescriptor) return false
if (Visibilities.isPrivate(descriptor.visibility)) return false
if (descriptor.constructedClass.isInline) return false
// TODO inner class in inline class
return descriptor.valueParameters.any { it.type.requiresFunctionNameMangling() }
}
fun getInlineClassSignatureManglingSuffix(valueParameterTypes: List<KotlinType>) =
if (valueParameterTypes.none { it.requiresFunctionNameMangling() })
null