[FE] Support intersection type emptiness checking for interfaces
This commit is contained in:
committed by
teamcity
parent
1da52ab197
commit
39d13442be
+36
@@ -15343,12 +15343,48 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_28.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_28.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_29.kt")
|
||||||
|
public void testKt45461_29() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_29.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt45461_3.kt")
|
@TestMetadata("kt45461_3.kt")
|
||||||
public void testKt45461_3() throws Exception {
|
public void testKt45461_3() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_3.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_3.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_30.kt")
|
||||||
|
public void testKt45461_30() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_30.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_31.kt")
|
||||||
|
public void testKt45461_31() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_31.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_32.kt")
|
||||||
|
public void testKt45461_32() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_32.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_33.kt")
|
||||||
|
public void testKt45461_33() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_33.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_34.kt")
|
||||||
|
public void testKt45461_34() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_34.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt45461_4.kt")
|
@TestMetadata("kt45461_4.kt")
|
||||||
public void testKt45461_4() throws Exception {
|
public void testKt45461_4() throws Exception {
|
||||||
|
|||||||
+36
@@ -15343,12 +15343,48 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_28.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_28.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_29.kt")
|
||||||
|
public void testKt45461_29() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_29.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt45461_3.kt")
|
@TestMetadata("kt45461_3.kt")
|
||||||
public void testKt45461_3() throws Exception {
|
public void testKt45461_3() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_3.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_3.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_30.kt")
|
||||||
|
public void testKt45461_30() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_30.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_31.kt")
|
||||||
|
public void testKt45461_31() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_31.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_32.kt")
|
||||||
|
public void testKt45461_32() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_32.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_33.kt")
|
||||||
|
public void testKt45461_33() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_33.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_34.kt")
|
||||||
|
public void testKt45461_34() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_34.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt45461_4.kt")
|
@TestMetadata("kt45461_4.kt")
|
||||||
public void testKt45461_4() throws Exception {
|
public void testKt45461_4() throws Exception {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
|||||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator.commonSuperType
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeRefiner
|
import org.jetbrains.kotlin.types.AbstractTypeRefiner
|
||||||
import org.jetbrains.kotlin.types.TypeCheckerState
|
import org.jetbrains.kotlin.types.TypeCheckerState
|
||||||
@@ -502,8 +503,8 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
|||||||
this
|
this
|
||||||
else {
|
else {
|
||||||
var functionalSupertype: KotlinTypeMarker? = null
|
var functionalSupertype: KotlinTypeMarker? = null
|
||||||
simpleType.anySuperTypeConstructor { typeConstructor ->
|
simpleType.anySuperTypeConstructor { type ->
|
||||||
simpleType.fastCorrespondingSupertypes(typeConstructor)?.any { superType ->
|
simpleType.fastCorrespondingSupertypes(type.typeConstructor())?.any { superType ->
|
||||||
val isFunctional = superType.cast<ConeKotlinType>().isBuiltinFunctionalType(session)
|
val isFunctional = superType.cast<ConeKotlinType>().isBuiltinFunctionalType(session)
|
||||||
if (isFunctional)
|
if (isFunctional)
|
||||||
functionalSupertype = superType
|
functionalSupertype = superType
|
||||||
|
|||||||
@@ -631,7 +631,8 @@ internal fun captureFromTypeParameterUpperBoundIfNeeded(
|
|||||||
private fun ConeKotlinType.hasSupertypeWithGivenClassId(classId: ClassId, context: TypeSystemCommonSuperTypesContext): Boolean {
|
private fun ConeKotlinType.hasSupertypeWithGivenClassId(classId: ClassId, context: TypeSystemCommonSuperTypesContext): Boolean {
|
||||||
return with(context) {
|
return with(context) {
|
||||||
anySuperTypeConstructor {
|
anySuperTypeConstructor {
|
||||||
it is ConeClassLikeLookupTag && it.classId == classId
|
val typeConstructor = it.typeConstructor()
|
||||||
|
typeConstructor is ConeClassLikeLookupTag && typeConstructor.classId == classId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -38,10 +38,10 @@ fun test() {
|
|||||||
|
|
||||||
build2 {
|
build2 {
|
||||||
emit(1)
|
emit(1)
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!><!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>intersect<!>(this@build.getIn(), getIn())<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>intersect(<!TYPE_MISMATCH!>this@build.getIn()<!>, getIn())<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!><!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>intersect<!>(getIn(), Test.foo(this@build.getIn()))<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>intersect(<!TYPE_MISMATCH!>getIn()<!>, Test.foo(this@build.getIn()))<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!><!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>intersect<!>(Test.foo(this@build.getIn()), Test.foo(getIn()))<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>intersect(<!TYPE_MISMATCH!>Test.foo(this@build.getIn())<!>, Test.foo(getIn()))<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!><!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>intersect<!>(Test.foo(getIn()), this@build.getIn())<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>intersect(<!TYPE_MISMATCH!>Test.foo(getIn())<!>, this@build.getIn())<!>
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
""
|
""
|
||||||
|
|||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
class Bar<T> {
|
||||||
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Inv<P>
|
||||||
|
|
||||||
|
interface A
|
||||||
|
interface B
|
||||||
|
|
||||||
|
fun <K : Inv<A>> main() {
|
||||||
|
val foo = Foo<K>()
|
||||||
|
Bar<Inv<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
class Bar<T> {
|
||||||
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Inv<P>
|
||||||
|
|
||||||
|
interface A
|
||||||
|
interface B
|
||||||
|
|
||||||
|
fun <K : Inv<A>> main() {
|
||||||
|
val foo = Foo<K>()
|
||||||
|
Bar<Inv<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ K : Inv<A>> main(): kotlin.Unit
|
||||||
|
|
||||||
|
public interface A {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface B {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Bar</*0*/ T> {
|
||||||
|
public constructor Bar</*0*/ T>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public final fun </*0*/ S : T> takeFoo(/*0*/ foo: Foo<in S>): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Foo</*0*/ T> {
|
||||||
|
public constructor Foo</*0*/ T>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Inv</*0*/ P> {
|
||||||
|
public constructor Inv</*0*/ P>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
class Bar<T> {
|
||||||
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Out<out P>
|
||||||
|
|
||||||
|
interface A<K>
|
||||||
|
interface B<K> : A<Int>
|
||||||
|
|
||||||
|
fun <K : Out<A<String>>> main() {
|
||||||
|
val foo = Foo<K>()
|
||||||
|
Bar<Out<B<String>>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
class Bar<T> {
|
||||||
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Out<out P>
|
||||||
|
|
||||||
|
interface A<K>
|
||||||
|
interface B<K> : A<Int>
|
||||||
|
|
||||||
|
fun <K : Out<A<String>>> main() {
|
||||||
|
val foo = Foo<K>()
|
||||||
|
Bar<Out<B<String>>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ K : Out<A<kotlin.String>>> main(): kotlin.Unit
|
||||||
|
|
||||||
|
public interface A</*0*/ K> {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface B</*0*/ K> : A<kotlin.Int> {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Bar</*0*/ T> {
|
||||||
|
public constructor Bar</*0*/ T>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public final fun </*0*/ S : T> takeFoo(/*0*/ foo: Foo<in S>): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Foo</*0*/ T> {
|
||||||
|
public constructor Foo</*0*/ T>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Out</*0*/ out P> {
|
||||||
|
public constructor Out</*0*/ out P>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
class Bar<T> {
|
||||||
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Out<out P>
|
||||||
|
|
||||||
|
interface A<K>
|
||||||
|
interface B : A<Int>
|
||||||
|
|
||||||
|
fun <K : Out<A<String>>> main() {
|
||||||
|
val foo = Foo<K>()
|
||||||
|
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
class Bar<T> {
|
||||||
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Out<out P>
|
||||||
|
|
||||||
|
interface A<K>
|
||||||
|
interface B : A<Int>
|
||||||
|
|
||||||
|
fun <K : Out<A<String>>> main() {
|
||||||
|
val foo = Foo<K>()
|
||||||
|
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ K : Out<A<kotlin.String>>> main(): kotlin.Unit
|
||||||
|
|
||||||
|
public interface A</*0*/ K> {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface B : A<kotlin.Int> {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Bar</*0*/ T> {
|
||||||
|
public constructor Bar</*0*/ T>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public final fun </*0*/ S : T> takeFoo(/*0*/ foo: Foo<in S>): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Foo</*0*/ T> {
|
||||||
|
public constructor Foo</*0*/ T>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Out</*0*/ out P> {
|
||||||
|
public constructor Out</*0*/ out P>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
class Bar<T> {
|
||||||
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Out<out P>
|
||||||
|
|
||||||
|
interface A<K>
|
||||||
|
interface B : A<Int>
|
||||||
|
interface C : A<String>
|
||||||
|
|
||||||
|
fun <K : Out<C>> main() {
|
||||||
|
val foo = Foo<K>()
|
||||||
|
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
class Bar<T> {
|
||||||
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Out<out P>
|
||||||
|
|
||||||
|
interface A<K>
|
||||||
|
interface B : A<Int>
|
||||||
|
interface C : A<String>
|
||||||
|
|
||||||
|
fun <K : Out<C>> main() {
|
||||||
|
val foo = Foo<K>()
|
||||||
|
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
|
}
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ K : Out<C>> main(): kotlin.Unit
|
||||||
|
|
||||||
|
public interface A</*0*/ K> {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface B : A<kotlin.Int> {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Bar</*0*/ T> {
|
||||||
|
public constructor Bar</*0*/ T>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public final fun </*0*/ S : T> takeFoo(/*0*/ foo: Foo<in S>): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface C : A<kotlin.String> {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Foo</*0*/ T> {
|
||||||
|
public constructor Foo</*0*/ T>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Out</*0*/ out P> {
|
||||||
|
public constructor Out</*0*/ out P>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
class Bar<T> {
|
||||||
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Out<out P>
|
||||||
|
|
||||||
|
interface A<K>
|
||||||
|
class B : A<Int>
|
||||||
|
class C : A<String>
|
||||||
|
|
||||||
|
fun <K : <!FINAL_UPPER_BOUND!>Out<C><!>> main() {
|
||||||
|
val foo = Foo<K>()
|
||||||
|
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
class Bar<T> {
|
||||||
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Out<out P>
|
||||||
|
|
||||||
|
interface A<K>
|
||||||
|
class B : A<Int>
|
||||||
|
class C : A<String>
|
||||||
|
|
||||||
|
fun <K : <!FINAL_UPPER_BOUND!>Out<C><!>> main() {
|
||||||
|
val foo = Foo<K>()
|
||||||
|
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
|
}
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ K : Out<C>> main(): kotlin.Unit
|
||||||
|
|
||||||
|
public interface A</*0*/ K> {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class B : A<kotlin.Int> {
|
||||||
|
public constructor B()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Bar</*0*/ T> {
|
||||||
|
public constructor Bar</*0*/ T>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public final fun </*0*/ S : T> takeFoo(/*0*/ foo: Foo<in S>): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class C : A<kotlin.String> {
|
||||||
|
public constructor C()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Foo</*0*/ T> {
|
||||||
|
public constructor Foo</*0*/ T>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Out</*0*/ out P> {
|
||||||
|
public constructor Out</*0*/ out P>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
class Bar<T> {
|
||||||
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Out<out P>
|
||||||
|
|
||||||
|
interface A<K>
|
||||||
|
class B : A<Int>
|
||||||
|
|
||||||
|
fun <K : Out<A<String>>> main() {
|
||||||
|
val foo = Foo<K>()
|
||||||
|
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
class Bar<T> {
|
||||||
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Out<out P>
|
||||||
|
|
||||||
|
interface A<K>
|
||||||
|
class B : A<Int>
|
||||||
|
|
||||||
|
fun <K : Out<A<String>>> main() {
|
||||||
|
val foo = Foo<K>()
|
||||||
|
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ K : Out<A<kotlin.String>>> main(): kotlin.Unit
|
||||||
|
|
||||||
|
public interface A</*0*/ K> {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class B : A<kotlin.Int> {
|
||||||
|
public constructor B()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Bar</*0*/ T> {
|
||||||
|
public constructor Bar</*0*/ T>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public final fun </*0*/ S : T> takeFoo(/*0*/ foo: Foo<in S>): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Foo</*0*/ T> {
|
||||||
|
public constructor Foo</*0*/ T>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Out</*0*/ out P> {
|
||||||
|
public constructor Out</*0*/ out P>()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
interface A<T>
|
|
||||||
interface B<T> : A<T>
|
|
||||||
|
|
||||||
fun <T : Comparable<T>, S : T?> B<in S>.foo(t: T) {}
|
|
||||||
fun <T : Comparable<T>, S : T?> A<in S>.foo(other: A<in S>) {}
|
|
||||||
|
|
||||||
interface C<T> : B<T>, Comparable<C<*>>
|
|
||||||
|
|
||||||
fun test(x: C<Long?>) {
|
|
||||||
x.foo(x) // OVERLOAD_RESOLUTION_AMBIGUITY, shoub be OK
|
|
||||||
}
|
|
||||||
+2
-1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
interface A<T>
|
interface A<T>
|
||||||
interface B<T> : A<T>
|
interface B<T> : A<T>
|
||||||
|
|
||||||
@@ -7,5 +8,5 @@ fun <T : Comparable<T>, S : T?> A<in S>.foo(other: A<in S>) {}
|
|||||||
interface C<T> : B<T>, Comparable<C<*>>
|
interface C<T> : B<T>, Comparable<C<*>>
|
||||||
|
|
||||||
fun test(x: C<Long?>) {
|
fun test(x: C<Long?>) {
|
||||||
x.<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>(x) // OVERLOAD_RESOLUTION_AMBIGUITY, shoub be OK
|
x.foo(x) // OVERLOAD_RESOLUTION_AMBIGUITY, shoub be OK
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -53,5 +53,5 @@ fun main() {
|
|||||||
|
|
||||||
select(id(::foo5), id { x: A -> }, id { x: B -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> })
|
select(id(::foo5), id { x: A -> }, id { x: B -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> })
|
||||||
|
|
||||||
val x2: (Int) -> Unit = selectNumber(id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Number, kotlin.Unit>")!>::foo6<!>), id { x -> <!DEBUG_INFO_EXPRESSION_TYPE("{Comparable<*> & Number}")!>x<!> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("{Comparable<*> & Number}")!>it<!> })
|
val x2: (Int) -> Unit = selectNumber(id(::<!CALLABLE_REFERENCE_RESOLUTION_AMBIGUITY!>foo6<!>), id { x -> <!DEBUG_INFO_EXPRESSION_TYPE("{Comparable<*> & Number}")!>x<!> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("{Comparable<*> & Number}")!>it<!> })
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+36
@@ -15349,12 +15349,48 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_28.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_28.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_29.kt")
|
||||||
|
public void testKt45461_29() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_29.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt45461_3.kt")
|
@TestMetadata("kt45461_3.kt")
|
||||||
public void testKt45461_3() throws Exception {
|
public void testKt45461_3() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_3.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_3.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_30.kt")
|
||||||
|
public void testKt45461_30() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_30.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_31.kt")
|
||||||
|
public void testKt45461_31() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_31.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_32.kt")
|
||||||
|
public void testKt45461_32() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_32.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_33.kt")
|
||||||
|
public void testKt45461_33() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_33.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt45461_34.kt")
|
||||||
|
public void testKt45461_34() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_34.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt45461_4.kt")
|
@TestMetadata("kt45461_4.kt")
|
||||||
public void testKt45461_4() throws Exception {
|
public void testKt45461_4() throws Exception {
|
||||||
|
|||||||
@@ -205,6 +205,16 @@ object AbstractTypeChecker {
|
|||||||
return isSubtypeOf(context.newTypeCheckerState(true, stubTypesEqualToAnything), subType, superType)
|
return isSubtypeOf(context.newTypeCheckerState(true, stubTypesEqualToAnything), subType, superType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun areRelatedBySubtyping(
|
||||||
|
context: TypeCheckerProviderContext,
|
||||||
|
subType: KotlinTypeMarker,
|
||||||
|
superType: KotlinTypeMarker,
|
||||||
|
stubTypesEqualToAnything: Boolean = true
|
||||||
|
): Boolean {
|
||||||
|
val typeCheckerContext = context.newTypeCheckerState(true, stubTypesEqualToAnything)
|
||||||
|
return isSubtypeOf(typeCheckerContext, subType, superType) || isSubtypeOf(typeCheckerContext, superType, subType)
|
||||||
|
}
|
||||||
|
|
||||||
fun isSubtypeOfClass(
|
fun isSubtypeOfClass(
|
||||||
state: TypeCheckerState,
|
state: TypeCheckerState,
|
||||||
typeConstructor: TypeConstructorMarker,
|
typeConstructor: TypeConstructorMarker,
|
||||||
|
|||||||
@@ -105,11 +105,11 @@ interface TypeCheckerProviderContext {
|
|||||||
*/
|
*/
|
||||||
interface TypeSystemCommonSuperTypesContext : TypeSystemContext, TypeSystemTypeFactoryContext, TypeCheckerProviderContext {
|
interface TypeSystemCommonSuperTypesContext : TypeSystemContext, TypeSystemTypeFactoryContext, TypeCheckerProviderContext {
|
||||||
|
|
||||||
fun KotlinTypeMarker.anySuperTypeConstructor(predicate: (TypeConstructorMarker) -> Boolean) =
|
fun KotlinTypeMarker.anySuperTypeConstructor(predicate: (SimpleTypeMarker) -> Boolean) =
|
||||||
newTypeCheckerState(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true)
|
newTypeCheckerState(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true)
|
||||||
.anySupertype(
|
.anySupertype(
|
||||||
lowerBoundIfFlexible(),
|
lowerBoundIfFlexible(),
|
||||||
{ predicate(it.typeConstructor()) },
|
{ predicate(it) },
|
||||||
{ TypeCheckerState.SupertypesPolicy.LowerIfFlexible }
|
{ TypeCheckerState.SupertypesPolicy.LowerIfFlexible }
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -325,13 +325,13 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
|||||||
|
|
||||||
for (i in 0 until types.size) {
|
for (i in 0 until types.size) {
|
||||||
val firstType = types[i]
|
val firstType = types[i]
|
||||||
if (!firstType.typeConstructor().mayCauseEmptyIntersection()) continue
|
if (!firstType.mayCauseEmptyIntersection()) continue
|
||||||
|
|
||||||
val firstSubstitutedType by lazy { firstType.eraseContainingTypeParameters() }
|
val firstSubstitutedType by lazy { firstType.eraseContainingTypeParameters() }
|
||||||
|
|
||||||
for (j in i + 1 until types.size) {
|
for (j in i + 1 until types.size) {
|
||||||
val secondType = types[j]
|
val secondType = types[j]
|
||||||
if (!secondType.typeConstructor().mayCauseEmptyIntersection()) continue
|
if (!secondType.mayCauseEmptyIntersection()) continue
|
||||||
|
|
||||||
val secondSubstitutedType = secondType.eraseContainingTypeParameters()
|
val secondSubstitutedType = secondType.eraseContainingTypeParameters()
|
||||||
|
|
||||||
@@ -343,6 +343,30 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
|||||||
return EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION
|
return EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun canHaveCommonSubtypeWithInterface(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker): Boolean {
|
||||||
|
require(firstType.typeConstructor().isInterface() || secondType.typeConstructor().isInterface()) {
|
||||||
|
"One of the passed type should be an interface"
|
||||||
|
}
|
||||||
|
@Suppress("NAME_SHADOWING")
|
||||||
|
val firstType = firstType.withNullability(false)
|
||||||
|
|
||||||
|
@Suppress("NAME_SHADOWING")
|
||||||
|
val secondType = secondType.withNullability(false)
|
||||||
|
|
||||||
|
// interface A<K>
|
||||||
|
// interface B: A<String>
|
||||||
|
// interface C: A<Int>
|
||||||
|
// B & C can't have common subtype due to having incompatible supertypes: A<String> and A<Int>
|
||||||
|
val haveIncompatibleSupertypes = firstType.anySuperTypeConstructor { superTypeOfFirst ->
|
||||||
|
secondType.anySuperTypeConstructor { superTypeOfSecond ->
|
||||||
|
superTypeOfFirst.typeConstructor() == superTypeOfSecond.typeConstructor()
|
||||||
|
&& !AbstractTypeChecker.equalTypes(this, superTypeOfFirst, superTypeOfSecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !haveIncompatibleSupertypes
|
||||||
|
}
|
||||||
|
|
||||||
private fun canHaveCommonSubtype(first: KotlinTypeMarker, second: KotlinTypeMarker): Boolean {
|
private fun canHaveCommonSubtype(first: KotlinTypeMarker, second: KotlinTypeMarker): Boolean {
|
||||||
fun extractIntersectionComponentsIfNeeded(type: KotlinTypeMarker) =
|
fun extractIntersectionComponentsIfNeeded(type: KotlinTypeMarker) =
|
||||||
if (type.typeConstructor() is IntersectionTypeConstructorMarker) {
|
if (type.typeConstructor() is IntersectionTypeConstructorMarker) {
|
||||||
@@ -350,26 +374,28 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
|||||||
} else listOf(type)
|
} else listOf(type)
|
||||||
|
|
||||||
val expandedTypes = extractIntersectionComponentsIfNeeded(first) + extractIntersectionComponentsIfNeeded(second)
|
val expandedTypes = extractIntersectionComponentsIfNeeded(first) + extractIntersectionComponentsIfNeeded(second)
|
||||||
|
|
||||||
val typeCheckerState = newTypeCheckerState(errorTypesEqualToAnything = true, stubTypesEqualToAnything = true)
|
val typeCheckerState = newTypeCheckerState(errorTypesEqualToAnything = true, stubTypesEqualToAnything = true)
|
||||||
|
|
||||||
for (i in 0 until expandedTypes.size) {
|
for (i in expandedTypes.indices) {
|
||||||
val firstType = expandedTypes[i]
|
val firstType = expandedTypes[i]
|
||||||
val firstTypeConstructor = firstType.typeConstructor()
|
val firstTypeConstructor = firstType.typeConstructor()
|
||||||
|
|
||||||
if (!firstTypeConstructor.mayCauseEmptyIntersection())
|
if (!firstType.mayCauseEmptyIntersection())
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for (j in i + 1 until expandedTypes.size) {
|
for (j in i + 1 until expandedTypes.size) {
|
||||||
val secondType = expandedTypes[j]
|
val secondType = expandedTypes[j]
|
||||||
val secondTypeConstructor = secondType.typeConstructor()
|
val secondTypeConstructor = secondType.typeConstructor()
|
||||||
|
|
||||||
if (!secondTypeConstructor.mayCauseEmptyIntersection())
|
if (!secondType.mayCauseEmptyIntersection())
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if (areEqualTypeConstructors(firstTypeConstructor, secondTypeConstructor) && secondTypeConstructor.parametersCount() == 0)
|
if (areEqualTypeConstructors(firstTypeConstructor, secondTypeConstructor) && secondTypeConstructor.parametersCount() == 0)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if (AbstractTypeChecker.areRelatedBySubtyping(this, firstType, secondType))
|
||||||
|
continue
|
||||||
|
|
||||||
val superTypeByFirstConstructor = AbstractTypeChecker.findCorrespondingSupertypes(
|
val superTypeByFirstConstructor = AbstractTypeChecker.findCorrespondingSupertypes(
|
||||||
typeCheckerState, firstType.lowerBoundIfFlexible(), secondTypeConstructor
|
typeCheckerState, firstType.lowerBoundIfFlexible(), secondTypeConstructor
|
||||||
).singleOrNull()
|
).singleOrNull()
|
||||||
@@ -377,15 +403,20 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
|||||||
typeCheckerState, secondType.lowerBoundIfFlexible(), firstTypeConstructor
|
typeCheckerState, secondType.lowerBoundIfFlexible(), firstTypeConstructor
|
||||||
).singleOrNull()
|
).singleOrNull()
|
||||||
|
|
||||||
if (superTypeByFirstConstructor == null && superTypeBySecondConstructor == null)
|
val anyInference = firstTypeConstructor.isInterface() || secondTypeConstructor.isInterface()
|
||||||
|
|
||||||
|
// Two classes can't have a common subtype if neither is a subtype of another
|
||||||
|
if (superTypeByFirstConstructor == null && superTypeBySecondConstructor == null && !anyInference)
|
||||||
|
return false
|
||||||
|
|
||||||
|
if (anyInference && !canHaveCommonSubtypeWithInterface(firstType, secondType))
|
||||||
return false
|
return false
|
||||||
|
|
||||||
if (superTypeByFirstConstructor == null || superTypeBySecondConstructor == null)
|
if (superTypeByFirstConstructor == null || superTypeBySecondConstructor == null)
|
||||||
continue // first or second is actually subtype of another
|
continue // first or second is actually subtype of another
|
||||||
|
|
||||||
if (!checkArgumentsOfTypesToBeAbleToHaveCommonSubtype(superTypeByFirstConstructor, superTypeBySecondConstructor)) {
|
if (!checkArgumentsOfTypesToBeAbleToHaveCommonSubtype(superTypeByFirstConstructor, superTypeBySecondConstructor))
|
||||||
return false
|
return false
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,8 +431,19 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
|||||||
private fun computeEffectiveVariance(parameter: TypeParameterMarker, argument: TypeArgumentMarker): TypeVariance? =
|
private fun computeEffectiveVariance(parameter: TypeParameterMarker, argument: TypeArgumentMarker): TypeVariance? =
|
||||||
AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance())
|
AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance())
|
||||||
|
|
||||||
private fun TypeConstructorMarker.mayCauseEmptyIntersection(): Boolean =
|
private fun KotlinTypeMarker.mayCauseEmptyIntersection(): Boolean {
|
||||||
(isClassTypeConstructor() || isTypeParameterTypeConstructor()) && !isInterface() && !isAnyConstructor() && !isNothingConstructor()
|
val typeConstructor = typeConstructor()
|
||||||
|
|
||||||
|
if (!typeConstructor.isClassTypeConstructor() && !typeConstructor.isTypeParameterTypeConstructor())
|
||||||
|
return false
|
||||||
|
|
||||||
|
// Even two interfaces may be an empty intersection type:
|
||||||
|
// interface Inv<K>
|
||||||
|
// interface B : Inv<Int>
|
||||||
|
// `Inv<String> & B` or `Inv<String> & Inv<Int>` are empty
|
||||||
|
// So we don't filter out interfaces here
|
||||||
|
return !typeConstructor.isAnyConstructor() && !typeConstructor.isNothingConstructor()
|
||||||
|
}
|
||||||
|
|
||||||
private fun areArgumentsOfSpecifiedVariances(
|
private fun areArgumentsOfSpecifiedVariances(
|
||||||
firstType: KotlinTypeMarker,
|
firstType: KotlinTypeMarker,
|
||||||
@@ -431,6 +473,9 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
|||||||
fun isSubtypeOf(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker) =
|
fun isSubtypeOf(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker) =
|
||||||
AbstractTypeChecker.isSubtypeOf(this, firstType, secondType)
|
AbstractTypeChecker.isSubtypeOf(this, firstType, secondType)
|
||||||
|
|
||||||
|
fun areEqualTypes(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker) =
|
||||||
|
AbstractTypeChecker.equalTypes(this, firstType, secondType)
|
||||||
|
|
||||||
for ((i, argumentOfFirst) in firstType.getArguments().withIndex()) {
|
for ((i, argumentOfFirst) in firstType.getArguments().withIndex()) {
|
||||||
@Suppress("NAME_SHADOWING")
|
@Suppress("NAME_SHADOWING")
|
||||||
val argumentOfFirst = argumentOfFirst.uncaptureIfNeeded()
|
val argumentOfFirst = argumentOfFirst.uncaptureIfNeeded()
|
||||||
@@ -444,31 +489,27 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
|||||||
|
|
||||||
when {
|
when {
|
||||||
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.INV) ->
|
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.INV) ->
|
||||||
return false
|
return areEqualTypes(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||||
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.OUT) -> {
|
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.OUT) -> {
|
||||||
if (!isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond)) {
|
if (!isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond))
|
||||||
return false
|
return false
|
||||||
}
|
|
||||||
}
|
}
|
||||||
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.IN) -> {
|
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.IN) -> {
|
||||||
if (!isSubtypeOf(argumentTypeOfSecond, argumentTypeOfFirst)) {
|
if (!isSubtypeOf(argumentTypeOfSecond, argumentTypeOfFirst))
|
||||||
return false
|
return false
|
||||||
}
|
|
||||||
}
|
}
|
||||||
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.IN, TypeVariance.OUT) -> {
|
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.IN, TypeVariance.OUT) -> {
|
||||||
if (argumentTypeOfFirst.argumentsCount() == 0 && argumentTypeOfSecond.argumentsCount() == 0) {
|
if (argumentTypeOfFirst.argumentsCount() == 0 && argumentTypeOfSecond.argumentsCount() == 0) {
|
||||||
if (!isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond)) {
|
if (!isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond))
|
||||||
return false
|
return false
|
||||||
}
|
|
||||||
} else if (!canHaveCommonSubtype(argumentTypeOfFirst, argumentTypeOfSecond)) {
|
} else if (!canHaveCommonSubtype(argumentTypeOfFirst, argumentTypeOfSecond)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.OUT, TypeVariance.OUT)
|
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.OUT, TypeVariance.OUT)
|
||||||
|| areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.IN, TypeVariance.IN) -> {
|
|| areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.IN, TypeVariance.IN) -> {
|
||||||
if (!canHaveCommonSubtype(argumentTypeOfFirst, argumentTypeOfSecond)) {
|
if (!canHaveCommonSubtype(argumentTypeOfFirst, argumentTypeOfSecond))
|
||||||
return false
|
return false
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user