From 2b3f34cc5227abbe18b27a87b7733847d251610d Mon Sep 17 00:00:00 2001 From: "Denis.Zharkov" Date: Wed, 7 Dec 2022 15:32:46 +0100 Subject: [PATCH] K2: Fix false-positive type equality for different captured types This is mostly a revert of 2f61a2f56f55a55c8a11efde94bc5984418a8cab There, we erroneously assumed that we may take captured types as equal if they are based on the same-typed projections. Each instance of capturing defines its own captured type, that should not be equal to any other type captured in other place. Initial motivation was brought by FP Ultimate, where a piece of code from the new test was found that started working differently after recent changes. The most obvious consequence is the change in addAllProjection.fir.kt: one cannot use an instance as an argument when expected type is captured type based on the same instance. Otherwise, it would lead to CCE if we allowed to put arbitrary charsequences to the list that initially was a MutableList All other test data changes (but addAllProjection.fir.kt and differentCapturedTypes.kt) are irrelevant and will be fixed in the subsequent commits --- ...CompilerTestFE10TestdataTestGenerated.java | 6 ++++++ ...irOldFrontendDiagnosticsTestGenerated.java | 6 ++++++ ...DiagnosticsWithLightTreeTestGenerated.java | 6 ++++++ .../jetbrains/kotlin/fir/types/ConeTypes.kt | 6 ++---- ...proximateContravariantCapturedTypes.fir.kt | 20 +++++++++---------- .../capturedTypes/differentCapturedTypes.kt | 18 +++++++++++++++++ .../tests/smartCasts/inference/kt25432.fir.kt | 2 +- ...rtCastOnValueBoundToSubjectVariable.fir.kt | 4 ++-- .../testsWithStdLib/addAllProjection.fir.kt | 2 +- .../test/runners/DiagnosticTestGenerated.java | 6 ++++++ 10 files changed, 58 insertions(+), 18 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inference/capturedTypes/differentCapturedTypes.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index b8b28132200..cd12372aa54 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -15195,6 +15195,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturingFromArgumentOfFlexibleType.kt"); } + @Test + @TestMetadata("differentCapturedTypes.kt") + public void testDifferentCapturedTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/differentCapturedTypes.kt"); + } + @Test @TestMetadata("dontCheckNewCapturedTypeSpecificChecksForOldOnes.kt") public void testDontCheckNewCapturedTypeSpecificChecksForOldOnes() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index a3238759a57..591dc323423 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -15201,6 +15201,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturingFromArgumentOfFlexibleType.kt"); } + @Test + @TestMetadata("differentCapturedTypes.kt") + public void testDifferentCapturedTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/differentCapturedTypes.kt"); + } + @Test @TestMetadata("dontCheckNewCapturedTypeSpecificChecksForOldOnes.kt") public void testDontCheckNewCapturedTypeSpecificChecksForOldOnes() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index d47ba025319..4e860627d17 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -15195,6 +15195,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturingFromArgumentOfFlexibleType.kt"); } + @Test + @TestMetadata("differentCapturedTypes.kt") + public void testDifferentCapturedTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/differentCapturedTypes.kt"); + } + @Test @TestMetadata("dontCheckNewCapturedTypeSpecificChecksForOldOnes.kt") public void testDontCheckNewCapturedTypeSpecificChecksForOldOnes() throws Exception { diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt index 03b9e603493..98668fae190 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt @@ -150,8 +150,7 @@ data class ConeCapturedType( other as ConeCapturedType if (lowerType != other.lowerType) return false - if (constructor.projection != other.constructor.projection) return false - if (constructor.typeParameterMarker != other.constructor.typeParameterMarker) return false + if (constructor != other.constructor) return false if (captureStatus != other.captureStatus) return false if (nullability != other.nullability) return false @@ -161,8 +160,7 @@ data class ConeCapturedType( override fun hashCode(): Int { var result = 7 result = 31 * result + (lowerType?.hashCode() ?: 0) - result = 31 * result + constructor.projection.hashCode() - result = 31 * result + constructor.typeParameterMarker.hashCode() + result = 31 * result + constructor.hashCode() result = 31 * result + captureStatus.hashCode() result = 31 * result + nullability.hashCode() return result diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/approximateContravariantCapturedTypes.fir.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/approximateContravariantCapturedTypes.fir.kt index 56481fbde2f..64f52361d33 100644 --- a/compiler/testData/diagnostics/tests/inference/capturedTypes/approximateContravariantCapturedTypes.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/approximateContravariantCapturedTypes.fir.kt @@ -26,15 +26,15 @@ fun Float.bar() {} fun id(x: K) = x fun test1() { - val fooSetRef = , CapturedType(*), CapturedType(*)>")!>Foo<*>::setX + val fooSetRef = Foo<*>::setX - val fooSetRef2 = , kotlin.Nothing, kotlin.Number>")!>id( - , CapturedType(*), CapturedType(*)>")!>Foo<*>::setX + val fooSetRef2 = id( + Foo<*>::setX ) val foo = Foo(1f) - fooSetRef.invoke(foo, 1) - fooSetRef2.invoke(foo, 1) + fooSetRef.invoke(foo, 1) + fooSetRef2.invoke(foo, 1) foo.x.bar() } @@ -53,14 +53,14 @@ fun test2() { } fun test3() { - val fooSetRef = , CapturedType(*), CapturedType(*)>")!>Foo2<*>::setX - val fooSetRef2 = , kotlin.Nothing, kotlin.Any?>")!>id( - , CapturedType(*), CapturedType(*)>")!>Foo2<*>::setX + val fooSetRef = Foo2<*>::setX + val fooSetRef2 = id( + Foo2<*>::setX ) val foo = Foo2(1) - fooSetRef.invoke(foo, "") - fooSetRef2.invoke(foo, "") + fooSetRef.invoke(foo, "") + fooSetRef2.invoke(foo, "") foo.x.bar() } diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/differentCapturedTypes.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/differentCapturedTypes.kt new file mode 100644 index 00000000000..65e0cbea0a3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/differentCapturedTypes.kt @@ -0,0 +1,18 @@ +// FIR_IDENTICAL +// SKIP_TXT + +fun select(vararg x: X): X = x[0] +fun myE(): Out? = null + +interface Out + +fun foo(w: Out<*>) { + // To have inference working we need both instances of `w` expressions captured to a different captured types instances + // that return `false` when comparing them via `equals`. + // + // Otherwise, due to some complicated inferences implementation details that are not really relevant, + // we've got NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER here. + // + // Anyway, this code should be definitely green and this test ensures it. + select(w, myE() ?: w) +} diff --git a/compiler/testData/diagnostics/tests/smartCasts/inference/kt25432.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/inference/kt25432.fir.kt index fad47bd5e27..15e4c2c716c 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/inference/kt25432.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/inference/kt25432.fir.kt @@ -4,7 +4,7 @@ class Data(val s: T) fun test(d: Data) { if (d.s is String) { - d.s.length + d.s.length } } diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartCastOnValueBoundToSubjectVariable.fir.kt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartCastOnValueBoundToSubjectVariable.fir.kt index f74066d400b..d98e52b8cf0 100644 --- a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartCastOnValueBoundToSubjectVariable.fir.kt +++ b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartCastOnValueBoundToSubjectVariable.fir.kt @@ -43,6 +43,6 @@ fun test5(x: Inv) { fun test6(x: Inv) { when (val y = x.data) { - is String -> x.data.length // should be ok + is String -> x.data.length // should be ok } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/addAllProjection.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/addAllProjection.fir.kt index 6b45cf7601d..9c3f8d9fcd3 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/addAllProjection.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/addAllProjection.fir.kt @@ -1,6 +1,6 @@ fun test(mc: MutableCollection) { - mc.addAll(mc) + mc.addAll(mc) mc.addAll(arrayListOf()) mc.addAll(arrayListOf()) diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index a02a365c895..374d95de6ba 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -15201,6 +15201,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturingFromArgumentOfFlexibleType.kt"); } + @Test + @TestMetadata("differentCapturedTypes.kt") + public void testDifferentCapturedTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/differentCapturedTypes.kt"); + } + @Test @TestMetadata("dontCheckNewCapturedTypeSpecificChecksForOldOnes.kt") public void testDontCheckNewCapturedTypeSpecificChecksForOldOnes() throws Exception {