KT-30419 Box inline classes in return types of covariant overrides

Use boxed version of an inline class in return type position for
covariant and generic-specialized overrides.

Also fixes KT-35234 and KT-31585.
This commit is contained in:
Dmitry Petrov
2020-03-30 12:41:48 +03:00
parent e44f12d7b0
commit 24b8495e00
31 changed files with 1296 additions and 68 deletions
@@ -10914,6 +10914,104 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/whenWithSubject.kt");
}
@TestMetadata("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class BoxReturnValueOnOverride extends AbstractIrJsCodegenBoxTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInBoxReturnValueOnOverride() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@TestMetadata("covariantOverrideErasedToAny.kt")
public void testCovariantOverrideErasedToAny() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideErasedToAny.kt");
}
@TestMetadata("covariantOverrideErasedToInterface.kt")
public void testCovariantOverrideErasedToInterface() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideErasedToInterface.kt");
}
@TestMetadata("covariantOverrideErasedToPrimitive.kt")
public void testCovariantOverrideErasedToPrimitive() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideErasedToPrimitive.kt");
}
@TestMetadata("covariantOverrideListVsMutableList.kt")
public void testCovariantOverrideListVsMutableList() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideListVsMutableList.kt");
}
@TestMetadata("covariantOverrideUnrelatedInterfaces.kt")
public void testCovariantOverrideUnrelatedInterfaces() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideUnrelatedInterfaces.kt");
}
@TestMetadata("genericOverride.kt")
public void testGenericOverride() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/genericOverride.kt");
}
@TestMetadata("genericOverrideSpecialized.kt")
public void testGenericOverrideSpecialized() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/genericOverrideSpecialized.kt");
}
@TestMetadata("inlineClassInOverriddenReturnTypes.kt")
public void testInlineClassInOverriddenReturnTypes() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/inlineClassInOverriddenReturnTypes.kt");
}
@TestMetadata("kt28483.kt")
public void testKt28483() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt28483.kt");
}
@TestMetadata("kt31585.kt")
public void testKt31585() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt31585.kt");
}
@TestMetadata("kt35234.kt")
public void testKt35234() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt35234.kt");
}
@TestMetadata("kt35234a.kt")
public void testKt35234a() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt35234a.kt");
}
@TestMetadata("relatedReturnTypes1a.kt")
public void testRelatedReturnTypes1a() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes1a.kt");
}
@TestMetadata("relatedReturnTypes1b.kt")
public void testRelatedReturnTypes1b() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes1b.kt");
}
@TestMetadata("relatedReturnTypes2a.kt")
public void testRelatedReturnTypes2a() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes2a.kt");
}
@TestMetadata("relatedReturnTypes2b.kt")
public void testRelatedReturnTypes2b() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes2b.kt");
}
@TestMetadata("unrelatedGenerics.kt")
public void testUnrelatedGenerics() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/unrelatedGenerics.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/inlineClasses/callableReferences")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -10979,6 +10979,104 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/whenWithSubject.kt");
}
@TestMetadata("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class BoxReturnValueOnOverride extends AbstractJsCodegenBoxTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
}
public void testAllFilesPresentInBoxReturnValueOnOverride() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
@TestMetadata("covariantOverrideErasedToAny.kt")
public void testCovariantOverrideErasedToAny() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideErasedToAny.kt");
}
@TestMetadata("covariantOverrideErasedToInterface.kt")
public void testCovariantOverrideErasedToInterface() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideErasedToInterface.kt");
}
@TestMetadata("covariantOverrideErasedToPrimitive.kt")
public void testCovariantOverrideErasedToPrimitive() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideErasedToPrimitive.kt");
}
@TestMetadata("covariantOverrideListVsMutableList.kt")
public void testCovariantOverrideListVsMutableList() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideListVsMutableList.kt");
}
@TestMetadata("covariantOverrideUnrelatedInterfaces.kt")
public void testCovariantOverrideUnrelatedInterfaces() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/covariantOverrideUnrelatedInterfaces.kt");
}
@TestMetadata("genericOverride.kt")
public void testGenericOverride() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/genericOverride.kt");
}
@TestMetadata("genericOverrideSpecialized.kt")
public void testGenericOverrideSpecialized() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/genericOverrideSpecialized.kt");
}
@TestMetadata("inlineClassInOverriddenReturnTypes.kt")
public void testInlineClassInOverriddenReturnTypes() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/inlineClassInOverriddenReturnTypes.kt");
}
@TestMetadata("kt28483.kt")
public void testKt28483() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt28483.kt");
}
@TestMetadata("kt31585.kt")
public void testKt31585() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt31585.kt");
}
@TestMetadata("kt35234.kt")
public void testKt35234() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt35234.kt");
}
@TestMetadata("kt35234a.kt")
public void testKt35234a() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/kt35234a.kt");
}
@TestMetadata("relatedReturnTypes1a.kt")
public void testRelatedReturnTypes1a() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes1a.kt");
}
@TestMetadata("relatedReturnTypes1b.kt")
public void testRelatedReturnTypes1b() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes1b.kt");
}
@TestMetadata("relatedReturnTypes2a.kt")
public void testRelatedReturnTypes2a() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes2a.kt");
}
@TestMetadata("relatedReturnTypes2b.kt")
public void testRelatedReturnTypes2b() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes2b.kt");
}
@TestMetadata("unrelatedGenerics.kt")
public void testUnrelatedGenerics() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/unrelatedGenerics.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/inlineClasses/callableReferences")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -50,8 +50,8 @@ class ClassModelGenerator(val context: TranslationContext) {
private fun copyDefaultMembers(descriptor: ClassDescriptor, model: JsClassModel) {
val members = descriptor.unsubstitutedMemberScope
.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
.mapNotNull { it as? CallableMemberDescriptor }
.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
.mapNotNull { it as? CallableMemberDescriptor }
// Traverse fake non-abstract member. Current class does not provide their implementation,
// it can be inherited from interface.
@@ -93,11 +93,15 @@ class ClassModelGenerator(val context: TranslationContext) {
val targetClass = member.containingDeclaration as ClassDescriptor
val fromInterfaceName = context.getNameForDescriptor(fromInterface).ident
copyMethod(context.getNameForDescriptor(fromClass).ident, fromInterfaceName + Namer.DEFAULT_PARAMETER_IMPLEMENTOR_SUFFIX,
fromClass.containingDeclaration as ClassDescriptor, targetClass, model.postDeclarationBlock)
copyMethod(fromInterfaceName, context.getNameForDescriptor(member).ident,
fromInterface.containingDeclaration as ClassDescriptor, targetClass,
model.postDeclarationBlock)
copyMethod(
context.getNameForDescriptor(fromClass).ident, fromInterfaceName + Namer.DEFAULT_PARAMETER_IMPLEMENTOR_SUFFIX,
fromClass.containingDeclaration as ClassDescriptor, targetClass, model.postDeclarationBlock
)
copyMethod(
fromInterfaceName, context.getNameForDescriptor(member).ident,
fromInterface.containingDeclaration as ClassDescriptor, targetClass,
model.postDeclarationBlock
)
return true
}
@@ -113,8 +117,7 @@ class ClassModelGenerator(val context: TranslationContext) {
if (memberToCopy is FunctionDescriptor && memberToCopy.hasOrInheritsParametersWithDefaultValue()) {
val name = context.getNameForDescriptor(member).ident + Namer.DEFAULT_PARAMETER_IMPLEMENTOR_SUFFIX
copyMethod(name, name, classToCopyFrom, descriptor, model.postDeclarationBlock)
}
else {
} else {
copyMember(member, classToCopyFrom, descriptor, model)
}
}
@@ -141,8 +144,7 @@ class ClassModelGenerator(val context: TranslationContext) {
val accessorName = context.getNameForDescriptor(accessor).ident
copyMethod(accessorName, accessorName, from, to, model.postDeclarationBlock)
}
}
else {
} else {
copyProperty(name, from, to, model.postDeclarationBlock)
}
}
@@ -182,9 +184,9 @@ class ClassModelGenerator(val context: TranslationContext) {
get() = KotlinBuiltIns.isAny(containingDeclaration as ClassDescriptor) || overriddenDescriptors.any { it.isInheritedFromAny }
private fun <T : CallableMemberDescriptor> T.findOverriddenDescriptor(
getTypedOverriddenDescriptors: T.() -> Collection<T>,
getOriginalDescriptor: T.() -> T,
filter: T.() -> Boolean
getTypedOverriddenDescriptors: T.() -> Collection<T>,
getOriginalDescriptor: T.() -> T,
filter: T.() -> Boolean
): T? {
val visitedDescriptors = mutableSetOf<T>()
val collectedDescriptors = mutableMapOf<T, T>()
@@ -195,8 +197,7 @@ class ClassModelGenerator(val context: TranslationContext) {
if (original.kind.isReal && !original.isEffectivelyExternal()) {
collectedDescriptors.putIfAbsent(original, source)
}
else {
} else {
overridden.forEach { walk(it, source) }
}
}
@@ -208,8 +209,8 @@ class ClassModelGenerator(val context: TranslationContext) {
}
private fun <T : CallableMemberDescriptor> Collection<T>.removeRepeated(
getTypedOverriddenDescriptors: T.() -> Collection<T>,
getOriginalDescriptor: T.() -> T
getTypedOverriddenDescriptors: T.() -> Collection<T>,
getOriginalDescriptor: T.() -> T
): List<T> {
val visitedDescriptors = mutableSetOf<T>()
fun walk(descriptor: T) {
@@ -234,8 +235,10 @@ class ClassModelGenerator(val context: TranslationContext) {
val sourceName = context.getNameForDescriptor(key).ident
val targetName = context.getNameForDescriptor(value).ident
if (sourceName != targetName) {
val statement = generateDelegateCall(descriptor, key, value, JsThisRef(), context, false,
descriptor.source.getPsi())
val statement = generateDelegateCall(
descriptor, key, value, JsThisRef(), context, false,
descriptor.source.getPsi()
)
model.postDeclarationBlock.statements += statement
}
}
@@ -253,7 +256,7 @@ class ClassModelGenerator(val context: TranslationContext) {
}
}
private fun generateBridge(descriptor: ClassDescriptor, model: JsClassModel, bridge: Bridge<FunctionDescriptor>) {
private fun generateBridge(descriptor: ClassDescriptor, model: JsClassModel, bridge: Bridge<FunctionDescriptor, *>) {
val fromDescriptor = bridge.from
val toDescriptor = bridge.to
@@ -267,16 +270,18 @@ class ClassModelGenerator(val context: TranslationContext) {
if (fromDescriptor.kind.isReal && fromDescriptor.modality != Modality.ABSTRACT && !toDescriptor.kind.isReal) return
}
model.postDeclarationBlock.statements += generateDelegateCall(descriptor, fromDescriptor, toDescriptor, JsThisRef(),
context, false, descriptor.source.getPsi())
model.postDeclarationBlock.statements += generateDelegateCall(
descriptor, fromDescriptor, toDescriptor, JsThisRef(),
context, false, descriptor.source.getPsi()
)
}
private fun copyMethod(
sourceName: String,
targetName: String,
sourceDescriptor: ClassDescriptor,
targetDescriptor: ClassDescriptor,
block: JsBlock
sourceName: String,
targetName: String,
sourceDescriptor: ClassDescriptor,
targetDescriptor: ClassDescriptor,
block: JsBlock
) {
if (!context.isFromCurrentModule(targetDescriptor)) return
@@ -288,10 +293,10 @@ class ClassModelGenerator(val context: TranslationContext) {
}
private fun copyProperty(
name: String,
sourceDescriptor: ClassDescriptor,
targetDescriptor: ClassDescriptor,
block: JsBlock
name: String,
sourceDescriptor: ClassDescriptor,
targetDescriptor: ClassDescriptor,
block: JsBlock
) {
if (!context.isFromCurrentModule(targetDescriptor)) return