From b3943f5ab6abe49340e532f55715811eea8a3f06 Mon Sep 17 00:00:00 2001 From: Victor Petukhov Date: Wed, 8 Dec 2021 11:31:35 +0300 Subject: [PATCH] [FE 1.0] Process builder inference stub types with different nullability properly ^KT-49887 Fixed --- .../FirBlackBoxCodegenTestGenerated.java | 6 ++ .../calls/NewCommonSuperTypeCalculator.kt | 55 ++++++++--- .../box/inference/builderInference/kt49887.kt | 12 +++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 ++ .../IrBlackBoxCodegenTestGenerated.java | 6 ++ .../LightAnalysisModeTestGenerated.java | 5 + .../diagnostics/notLinked/dfa/pos/12.kt | 92 +++++++++---------- .../diagnostics/notLinked/dfa/pos/13.kt | 92 +++++++++---------- .../jetbrains/kotlin/types/SpecialTypes.kt | 2 +- .../js/test/JsCodegenBoxTestGenerated.java | 6 ++ .../test/ir/IrJsCodegenBoxTestGenerated.java | 6 ++ .../IrCodegenBoxWasmTestGenerated.java | 5 + .../NativeExtBlackBoxTestGenerated.java | 6 ++ 13 files changed, 195 insertions(+), 104 deletions(-) create mode 100644 compiler/testData/codegen/box/inference/builderInference/kt49887.kt 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 8825a51f627..a7e376b4298 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 @@ -19052,6 +19052,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/inference/builderInference/kt49285.kt"); } + @Test + @TestMetadata("kt49887.kt") + public void testKt49887() throws Exception { + runTest("compiler/testData/codegen/box/inference/builderInference/kt49887.kt"); + } + @Test @TestMetadata("labaledCall.kt") public void testLabaledCall() throws Exception { diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt index 382b2ddff8d..e421b967b9a 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt @@ -155,6 +155,40 @@ object NewCommonSuperTypeCalculator { return supertypes } + private fun TypeSystemCommonSuperTypesContext.commonSuperTypeForBuilderInferenceStubTypes( + stubTypes: List, + stateStubTypesNotEqual: TypeCheckerState, + ): SimpleTypeMarker { + require(stubTypes.isNotEmpty()) { "There should be stub types to compute common super type on them" } + + var areAllDefNotNull = true + var areThereAnyNullable = false + val typesToUniquify = buildList { + for (stubType in stubTypes) { + when { + stubType is DefinitelyNotNullTypeMarker -> add(stubType.original()) + stubType.isMarkedNullable() -> { + areThereAnyNullable = true + areAllDefNotNull = false + add(stubType.withNullability(false)) + } + else -> { + areAllDefNotNull = false + add(stubType) + } + } + } + } + + return uniquify(typesToUniquify, stateStubTypesNotEqual).singleOrNull()?.let { + when { + areAllDefNotNull -> it.makeSimpleTypeDefinitelyNotNullOrNotNull() + areThereAnyNullable -> it.withNullability(true) + else -> it + } + } ?: nullableAnyType() + } + /* * Common Supertype calculator works with proper types and stub types (which is a replacement for non-proper types) * Also, there are two invariant related to stub types: @@ -176,20 +210,19 @@ object NewCommonSuperTypeCalculator { "There should be at least one non-stub type to compute common supertype but there are: $types" } - val nonStubTypeVariables = types.filter { !it.isStubTypeForBuilderInference() } - val areAllNonStubTypesNothing = nonStubTypeVariables.isNotEmpty() && nonStubTypeVariables.all { it.isNothing() } - if (nonStubTypeVariables.size == 1 && !areAllNonStubTypesNothing) return nonStubTypeVariables.single() + val (builderInferenceStubTypes, nonBuilderInferenceStubTypes) = types.partition { it.isStubTypeForBuilderInference() } + val areAllNonBuilderInferenceStubTypesNothing = + nonBuilderInferenceStubTypes.isNotEmpty() && nonBuilderInferenceStubTypes.all { it.isNothing() } - if (nonStubTypeVariables.isEmpty() || areAllNonStubTypesNothing) { - val stubTypeVariables = types.filter { it.isStubType() } - val uniqueStubTypes = - stubTypeVariables.distinctBy { it.asDefinitelyNotNullType()?.original()?.typeConstructor() ?: it.typeConstructor() } + if (nonBuilderInferenceStubTypes.size == 1 && !areAllNonBuilderInferenceStubTypesNothing) + return nonBuilderInferenceStubTypes.single() - if (uniqueStubTypes.size > 1) return nullableAnyType() - - if (stubTypeVariables.none { it.isDefinitelyNotNullType() }) { - return uniquify(stubTypeVariables.ifEmpty { types }, stateStubTypesNotEqual).singleOrNull() ?: return nullableAnyType() + if (builderInferenceStubTypes.isNotEmpty()) { + // Common super type between any non stub type (except Nothing) and stub one is always Any? + if (nonBuilderInferenceStubTypes.isNotEmpty() && !areAllNonBuilderInferenceStubTypesNothing) { + return nullableAnyType() } + return commonSuperTypeForBuilderInferenceStubTypes(builderInferenceStubTypes, stateStubTypesNotEqual) } val uniqueTypes = uniquify(nonTypeVariables, stateStubTypesNotEqual) diff --git a/compiler/testData/codegen/box/inference/builderInference/kt49887.kt b/compiler/testData/codegen/box/inference/builderInference/kt49887.kt new file mode 100644 index 00000000000..33a795ed6ad --- /dev/null +++ b/compiler/testData/codegen/box/inference/builderInference/kt49887.kt @@ -0,0 +1,12 @@ +// WITH_STDLIB + +fun test(): Int = buildList { + add(1) + add(2) + + val number = removeLastOrNull() ?: throw Exception() +}.singleOrNull() ?: throw Exception() + +fun box(): String { + return if (test() == 1) "OK" else "NOK" +} 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 25b9c4f63c6..98fdfe0419e 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 @@ -18662,6 +18662,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inference/builderInference/kt49285.kt"); } + @Test + @TestMetadata("kt49887.kt") + public void testKt49887() throws Exception { + runTest("compiler/testData/codegen/box/inference/builderInference/kt49887.kt"); + } + @Test @TestMetadata("labaledCall.kt") public void testLabaledCall() 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 dfd376cd2b8..66f2f5df4ba 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 @@ -19052,6 +19052,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inference/builderInference/kt49285.kt"); } + @Test + @TestMetadata("kt49887.kt") + public void testKt49887() throws Exception { + runTest("compiler/testData/codegen/box/inference/builderInference/kt49887.kt"); + } + @Test @TestMetadata("labaledCall.kt") public void testLabaledCall() 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 92736479a9d..775f6a418bd 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -15503,6 +15503,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inference/builderInference/kt49285.kt"); } + @TestMetadata("kt49887.kt") + public void testKt49887() throws Exception { + runTest("compiler/testData/codegen/box/inference/builderInference/kt49887.kt"); + } + @TestMetadata("labaledCall.kt") public void testLabaledCall() throws Exception { runTest("compiler/testData/codegen/box/inference/builderInference/labaledCall.kt"); diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/12.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/12.kt index bc6b9c4eaac..9fedede381b 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/12.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/12.kt @@ -112,8 +112,8 @@ fun T?.case_5() { equals(this) itest1() apply { - this - this + this + this equals(null) propT propAny @@ -124,30 +124,30 @@ fun T?.case_5() { funNullableT() funNullableAny() itest1() - this.equals(null) - this.propT - this.propAny - this.propNullableT - this.propNullableAny - this.funT() - this.funAny() - this.funNullableT() - this.funNullableAny() - this.itest1() + this.equals(null) + this.propT + this.propAny + this.propNullableT + this.propNullableAny + this.funT() + this.funAny() + this.funNullableT() + this.funNullableAny() + this.itest1() } also { - it - it - it.itest1() - it.equals(null) - it.propT - it.propAny - it.propNullableT - it.propNullableAny - it.funT() - it.funAny() - it.funNullableT() - it.funNullableAny() + it + it + it.itest1() + it.equals(null) + it.propT + it.propAny + it.propNullableT + it.propNullableAny + it.funT() + it.funAny() + it.funNullableT() + it.funNullableAny() } } } @@ -172,7 +172,7 @@ fun T?.case_6() { equals(this) itest1() apply { - this + this equals(null) propT propAny @@ -183,29 +183,29 @@ fun T?.case_6() { funNullableT() funNullableAny() itest1() - this.equals(null) - this.propT - this.propAny - this.propNullableT - this.propNullableAny - this.funT() - this.funAny() - this.funNullableT() - this.funNullableAny() - this.itest1() + this.equals(null) + this.propT + this.propAny + this.propNullableT + this.propNullableAny + this.funT() + this.funAny() + this.funNullableT() + this.funNullableAny() + this.itest1() } also { - it - it.itest1() - it.equals(null) - it.propT - it.propAny - it.propNullableT - it.propNullableAny - it.funT() - it.funAny() - it.funNullableT() - it.funNullableAny() + it + it.itest1() + it.equals(null) + it.propT + it.propAny + it.propNullableT + it.propNullableAny + it.funT() + it.funAny() + it.funNullableT() + it.funNullableAny() } } } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/13.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/13.kt index d5c94d1a591..c781d0f2b60 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/13.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/13.kt @@ -148,8 +148,8 @@ fun case_5(x: T?) { x.funNullableAny() x.itest() x.apply { - this - this + this + this equals(null) propT propAny @@ -160,30 +160,30 @@ fun case_5(x: T?) { funNullableT() funNullableAny() itest() - this.equals(null) - this.propT - this.propAny - this.propNullableT - this.propNullableAny - this.funT() - this.funAny() - this.funNullableT() - this.funNullableAny() - this.itest() + this.equals(null) + this.propT + this.propAny + this.propNullableT + this.propNullableAny + this.funT() + this.funAny() + this.funNullableT() + this.funNullableAny() + this.itest() } x.also { - it - it - it.itest() - it.equals(null) - it.propT - it.propAny - it.propNullableT - it.propNullableAny - it.funT() - it.funAny() - it.funNullableT() - it.funNullableAny() + it + it + it.itest() + it.equals(null) + it.propT + it.propAny + it.propNullableT + it.propNullableAny + it.funT() + it.funAny() + it.funNullableT() + it.funNullableAny() } } } @@ -224,7 +224,7 @@ fun case_6(x: T?) { x.funNullableAny() x.itest() x.apply { - this + this equals(null) propT propAny @@ -235,29 +235,29 @@ fun case_6(x: T?) { funNullableT() funNullableAny() itest() - this.equals(null) - this.propT - this.propAny - this.propNullableT - this.propNullableAny - this.funT() - this.funAny() - this.funNullableT() - this.funNullableAny() - this.itest() + this.equals(null) + this.propT + this.propAny + this.propNullableT + this.propNullableAny + this.funT() + this.funAny() + this.funNullableT() + this.funNullableAny() + this.itest() } x.also { - it - it.itest() - it.equals(null) - it.propT - it.propAny - it.propNullableT - it.propNullableAny - it.funT() - it.funAny() - it.funNullableT() - it.funNullableAny() + it + it.itest() + it.equals(null) + it.propT + it.propAny + it.propNullableT + it.propNullableAny + it.funT() + it.funAny() + it.funNullableT() + it.funNullableAny() } } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/SpecialTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/types/SpecialTypes.kt index aa0ebe3d023..88bdd009736 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/SpecialTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/SpecialTypes.kt @@ -112,7 +112,7 @@ class DefinitelyNotNullType private constructor( } - DefinitelyNotNullType(type.lowerIfFlexible(), useCorrectedNullabilityForTypeParameters) + DefinitelyNotNullType(type.lowerIfFlexible().makeNullableAsSpecified(false), useCorrectedNullabilityForTypeParameters) } else -> null 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 2ae4e699c9b..8c16281e7b4 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 @@ -14608,6 +14608,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inference/builderInference/kt49285.kt"); } + @Test + @TestMetadata("kt49887.kt") + public void testKt49887() throws Exception { + runTest("compiler/testData/codegen/box/inference/builderInference/kt49887.kt"); + } + @Test @TestMetadata("labaledCall.kt") public void testLabaledCall() 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 fdb90442692..f1f22ec73c8 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 @@ -14572,6 +14572,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inference/builderInference/kt49285.kt"); } + @Test + @TestMetadata("kt49887.kt") + public void testKt49887() throws Exception { + runTest("compiler/testData/codegen/box/inference/builderInference/kt49887.kt"); + } + @Test @TestMetadata("labaledCall.kt") public void testLabaledCall() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index 82fa278269f..60fdfbc3e46 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -12265,6 +12265,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/inference/builderInference/kt48445.kt"); } + @TestMetadata("kt49887.kt") + public void testKt49887() throws Exception { + runTest("compiler/testData/codegen/box/inference/builderInference/kt49887.kt"); + } + @TestMetadata("labaledCall.kt") public void testLabaledCall() throws Exception { runTest("compiler/testData/codegen/box/inference/builderInference/labaledCall.kt"); diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeExtBlackBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeExtBlackBoxTestGenerated.java index a079deb7b64..9aaaa5a0c45 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeExtBlackBoxTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeExtBlackBoxTestGenerated.java @@ -15465,6 +15465,12 @@ public class NativeExtBlackBoxTestGenerated extends AbstractNativeBlackBoxTest { runTest("compiler/testData/codegen/box/inference/builderInference/kt49285.kt"); } + @Test + @TestMetadata("kt49887.kt") + public void testKt49887() throws Exception { + runTest("compiler/testData/codegen/box/inference/builderInference/kt49887.kt"); + } + @Test @TestMetadata("labaledCall.kt") public void testLabaledCall() throws Exception {