From b02a9846d043d79ffd81217f9b52ee32e7a9f988 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Mon, 11 Jan 2021 13:43:01 +0300 Subject: [PATCH] IR KT-44233 support flexible nullability in IrTypeSystemContext ^KT-44233 Fixed Target versions 1.5-M1 --- .../ir/FirBlackBoxCodegenTestGenerated.java | 5 +++ .../kotlin/ir/types/IrTypeSystemContext.kt | 25 +++++++++--- .../org/jetbrains/kotlin/ir/types/irTypes.kt | 23 +++++------ .../ir/types/jvmSpecificFlexibleTypes.kt | 39 +++++++++++++++++++ .../codegen/box/collections/kt44233.kt | 18 +++++++++ .../collectionStubs/kt44233.kt | 14 +++++++ .../collectionStubs/kt44233.txt | 15 +++++++ .../collectionStubs/kt44233_ir.txt | 15 +++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 +++ .../codegen/BytecodeListingTestGenerated.java | 5 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++ .../ir/IrBytecodeListingTestGenerated.java | 5 +++ 13 files changed, 163 insertions(+), 16 deletions(-) create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/jvmSpecificFlexibleTypes.kt create mode 100644 compiler/testData/codegen/box/collections/kt44233.kt create mode 100644 compiler/testData/codegen/bytecodeListing/collectionStubs/kt44233.kt create mode 100644 compiler/testData/codegen/bytecodeListing/collectionStubs/kt44233.txt create mode 100644 compiler/testData/codegen/bytecodeListing/collectionStubs/kt44233_ir.txt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 779843e3493..6849164f38c 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -5068,6 +5068,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/collections/kt41123.kt"); } + @TestMetadata("kt44233.kt") + public void testKt44233() throws Exception { + runTest("compiler/testData/codegen/box/collections/kt44233.kt"); + } + @TestMetadata("mutableList.kt") public void testMutableList() throws Exception { runTest("compiler/testData/codegen/box/collections/mutableList.kt"); diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt index e9dd29d08ac..e6a34e2a4ed 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt @@ -33,7 +33,16 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon override fun KotlinTypeMarker.asSimpleType() = this as? SimpleTypeMarker - override fun KotlinTypeMarker.asFlexibleType() = this as? IrDynamicType + override fun KotlinTypeMarker.asFlexibleType(): FlexibleTypeMarker? { + if (this is FlexibleTypeMarker) return this + + if (this is IrType) { + val jvmFlexibleType = this.asJvmFlexibleType() + if (jvmFlexibleType != null) return jvmFlexibleType + } + + return null + } override fun KotlinTypeMarker.isError() = this is IrErrorType @@ -44,13 +53,19 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon override fun FlexibleTypeMarker.asRawType(): RawTypeMarker? = null override fun FlexibleTypeMarker.upperBound(): SimpleTypeMarker { - require(this is IrDynamicType) - return irBuiltIns.anyNType as IrSimpleType + return when (this) { + is IrDynamicType -> irBuiltIns.anyNType as IrSimpleType + is IrJvmFlexibleType -> this.upperBound + else -> error("Unexpected flexible type ${this::class.java.simpleName}: $this") + } } override fun FlexibleTypeMarker.lowerBound(): SimpleTypeMarker { - require(this is IrDynamicType) - return irBuiltIns.nothingType as IrSimpleType + return when (this) { + is IrDynamicType -> irBuiltIns.nothingType as IrSimpleType + is IrJvmFlexibleType -> this.lowerBound + else -> error("Unexpected flexible type ${this::class.java.simpleName}: $this") + } } override fun SimpleTypeMarker.asCapturedType(): CapturedTypeMarker? = null diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt index a7427edd14b..50298b854d5 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt @@ -21,7 +21,6 @@ import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.isAnonymousObject import org.jetbrains.kotlin.ir.util.isPropertyAccessor import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.types.typeUtil.makeNullable @@ -30,19 +29,21 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs fun IrType.withHasQuestionMark(newHasQuestionMark: Boolean): IrType = when (this) { - is IrSimpleType -> - if (this.hasQuestionMark == newHasQuestionMark) - this - else - buildSimpleType { - hasQuestionMark = newHasQuestionMark - kotlinType = originalKotlinType?.run { - if (newHasQuestionMark) makeNullable() else makeNotNullable() - } - } + is IrSimpleType -> withHasQuestionMark(newHasQuestionMark) else -> this } +fun IrSimpleType.withHasQuestionMark(newHasQuestionMark: Boolean): IrSimpleType = + if (this.hasQuestionMark == newHasQuestionMark) + this + else + buildSimpleType { + hasQuestionMark = newHasQuestionMark + kotlinType = originalKotlinType?.run { + if (newHasQuestionMark) makeNullable() else makeNotNullable() + } + } + fun IrType.addAnnotations(newAnnotations: List): IrType = if (newAnnotations.isEmpty()) this diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/jvmSpecificFlexibleTypes.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/jvmSpecificFlexibleTypes.kt new file mode 100644 index 00000000000..7f927cc3ca6 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/jvmSpecificFlexibleTypes.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ir.types + +import org.jetbrains.kotlin.ir.util.hasAnnotation +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.types.model.FlexibleTypeMarker +import org.jetbrains.kotlin.types.model.SimpleTypeMarker + +internal interface IrJvmFlexibleType : FlexibleTypeMarker { + val lowerBound: SimpleTypeMarker + val upperBound: SimpleTypeMarker +} + +internal class IrJvmFlexibleNullabilityType(val irType: IrSimpleType) : IrJvmFlexibleType { + override val lowerBound get() = irType.withHasQuestionMark(false) + override val upperBound get() = irType.withHasQuestionMark(true) +} + +internal val FLEXIBLE_NULLABILITY_FQN = FqName("kotlin.internal.ir").child(Name.identifier("FlexibleNullability")) + +internal fun IrType.isWithFlexibleNullability() = + hasAnnotation(FLEXIBLE_NULLABILITY_FQN) + +internal fun IrType.asJvmFlexibleType() = + when { + this is IrSimpleType && isWithFlexibleNullability() -> + IrJvmFlexibleNullabilityType( + this.removeAnnotations { irCtorCall -> + irCtorCall.type.classFqName == FLEXIBLE_NULLABILITY_FQN + } as IrSimpleType + ) + else -> + null + } \ No newline at end of file diff --git a/compiler/testData/codegen/box/collections/kt44233.kt b/compiler/testData/codegen/box/collections/kt44233.kt new file mode 100644 index 00000000000..5d2cb6cb2b1 --- /dev/null +++ b/compiler/testData/codegen/box/collections/kt44233.kt @@ -0,0 +1,18 @@ +// TARGET_BACKEND: JVM +// IGNORE_BACKEND_FIR: JVM_IR +// FULL_JDK + +import java.util.concurrent.ConcurrentSkipListSet + +class StringIterable : Iterable { + private val strings = ConcurrentSkipListSet() + override fun iterator() = strings.iterator() +} + +fun box(): String { + val si = StringIterable() + return if (si.iterator().hasNext()) + "Failed" + else + "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/collectionStubs/kt44233.kt b/compiler/testData/codegen/bytecodeListing/collectionStubs/kt44233.kt new file mode 100644 index 00000000000..4772276359a --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/collectionStubs/kt44233.kt @@ -0,0 +1,14 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// FULL_JDK + +import java.util.concurrent.* + +class Test1 : Iterable { + private val received = ConcurrentSkipListSet() + override fun iterator() = received.iterator() +} + +class Test2 : Iterable { + private val received = Array(0) { "" } + override fun iterator() = received.iterator() +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/collectionStubs/kt44233.txt b/compiler/testData/codegen/bytecodeListing/collectionStubs/kt44233.txt new file mode 100644 index 00000000000..9129aa0d9b4 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/collectionStubs/kt44233.txt @@ -0,0 +1,15 @@ +@kotlin.Metadata +public final class Test1 { + // source: 'kt44233.kt' + private final field received: java.util.concurrent.ConcurrentSkipListSet + public method (): void + public @org.jetbrains.annotations.NotNull method iterator(): java.util.Iterator +} + +@kotlin.Metadata +public final class Test2 { + // source: 'kt44233.kt' + private final field received: java.lang.String[] + public method (): void + public @org.jetbrains.annotations.NotNull method iterator(): java.util.Iterator +} diff --git a/compiler/testData/codegen/bytecodeListing/collectionStubs/kt44233_ir.txt b/compiler/testData/codegen/bytecodeListing/collectionStubs/kt44233_ir.txt new file mode 100644 index 00000000000..342ea4b02f4 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/collectionStubs/kt44233_ir.txt @@ -0,0 +1,15 @@ +@kotlin.Metadata +public final class Test1 { + // source: 'kt44233.kt' + private final @org.jetbrains.annotations.NotNull field received: java.util.concurrent.ConcurrentSkipListSet + public method (): void + public @org.jetbrains.annotations.NotNull method iterator(): java.util.Iterator +} + +@kotlin.Metadata +public final class Test2 { + // source: 'kt44233.kt' + private final @org.jetbrains.annotations.NotNull field received: java.lang.String[] + public method (): void + public @org.jetbrains.annotations.NotNull method iterator(): java.util.Iterator +} diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 7c749d7fd15..7692c587f8e 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -5068,6 +5068,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/collections/kt41123.kt"); } + @TestMetadata("kt44233.kt") + public void testKt44233() throws Exception { + runTest("compiler/testData/codegen/box/collections/kt44233.kt"); + } + @TestMetadata("mutableList.kt") public void testMutableList() throws Exception { runTest("compiler/testData/codegen/box/collections/mutableList.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index 436776ab37a..d54049b27e8 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -410,6 +410,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/inheritingFromAbstractMutableList.kt"); } + @TestMetadata("kt44233.kt") + public void testKt44233() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/kt44233.kt"); + } + @TestMetadata("mapOfPrimitivesFullJdk.kt") public void testMapOfPrimitivesFullJdk() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/mapOfPrimitivesFullJdk.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 1faddd7267d..002c29dda39 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -5068,6 +5068,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/collections/kt41123.kt"); } + @TestMetadata("kt44233.kt") + public void testKt44233() throws Exception { + runTest("compiler/testData/codegen/box/collections/kt44233.kt"); + } + @TestMetadata("mutableList.kt") public void testMutableList() throws Exception { runTest("compiler/testData/codegen/box/collections/mutableList.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 03082fce39e..2c8b40a254d 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -5068,6 +5068,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/collections/kt41123.kt"); } + @TestMetadata("kt44233.kt") + public void testKt44233() throws Exception { + runTest("compiler/testData/codegen/box/collections/kt44233.kt"); + } + @TestMetadata("mutableList.kt") public void testMutableList() throws Exception { runTest("compiler/testData/codegen/box/collections/mutableList.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java index a9ef97c564d..e1e072ffb74 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java @@ -410,6 +410,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/inheritingFromAbstractMutableList.kt"); } + @TestMetadata("kt44233.kt") + public void testKt44233() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/kt44233.kt"); + } + @TestMetadata("mapOfPrimitivesFullJdk.kt") public void testMapOfPrimitivesFullJdk() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/mapOfPrimitivesFullJdk.kt");