K2: Fix false-positive type equality for different captured types
This is mostly a revert of 2f61a2f56f
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<String>
All other test data changes (but addAllProjection.fir.kt and differentCapturedTypes.kt)
are irrelevant and will be fixed in the subsequent commits
This commit is contained in:
committed by
Space Team
parent
181f23bd8d
commit
2b3f34cc52
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
+10
-10
@@ -26,15 +26,15 @@ fun Float.bar() {}
|
||||
fun <K> id(x: K) = x
|
||||
|
||||
fun test1() {
|
||||
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, CapturedType(*), CapturedType(*)>")!>Foo<*>::setX<!>
|
||||
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved reference: setX")!>Foo<*>::<!UNRESOLVED_REFERENCE!>setX<!><!>
|
||||
|
||||
val fooSetRef2 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, kotlin.Nothing, kotlin.Number>")!>id(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, CapturedType(*), CapturedType(*)>")!>Foo<*>::setX<!>
|
||||
val fooSetRef2 = <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Cannot infer argument for type parameter K")!><!INAPPLICABLE_CANDIDATE!>id<!>(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved reference: setX")!>Foo<*>::<!UNRESOLVED_REFERENCE!>setX<!><!>
|
||||
)<!>
|
||||
val foo = Foo<Float>(1f)
|
||||
|
||||
fooSetRef.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>1<!>)
|
||||
fooSetRef2.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>1<!>)
|
||||
fooSetRef.<!UNRESOLVED_REFERENCE!>invoke<!>(foo, 1)
|
||||
fooSetRef2.<!UNRESOLVED_REFERENCE!>invoke<!>(foo, 1)
|
||||
|
||||
foo.x.bar()
|
||||
}
|
||||
@@ -53,14 +53,14 @@ fun test2() {
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, CapturedType(*), CapturedType(*)>")!>Foo2<*>::setX<!>
|
||||
val fooSetRef2 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, kotlin.Nothing, kotlin.Any?>")!>id(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, CapturedType(*), CapturedType(*)>")!>Foo2<*>::setX<!>
|
||||
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved reference: setX")!>Foo2<*>::<!UNRESOLVED_REFERENCE!>setX<!><!>
|
||||
val fooSetRef2 = <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Cannot infer argument for type parameter K")!><!INAPPLICABLE_CANDIDATE!>id<!>(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved reference: setX")!>Foo2<*>::<!UNRESOLVED_REFERENCE!>setX<!><!>
|
||||
)<!>
|
||||
val foo = Foo2<Int>(1)
|
||||
|
||||
fooSetRef.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>""<!>)
|
||||
fooSetRef2.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>""<!>)
|
||||
fooSetRef.<!UNRESOLVED_REFERENCE!>invoke<!>(foo, "")
|
||||
fooSetRef2.<!UNRESOLVED_REFERENCE!>invoke<!>(foo, "")
|
||||
|
||||
foo.x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>bar<!>()
|
||||
}
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// FIR_IDENTICAL
|
||||
// SKIP_TXT
|
||||
|
||||
fun <X> select(vararg x: X): X = x[0]
|
||||
fun <E> myE(): Out<E>? = null
|
||||
|
||||
interface Out<out T>
|
||||
|
||||
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)
|
||||
}
|
||||
@@ -4,7 +4,7 @@ class Data<T>(val s: T)
|
||||
|
||||
fun test(d: Data<out Any>) {
|
||||
if (d.s is String) {
|
||||
d.s.length
|
||||
d.s.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -43,6 +43,6 @@ fun test5(x: Inv<out Any?>) {
|
||||
|
||||
fun test6(x: Inv<out String?>) {
|
||||
when (val y = x.data) {
|
||||
is String -> x.data.length // should be ok
|
||||
is String -> x.data<!UNSAFE_CALL!>.<!>length // should be ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
fun test(mc: MutableCollection<out CharSequence>) {
|
||||
mc.addAll(mc)
|
||||
mc.addAll(<!ARGUMENT_TYPE_MISMATCH!>mc<!>)
|
||||
|
||||
mc.addAll(<!ARGUMENT_TYPE_MISMATCH!>arrayListOf<CharSequence>()<!>)
|
||||
mc.addAll(arrayListOf())
|
||||
|
||||
Generated
+6
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user