diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 3ee90b681db..99da23f71e1 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -46581,6 +46581,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/regressions/objectInsideDelegation.kt"); } + @Test + @TestMetadata("recursiveDnnTypeInLambda.kt") + public void testRecursiveDnnTypeInLambda() throws Exception { + runTest("compiler/testData/codegen/box/regressions/recursiveDnnTypeInLambda.kt"); + } + @Test @TestMetadata("referenceToSelfInLocal.kt") public void testReferenceToSelfInLocal() throws Exception { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBasedDescriptors.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBasedDescriptors.kt index def9920b8eb..322542d172e 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBasedDescriptors.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBasedDescriptors.kt @@ -1150,7 +1150,9 @@ fun IrType.toIrBasedKotlinType(): KotlinType = when (this) { is IrSimpleType -> makeKotlinType(classifier, arguments, isMarkedNullable()).let { if (classifier is IrTypeParameterSymbol && nullability == SimpleTypeNullability.DEFINITELY_NOT_NULL) { - DefinitelyNotNullType.makeDefinitelyNotNull(it.unwrap()) ?: it + // avoidCheckingActualTypeNullability = true is necessary because in recursive cases `makesSenseToBeDefinitelyNotNull` triggers + // supertype computation for a type parameter and for which bounds we need to call `toIrBasedKotlinType` again + DefinitelyNotNullType.makeDefinitelyNotNull(it.unwrap(), avoidCheckingActualTypeNullability = true) ?: it } else { it } diff --git a/compiler/testData/codegen/box/regressions/recursiveDnnTypeInLambda.kt b/compiler/testData/codegen/box/regressions/recursiveDnnTypeInLambda.kt new file mode 100644 index 00000000000..62257fa0b5a --- /dev/null +++ b/compiler/testData/codegen/box/regressions/recursiveDnnTypeInLambda.kt @@ -0,0 +1,15 @@ +fun ?> foo( + value: T, + range: CR +) = value?.run { toString() } ?: "fail" + +interface In +interface CR + +class Impl : In { + override fun toString(): String = "OK" +} + +fun box(): String { + return foo(Impl(), object : CR {}) +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 2e7e67ed3a3..e4545667077 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -44505,6 +44505,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/regressions/objectInsideDelegation.kt"); } + @Test + @TestMetadata("recursiveDnnTypeInLambda.kt") + public void testRecursiveDnnTypeInLambda() throws Exception { + runTest("compiler/testData/codegen/box/regressions/recursiveDnnTypeInLambda.kt"); + } + @Test @TestMetadata("referenceToSelfInLocal.kt") public void testReferenceToSelfInLocal() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 26ab8d2d74d..4dde1c726cc 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -46581,6 +46581,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/regressions/objectInsideDelegation.kt"); } + @Test + @TestMetadata("recursiveDnnTypeInLambda.kt") + public void testRecursiveDnnTypeInLambda() throws Exception { + runTest("compiler/testData/codegen/box/regressions/recursiveDnnTypeInLambda.kt"); + } + @Test @TestMetadata("referenceToSelfInLocal.kt") public void testReferenceToSelfInLocal() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 8d4855c5cd0..7406598b807 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -35869,6 +35869,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/regressions/objectInsideDelegation.kt"); } + @TestMetadata("recursiveDnnTypeInLambda.kt") + public void testRecursiveDnnTypeInLambda() throws Exception { + runTest("compiler/testData/codegen/box/regressions/recursiveDnnTypeInLambda.kt"); + } + @TestMetadata("referenceToSelfInLocal.kt") public void testReferenceToSelfInLocal() throws Exception { runTest("compiler/testData/codegen/box/regressions/referenceToSelfInLocal.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/SpecialTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/types/SpecialTypes.kt index 9c436a7ac3e..f568eb15ce1 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/SpecialTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/SpecialTypes.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.types import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.storage.StorageManager @@ -97,14 +96,22 @@ class DefinitelyNotNullType private constructor( DefinitelyNotNullTypeMarker { companion object { + // Having `@JvmOverloads` just to make sure we don't break ABI compatibility + @JvmOverloads fun makeDefinitelyNotNull( type: UnwrappedType, - useCorrectedNullabilityForTypeParameters: Boolean = false + useCorrectedNullabilityForTypeParameters: Boolean = false, + // Should be used when we are sure that original type is nullable, i.e. makesSenseToBeDefinitelyNotNull would return true, + // but we can't actually call it because otherwise we would fail with StackOverFlow because supertypes are being computed recursively + // and there's no easy way to prevent recursion. + // NB: makesSenseToBeDefinitelyNotNull is mostly needed as an optimization because nothing really bad would happen even if we + // create DNN for a type parameter with non-nullable bound. + avoidCheckingActualTypeNullability: Boolean = false, ): DefinitelyNotNullType? { return when { type is DefinitelyNotNullType -> type - makesSenseToBeDefinitelyNotNull(type, useCorrectedNullabilityForTypeParameters) -> { + avoidCheckingActualTypeNullability || makesSenseToBeDefinitelyNotNull(type, useCorrectedNullabilityForTypeParameters) -> { if (type is FlexibleType) { assert(type.lowerBound.constructor == type.upperBound.constructor) { "DefinitelyNotNullType for flexible type ($type) can be created only from type variable with the same constructor for bounds" diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java index 1d666001aeb..c2907fa58a2 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java @@ -33377,6 +33377,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/regressions/objectInsideDelegation.kt"); } + @Test + @TestMetadata("recursiveDnnTypeInLambda.kt") + public void testRecursiveDnnTypeInLambda() throws Exception { + runTest("compiler/testData/codegen/box/regressions/recursiveDnnTypeInLambda.kt"); + } + @Test @TestMetadata("resolvedCallForGetOperator.kt") public void testResolvedCallForGetOperator() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java index 78546d84d10..af60f4a873c 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java @@ -33557,6 +33557,12 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest { runTest("compiler/testData/codegen/box/regressions/objectInsideDelegation.kt"); } + @Test + @TestMetadata("recursiveDnnTypeInLambda.kt") + public void testRecursiveDnnTypeInLambda() throws Exception { + runTest("compiler/testData/codegen/box/regressions/recursiveDnnTypeInLambda.kt"); + } + @Test @TestMetadata("resolvedCallForGetOperator.kt") public void testResolvedCallForGetOperator() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java index 0b3540d8138..d93f384e13b 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java @@ -33557,6 +33557,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/regressions/objectInsideDelegation.kt"); } + @Test + @TestMetadata("recursiveDnnTypeInLambda.kt") + public void testRecursiveDnnTypeInLambda() throws Exception { + runTest("compiler/testData/codegen/box/regressions/recursiveDnnTypeInLambda.kt"); + } + @Test @TestMetadata("resolvedCallForGetOperator.kt") public void testResolvedCallForGetOperator() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.java index 849f2955a97..855a3b78d9e 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.java @@ -33557,6 +33557,12 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes runTest("compiler/testData/codegen/box/regressions/objectInsideDelegation.kt"); } + @Test + @TestMetadata("recursiveDnnTypeInLambda.kt") + public void testRecursiveDnnTypeInLambda() throws Exception { + runTest("compiler/testData/codegen/box/regressions/recursiveDnnTypeInLambda.kt"); + } + @Test @TestMetadata("resolvedCallForGetOperator.kt") public void testResolvedCallForGetOperator() throws Exception { diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/K2NativeCodegenBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/K2NativeCodegenBoxTestGenerated.java index baf25cb0b27..33de7461055 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/K2NativeCodegenBoxTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/K2NativeCodegenBoxTestGenerated.java @@ -37077,6 +37077,12 @@ public class K2NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTes runTest("compiler/testData/codegen/box/regressions/objectInsideDelegation.kt"); } + @Test + @TestMetadata("recursiveDnnTypeInLambda.kt") + public void testRecursiveDnnTypeInLambda() throws Exception { + runTest("compiler/testData/codegen/box/regressions/recursiveDnnTypeInLambda.kt"); + } + @Test @TestMetadata("resolvedCallForGetOperator.kt") public void testResolvedCallForGetOperator() throws Exception { diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java index 5e447212ac0..18565d71ce7 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java @@ -36620,6 +36620,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest runTest("compiler/testData/codegen/box/regressions/objectInsideDelegation.kt"); } + @Test + @TestMetadata("recursiveDnnTypeInLambda.kt") + public void testRecursiveDnnTypeInLambda() throws Exception { + runTest("compiler/testData/codegen/box/regressions/recursiveDnnTypeInLambda.kt"); + } + @Test @TestMetadata("resolvedCallForGetOperator.kt") public void testResolvedCallForGetOperator() throws Exception { diff --git a/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/IrCodegenBoxWasmTestGenerated.java b/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/IrCodegenBoxWasmTestGenerated.java index 2f123ae416a..c85df56b4b3 100644 --- a/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/IrCodegenBoxWasmTestGenerated.java +++ b/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/IrCodegenBoxWasmTestGenerated.java @@ -30039,6 +30039,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/regressions/objectInsideDelegation.kt"); } + @TestMetadata("recursiveDnnTypeInLambda.kt") + public void testRecursiveDnnTypeInLambda() throws Exception { + runTest("compiler/testData/codegen/box/regressions/recursiveDnnTypeInLambda.kt"); + } + @TestMetadata("resolvedCallForGetOperator.kt") public void testResolvedCallForGetOperator() throws Exception { runTest("compiler/testData/codegen/box/regressions/resolvedCallForGetOperator.kt");