KT-28054: Treat inline class constructor accessors specially

This commit is contained in:
Dmitry Petrov
2018-11-16 14:14:24 +03:00
parent 3a93cab3b6
commit 90da274eaa
11 changed files with 94 additions and 4 deletions
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.codegen.coroutines.SuspendFunctionGenerationStrategy
import org.jetbrains.kotlin.codegen.coroutines.SuspendInlineFunctionGenerationStrategy; import org.jetbrains.kotlin.codegen.coroutines.SuspendInlineFunctionGenerationStrategy;
import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.codegen.state.TypeMapperUtilsKt;
import org.jetbrains.kotlin.config.JvmDefaultMode; import org.jetbrains.kotlin.config.JvmDefaultMode;
import org.jetbrains.kotlin.config.JvmTarget; import org.jetbrains.kotlin.config.JvmTarget;
import org.jetbrains.kotlin.config.LanguageFeature; import org.jetbrains.kotlin.config.LanguageFeature;
@@ -189,7 +190,9 @@ public class FunctionCodegen {
@NotNull MethodContext methodContext, @NotNull MethodContext methodContext,
@NotNull FunctionGenerationStrategy strategy @NotNull FunctionGenerationStrategy strategy
) { ) {
OwnerKind contextKind = methodContext.getContextKind(); OwnerKind contextKind = TypeMapperUtilsKt.isInlineClassConstructorAccessor(functionDescriptor)
? OwnerKind.ERASED_INLINE_CLASS
: methodContext.getContextKind();
DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration(); DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
if (isInterface(containingDeclaration) && if (isInterface(containingDeclaration) &&
!processInterfaceMethod(functionDescriptor, contextKind, false, false, state.getJvmDefaultMode())) { !processInterfaceMethod(functionDescriptor, contextKind, false, false, state.getJvmDefaultMode())) {
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages;
import org.jetbrains.kotlin.codegen.inline.SourceMapper; import org.jetbrains.kotlin.codegen.inline.SourceMapper;
import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.codegen.state.TypeMapperUtilsKt;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.AnnotatedImpl; import org.jetbrains.kotlin.descriptors.annotations.AnnotatedImpl;
import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.descriptors.annotations.Annotations;
@@ -873,7 +874,9 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
functionDescriptor, functionDescriptor,
accessorDescriptor instanceof AccessorForCallableDescriptor && accessorDescriptor instanceof AccessorForCallableDescriptor &&
(((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallTarget() != null || (((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallTarget() != null ||
((AccessorForCallableDescriptor) accessorDescriptor).getAccessorKind() == AccessorKind.JVM_DEFAULT_COMPATIBILITY) ((AccessorForCallableDescriptor) accessorDescriptor).getAccessorKind() == AccessorKind.JVM_DEFAULT_COMPATIBILITY),
(accessorDescriptor != null && TypeMapperUtilsKt.isInlineClassConstructorAccessor(accessorDescriptor)
? OwnerKind.ERASED_INLINE_CLASS : null)
); );
boolean isJvmStaticInObjectOrClass = CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(functionDescriptor); boolean isJvmStaticInObjectOrClass = CodegenUtilKt.isJvmStaticInObjectOrClassOrInterface(functionDescriptor);
@@ -862,7 +862,9 @@ public class KotlinTypeMapper {
} }
} }
else { else {
boolean toInlinedErasedClass = currentOwner.isInline() && !isAccessor(functionDescriptor); boolean toInlinedErasedClass =
currentOwner.isInline() &&
(!isAccessor(functionDescriptor) || TypeMapperUtilsKt.isInlineClassConstructorAccessor(functionDescriptor));
if (toInlinedErasedClass) { if (toInlinedErasedClass) {
functionDescriptor = descriptor; functionDescriptor = descriptor;
} }
@@ -16,8 +16,10 @@
package org.jetbrains.kotlin.codegen.state package org.jetbrains.kotlin.codegen.state
import org.jetbrains.kotlin.codegen.AccessorForConstructorDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -87,3 +89,7 @@ fun KotlinType.removeExternalProjections(): KotlinType {
val newArguments = arguments.map { TypeProjectionImpl(Variance.INVARIANT, it.type) } val newArguments = arguments.map { TypeProjectionImpl(Variance.INVARIANT, it.type) }
return replace(newArguments) return replace(newArguments)
} }
fun isInlineClassConstructorAccessor(descriptor: FunctionDescriptor): Boolean =
descriptor is AccessorForConstructorDescriptor &&
descriptor.calleeDescriptor.constructedClass.isInline
@@ -0,0 +1,12 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
inline class Composed(val s: String) {
private constructor(s1: String, s2: String) : this(s1 + s2)
companion object {
fun p1(s: String) = Composed("O", s)
}
}
fun box() = Composed.p1("K").s
@@ -0,0 +1,14 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
inline class Composed(val s: String) {
constructor(s: String, x: Int) : this(s.subSequence(0, x).toString())
private constructor(s1: String, s2: String) : this(s1 + s2, 2)
fun p1(s2: String) =
{ Composed(s, s2) }
}
fun box() = Composed("O").p1("K1234")().s
@@ -12351,6 +12351,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassCompanionMethod2.kt"); runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassCompanionMethod2.kt");
} }
@TestMetadata("accessPrivateInlineClassConstructorFromCompanion.kt")
public void testAccessPrivateInlineClassConstructorFromCompanion() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassConstructorFromCompanion.kt");
}
@TestMetadata("accessPrivateInlineClassConstructorFromLambda.kt")
public void testAccessPrivateInlineClassConstructorFromLambda() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassConstructorFromLambda.kt");
}
@TestMetadata("accessPrivateInlineClassMethodFromCompanion.kt") @TestMetadata("accessPrivateInlineClassMethodFromCompanion.kt")
public void testAccessPrivateInlineClassMethodFromCompanion() throws Exception { public void testAccessPrivateInlineClassMethodFromCompanion() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassMethodFromCompanion.kt"); runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassMethodFromCompanion.kt");
@@ -12351,6 +12351,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassCompanionMethod2.kt"); runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassCompanionMethod2.kt");
} }
@TestMetadata("accessPrivateInlineClassConstructorFromCompanion.kt")
public void testAccessPrivateInlineClassConstructorFromCompanion() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassConstructorFromCompanion.kt");
}
@TestMetadata("accessPrivateInlineClassConstructorFromLambda.kt")
public void testAccessPrivateInlineClassConstructorFromLambda() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassConstructorFromLambda.kt");
}
@TestMetadata("accessPrivateInlineClassMethodFromCompanion.kt") @TestMetadata("accessPrivateInlineClassMethodFromCompanion.kt")
public void testAccessPrivateInlineClassMethodFromCompanion() throws Exception { public void testAccessPrivateInlineClassMethodFromCompanion() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassMethodFromCompanion.kt"); runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassMethodFromCompanion.kt");
@@ -12356,6 +12356,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassCompanionMethod2.kt"); runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassCompanionMethod2.kt");
} }
@TestMetadata("accessPrivateInlineClassConstructorFromCompanion.kt")
public void testAccessPrivateInlineClassConstructorFromCompanion() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassConstructorFromCompanion.kt");
}
@TestMetadata("accessPrivateInlineClassConstructorFromLambda.kt")
public void testAccessPrivateInlineClassConstructorFromLambda() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassConstructorFromLambda.kt");
}
@TestMetadata("accessPrivateInlineClassMethodFromCompanion.kt") @TestMetadata("accessPrivateInlineClassMethodFromCompanion.kt")
public void testAccessPrivateInlineClassMethodFromCompanion() throws Exception { public void testAccessPrivateInlineClassMethodFromCompanion() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassMethodFromCompanion.kt"); runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassMethodFromCompanion.kt");
@@ -10731,6 +10731,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassCompanionMethod2.kt"); runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassCompanionMethod2.kt");
} }
@TestMetadata("accessPrivateInlineClassConstructorFromCompanion.kt")
public void testAccessPrivateInlineClassConstructorFromCompanion() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassConstructorFromCompanion.kt");
}
@TestMetadata("accessPrivateInlineClassConstructorFromLambda.kt")
public void testAccessPrivateInlineClassConstructorFromLambda() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassConstructorFromLambda.kt");
}
@TestMetadata("accessPrivateInlineClassMethodFromCompanion.kt") @TestMetadata("accessPrivateInlineClassMethodFromCompanion.kt")
public void testAccessPrivateInlineClassMethodFromCompanion() throws Exception { public void testAccessPrivateInlineClassMethodFromCompanion() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassMethodFromCompanion.kt"); runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassMethodFromCompanion.kt");
@@ -11786,6 +11786,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassCompanionMethod2.kt"); runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassCompanionMethod2.kt");
} }
@TestMetadata("accessPrivateInlineClassConstructorFromCompanion.kt")
public void testAccessPrivateInlineClassConstructorFromCompanion() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassConstructorFromCompanion.kt");
}
@TestMetadata("accessPrivateInlineClassConstructorFromLambda.kt")
public void testAccessPrivateInlineClassConstructorFromLambda() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassConstructorFromLambda.kt");
}
@TestMetadata("accessPrivateInlineClassMethodFromCompanion.kt") @TestMetadata("accessPrivateInlineClassMethodFromCompanion.kt")
public void testAccessPrivateInlineClassMethodFromCompanion() throws Exception { public void testAccessPrivateInlineClassMethodFromCompanion() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassMethodFromCompanion.kt"); runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/accessPrivateInlineClassMethodFromCompanion.kt");