[FE] Determine intersection type emptiness by looking at supertypes properly: substitute their type arguments
This commit is contained in:
committed by
teamcity
parent
a0260292ec
commit
20a8e5d742
+18
@@ -15217,6 +15217,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/compatibilityResolveWhenVariableHasComplexIntersectionType.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/compatibilityResolveWhenVariableHasComplexIntersectionType.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("contravariance.kt")
|
||||||
|
public void testContravariance() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/contravariance.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt45461.kt")
|
@TestMetadata("kt45461.kt")
|
||||||
public void testKt45461() throws Exception {
|
public void testKt45461() throws Exception {
|
||||||
@@ -15510,6 +15516,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
public void testSelectFromCovariantAndContravariantTypes() throws Exception {
|
public void testSelectFromCovariantAndContravariantTypes() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/selectFromCovariantAndContravariantTypes.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/selectFromCovariantAndContravariantTypes.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("substitutingSuperTypes.kt")
|
||||||
|
public void testSubstitutingSuperTypes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/substitutingSuperTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("substitutingSuperTypes2.kt")
|
||||||
|
public void testSubstitutingSuperTypes2() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/substitutingSuperTypes2.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+18
@@ -15217,6 +15217,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/compatibilityResolveWhenVariableHasComplexIntersectionType.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/compatibilityResolveWhenVariableHasComplexIntersectionType.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("contravariance.kt")
|
||||||
|
public void testContravariance() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/contravariance.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt45461.kt")
|
@TestMetadata("kt45461.kt")
|
||||||
public void testKt45461() throws Exception {
|
public void testKt45461() throws Exception {
|
||||||
@@ -15510,6 +15516,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
public void testSelectFromCovariantAndContravariantTypes() throws Exception {
|
public void testSelectFromCovariantAndContravariantTypes() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/selectFromCovariantAndContravariantTypes.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/selectFromCovariantAndContravariantTypes.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("substitutingSuperTypes.kt")
|
||||||
|
public void testSubstitutingSuperTypes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/substitutingSuperTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("substitutingSuperTypes2.kt")
|
||||||
|
public void testSubstitutingSuperTypes2() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/substitutingSuperTypes2.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+18
@@ -15217,6 +15217,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/compatibilityResolveWhenVariableHasComplexIntersectionType.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/compatibilityResolveWhenVariableHasComplexIntersectionType.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("contravariance.kt")
|
||||||
|
public void testContravariance() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/contravariance.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt45461.kt")
|
@TestMetadata("kt45461.kt")
|
||||||
public void testKt45461() throws Exception {
|
public void testKt45461() throws Exception {
|
||||||
@@ -15510,6 +15516,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
public void testSelectFromCovariantAndContravariantTypes() throws Exception {
|
public void testSelectFromCovariantAndContravariantTypes() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/selectFromCovariantAndContravariantTypes.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/selectFromCovariantAndContravariantTypes.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("substitutingSuperTypes.kt")
|
||||||
|
public void testSubstitutingSuperTypes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/substitutingSuperTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("substitutingSuperTypes2.kt")
|
||||||
|
public void testSubstitutingSuperTypes2() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/substitutingSuperTypes2.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.types
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.isPrimitiveNumberOrUnsignedNumberType
|
import org.jetbrains.kotlin.fir.isPrimitiveNumberOrUnsignedNumberType
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.createSubstitutionForSupertype
|
||||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||||
@@ -563,4 +564,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
|||||||
|
|
||||||
override fun SimpleTypeMarker.createConstraintPartForLowerBoundAndFlexibleTypeVariable(): KotlinTypeMarker =
|
override fun SimpleTypeMarker.createConstraintPartForLowerBoundAndFlexibleTypeVariable(): KotlinTypeMarker =
|
||||||
createFlexibleType(this.makeSimpleTypeDefinitelyNotNullOrNotNull(), this.withNullability(true))
|
createFlexibleType(this.makeSimpleTypeDefinitelyNotNullOrNotNull(), this.withNullability(true))
|
||||||
|
|
||||||
|
override fun createSubstitutorForSuperTypes(baseType: KotlinTypeMarker): TypeSubstitutorMarker? =
|
||||||
|
if (baseType is ConeLookupTagBasedType) createSubstitutionForSupertype(baseType, session) else null
|
||||||
}
|
}
|
||||||
|
|||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
fun expandMaskConditionsAndUpdateVariableNodes(validOffsets: Collection<Int>) {}
|
||||||
|
|
||||||
|
fun main(x: List<Int>, y: Int) {
|
||||||
|
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>expandMaskConditionsAndUpdateVariableNodes<!>(
|
||||||
|
x.mapTo(mutableSetOf()) { y }
|
||||||
|
)
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
fun expandMaskConditionsAndUpdateVariableNodes(validOffsets: Collection<Int>) {}
|
||||||
|
|
||||||
|
fun main(x: List<Int>, y: Int) {
|
||||||
|
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>expandMaskConditionsAndUpdateVariableNodes<!>(
|
||||||
|
x.mapTo(mutableSetOf()) { y }
|
||||||
|
)
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun expandMaskConditionsAndUpdateVariableNodes(/*0*/ validOffsets: kotlin.collections.Collection<kotlin.Int>): kotlin.Unit
|
||||||
|
public fun main(/*0*/ x: kotlin.collections.List<kotlin.Int>, /*1*/ y: kotlin.Int): kotlin.Unit
|
||||||
|
|
||||||
Vendored
+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<T> : A<T>
|
||||||
|
interface C<T> : A<T>
|
||||||
|
|
||||||
|
fun <K : C<Int>> main() {
|
||||||
|
val foo = Foo<K>()
|
||||||
|
Bar<B<String>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
|
}
|
||||||
Vendored
+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<T> : A<T>
|
||||||
|
interface C<T> : A<T>
|
||||||
|
|
||||||
|
fun <K : C<Int>> main() {
|
||||||
|
val foo = Foo<K>()
|
||||||
|
Bar<B<String>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
|
}
|
||||||
Vendored
+43
@@ -0,0 +1,43 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ K : C<kotlin.Int>> 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*/ T> : A<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 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</*0*/ T> : A<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 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
|
||||||
|
}
|
||||||
Vendored
+18
@@ -0,0 +1,18 @@
|
|||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
class Bar<T> {
|
||||||
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Out<out P>
|
||||||
|
|
||||||
|
interface A<K>
|
||||||
|
interface B2<T> : A<T>
|
||||||
|
interface C2<T> : A<T>
|
||||||
|
interface B<T> : B2<T>
|
||||||
|
interface C<T> : C2<T>
|
||||||
|
|
||||||
|
fun <K : C<Int>> main() {
|
||||||
|
val foo = Foo<K>()
|
||||||
|
Bar<B<String>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
|
}
|
||||||
Vendored
+18
@@ -0,0 +1,18 @@
|
|||||||
|
class Foo<T>
|
||||||
|
|
||||||
|
class Bar<T> {
|
||||||
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Out<out P>
|
||||||
|
|
||||||
|
interface A<K>
|
||||||
|
interface B2<T> : A<T>
|
||||||
|
interface C2<T> : A<T>
|
||||||
|
interface B<T> : B2<T>
|
||||||
|
interface C<T> : C2<T>
|
||||||
|
|
||||||
|
fun <K : C<Int>> main() {
|
||||||
|
val foo = Foo<K>()
|
||||||
|
Bar<B<String>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
|
}
|
||||||
Vendored
+55
@@ -0,0 +1,55 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ K : C<kotlin.Int>> 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*/ T> : B2<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 interface B2</*0*/ T> : A<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 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</*0*/ T> : C2<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 interface C2</*0*/ T> : A<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 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
|
||||||
|
}
|
||||||
Generated
+18
@@ -15223,6 +15223,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/compatibilityResolveWhenVariableHasComplexIntersectionType.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/compatibilityResolveWhenVariableHasComplexIntersectionType.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("contravariance.kt")
|
||||||
|
public void testContravariance() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/contravariance.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt45461.kt")
|
@TestMetadata("kt45461.kt")
|
||||||
public void testKt45461() throws Exception {
|
public void testKt45461() throws Exception {
|
||||||
@@ -15516,6 +15522,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
public void testSelectFromCovariantAndContravariantTypes() throws Exception {
|
public void testSelectFromCovariantAndContravariantTypes() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/selectFromCovariantAndContravariantTypes.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/selectFromCovariantAndContravariantTypes.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("substitutingSuperTypes.kt")
|
||||||
|
public void testSubstitutingSuperTypes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/substitutingSuperTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("substitutingSuperTypes2.kt")
|
||||||
|
public void testSubstitutingSuperTypes2() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/substitutingSuperTypes2.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
@@ -343,33 +343,61 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
|||||||
return EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION
|
return EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createSubstitutorForSuperTypes(baseType: KotlinTypeMarker): TypeSubstitutorMarker?
|
||||||
|
|
||||||
|
private fun areIncompatibleSuperTypes(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker): Boolean =
|
||||||
|
firstType.typeConstructor() == secondType.typeConstructor()
|
||||||
|
&& !AbstractTypeChecker.equalTypes(context = this, firstType, secondType)
|
||||||
|
|
||||||
|
// interface A<T>
|
||||||
|
// interface B : A<Int>
|
||||||
|
// interface C : A<String>
|
||||||
|
// => B and C have incompatible supertypes
|
||||||
|
private fun hasIncompatibleSuperTypes(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker): Boolean {
|
||||||
|
val superTypesOfFirst = firstType.typeConstructor().supertypes()
|
||||||
|
val firstTypeSubstitutor = createSubstitutorForSuperTypes(firstType)
|
||||||
|
val superTypesOfSecond = secondType.typeConstructor().supertypes()
|
||||||
|
val secondTypeSubstitutor = createSubstitutorForSuperTypes(secondType)
|
||||||
|
|
||||||
|
for (superTypeOfFirst in superTypesOfFirst) {
|
||||||
|
@Suppress("NAME_SHADOWING")
|
||||||
|
val superTypeOfFirst = firstTypeSubstitutor?.safeSubstitute(superTypeOfFirst) ?: superTypeOfFirst
|
||||||
|
|
||||||
|
if (areIncompatibleSuperTypes(superTypeOfFirst, secondType))
|
||||||
|
return true
|
||||||
|
|
||||||
|
for (superTypeOfSecond in superTypesOfSecond) {
|
||||||
|
@Suppress("NAME_SHADOWING")
|
||||||
|
val superTypeOfSecond = secondTypeSubstitutor?.safeSubstitute(superTypeOfSecond) ?: superTypeOfSecond
|
||||||
|
|
||||||
|
if (
|
||||||
|
areIncompatibleSuperTypes(firstType, superTypeOfSecond)
|
||||||
|
|| areIncompatibleSuperTypes(superTypeOfFirst, superTypeOfSecond)
|
||||||
|
) return true
|
||||||
|
|
||||||
|
if (hasIncompatibleSuperTypes(superTypeOfFirst, superTypeOfSecond))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
private fun canHaveCommonSubtypeWithInterface(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker): Boolean {
|
private fun canHaveCommonSubtypeWithInterface(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker): Boolean {
|
||||||
require(firstType.typeConstructor().isInterface() || secondType.typeConstructor().isInterface()) {
|
require(firstType.typeConstructor().isInterface() || secondType.typeConstructor().isInterface()) {
|
||||||
"One of the passed type should be an interface"
|
"One of the passed type should be an interface"
|
||||||
}
|
}
|
||||||
@Suppress("NAME_SHADOWING")
|
@Suppress("NAME_SHADOWING")
|
||||||
val firstType = firstType.withNullability(false)
|
val firstType = firstType.withNullability(false).eraseContainingTypeParameters()
|
||||||
|
|
||||||
@Suppress("NAME_SHADOWING")
|
@Suppress("NAME_SHADOWING")
|
||||||
val secondType = secondType.withNullability(false)
|
val secondType = secondType.withNullability(false).eraseContainingTypeParameters()
|
||||||
|
|
||||||
// interface A<K>
|
// interface A<K>
|
||||||
// interface B: A<String>
|
// interface B: A<String>
|
||||||
// interface C: A<Int>
|
// interface C: A<Int>
|
||||||
// B & C can't have common subtype due to having incompatible supertypes: A<String> and A<Int>
|
// B & C can't have common subtype due to having incompatible supertypes: A<String> and A<Int>
|
||||||
val haveIncompatibleSupertypes = firstType.anySuperTypeConstructor { superTypeOfFirst ->
|
return !hasIncompatibleSuperTypes(firstType, secondType)
|
||||||
secondType.anySuperTypeConstructor { superTypeOfSecond ->
|
|
||||||
val erasedSuperTypeOfSecond by lazy { superTypeOfSecond.eraseContainingTypeParameters() }
|
|
||||||
superTypeOfFirst.typeConstructor() == superTypeOfSecond.typeConstructor()
|
|
||||||
&& !AbstractTypeChecker.equalTypes(
|
|
||||||
context = this,
|
|
||||||
superTypeOfFirst.eraseContainingTypeParameters(),
|
|
||||||
erasedSuperTypeOfSecond
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return !haveIncompatibleSupertypes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun canHaveCommonSubtype(first: KotlinTypeMarker, second: KotlinTypeMarker): Boolean {
|
private fun canHaveCommonSubtype(first: KotlinTypeMarker, second: KotlinTypeMarker): Boolean {
|
||||||
|
|||||||
@@ -30,8 +30,7 @@ import org.jetbrains.kotlin.utils.sure
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class SubstitutingScope(private val workerScope: MemberScope, givenSubstitutor: TypeSubstitutor) : MemberScope {
|
class SubstitutingScope(private val workerScope: MemberScope, givenSubstitutor: TypeSubstitutor) : MemberScope {
|
||||||
|
val substitutor = givenSubstitutor.substitution.wrapWithCapturingSubstitution().buildSubstitutor()
|
||||||
private val substitutor = givenSubstitutor.substitution.wrapWithCapturingSubstitution().buildSubstitutor()
|
|
||||||
|
|
||||||
private var substitutedDescriptors: MutableMap<DeclarationDescriptor, DeclarationDescriptor>? = null
|
private var substitutedDescriptors: MutableMap<DeclarationDescriptor, DeclarationDescriptor>? = null
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.CapturedType
|
import org.jetbrains.kotlin.resolve.calls.inference.CapturedType
|
||||||
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
|
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.SubstitutingScope
|
||||||
import org.jetbrains.kotlin.resolve.substitutedUnderlyingType
|
import org.jetbrains.kotlin.resolve.substitutedUnderlyingType
|
||||||
import org.jetbrains.kotlin.resolve.unsubstitutedUnderlyingType
|
import org.jetbrains.kotlin.resolve.unsubstitutedUnderlyingType
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
@@ -870,6 +871,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
|||||||
return getKFunctionDescriptor(builtIns, parametersNumber, isSuspend).typeConstructor
|
return getKFunctionDescriptor(builtIns, parametersNumber, isSuspend).typeConstructor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun createSubstitutorForSuperTypes(baseType: KotlinTypeMarker): TypeSubstitutorMarker? {
|
||||||
|
require(baseType is KotlinType, baseType::errorMessage)
|
||||||
|
return (baseType.memberScope as? SubstitutingScope)?.substitutor
|
||||||
|
}
|
||||||
|
|
||||||
override fun SimpleTypeMarker.createConstraintPartForLowerBoundAndFlexibleTypeVariable(): KotlinTypeMarker =
|
override fun SimpleTypeMarker.createConstraintPartForLowerBoundAndFlexibleTypeVariable(): KotlinTypeMarker =
|
||||||
if (this.isMarkedNullable()) {
|
if (this.isMarkedNullable()) {
|
||||||
this
|
this
|
||||||
|
|||||||
Reference in New Issue
Block a user