diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java index 7ebf99e32c0..c89c8e29684 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -10059,6 +10059,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/commonSuperTypeOfErrorTypes.kt"); } + @TestMetadata("compatibilityResolveWhenVariableHasComplexIntersectionType.kt") + public void testCompatibilityResolveWhenVariableHasComplexIntersectionType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.kt"); + } + @TestMetadata("completeInferenceIfManyFailed.kt") public void testCompleteInferenceIfManyFailed() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completeInferenceIfManyFailed.kt"); @@ -10209,6 +10214,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/intersectionTypeMultipleBoundsAsReceiver.kt"); } + @TestMetadata("intersectionTypesWithContravariantTypes.kt") + public void testIntersectionTypesWithContravariantTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.kt"); + } + @TestMetadata("intersectionWithEnum.kt") public void testIntersectionWithEnum() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/intersectionWithEnum.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt index 5f17c62867f..6b911c0f499 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionStatelessCallbacksImpl.kt @@ -39,6 +39,8 @@ import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeIntersector import org.jetbrains.kotlin.utils.addToStdlib.safeAs class KotlinResolutionStatelessCallbacksImpl( @@ -87,6 +89,10 @@ class KotlinResolutionStatelessCallbacksImpl( return org.jetbrains.kotlin.resolve.calls.inference.isApplicableCallForBuilderInference(descriptor, languageVersionSettings) } + override fun isOldIntersectionIsEmpty(types: Collection): Boolean { + return TypeIntersector.intersectTypes(types) == null + } + override fun createConstraintSystemForOverloadResolution( constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns, ): SimpleConstraintSystem { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt index 6bfcd1aacd1..0f3894846f2 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant +import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.StubType import org.jetbrains.kotlin.types.UnwrappedType @@ -36,6 +37,8 @@ interface KotlinResolutionStatelessCallbacks { fun isCoroutineCall(argument: KotlinCallArgument, parameter: ValueParameterDescriptor): Boolean fun isApplicableCallForBuilderInference(descriptor: CallableDescriptor, languageVersionSettings: LanguageVersionSettings): Boolean + fun isOldIntersectionIsEmpty(types: Collection): Boolean + fun createConstraintSystemForOverloadResolution( constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns ): SimpleConstraintSystem diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt index adf7e5a71b8..3835c05ed99 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.types.typeUtil.makeNullable import org.jetbrains.kotlin.utils.SmartList +import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.safeAs internal object CheckVisibility : ResolutionPart() { @@ -250,6 +251,24 @@ internal object PostponedVariablesInitializerResolutionPart : ResolutionPart() { } } +internal object CompatibilityOfTypeVariableAsIntersectionTypePart : ResolutionPart() { + override fun KotlinResolutionCandidate.process(workIndex: Int) { + for ((_, variableWithConstraints) in csBuilder.currentStorage().notFixedTypeVariables) { + val constraints = variableWithConstraints.constraints.filter { csBuilder.isProperType(it.type) } + + if (constraints.size <= 1) continue + if (constraints.any { it.kind.isLower() || it.kind.isEqual() }) continue + + // See TypeBoundsImpl.computeValues(). It returns several values for such situation which means an error in OI + if (callComponents.statelessCallbacks.isOldIntersectionIsEmpty(constraints.map { it.type }.cast())) { + addDiagnostic(LowerPriorityToPreserveCompatibility) + return + } + } + + } +} + internal object CheckExplicitReceiverKindConsistency : ResolutionPart() { private fun KotlinResolutionCandidate.hasError(): Nothing = error( diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt index e32895c0cb1..41b482853d4 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt @@ -228,6 +228,7 @@ enum class KotlinCallKind(vararg resolutionPart: ResolutionPart) { CheckArgumentsInParenthesis, CheckExternalArgument, EagerResolveOfCallableReferences, + CompatibilityOfTypeVariableAsIntersectionTypePart, PostponedVariablesInitializerResolutionPart ), INVOKE(*FUNCTION.resolutionSequence.toTypedArray()), diff --git a/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.fir.kt b/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.fir.kt new file mode 100644 index 00000000000..460d6e39714 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.fir.kt @@ -0,0 +1,37 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION + +abstract class Foo + +abstract class Bar : Foo(), Comparable> + +object Scope { + fun , S : T> greater(x: Bar, other: Foo) {} + + object Nested { + fun , S : T> greater(x: Bar, t: T) {} + + fun test(b: Bar) { + greater(b, b) + } + } +} + +object OnlyOne { + fun , S : T> greater(x: Bar, t: T) {} + + fun test(b: Bar) { + greater(b, b) + } +} + +object GoodOldCandidate { + fun , S : T> greater(x: Bar, t: T) {} + + object Nested { + fun , S : T> greater(x: Bar, other: Foo) {} + + fun test(b: Bar) { + greater(b, b) + } + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.kt b/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.kt new file mode 100644 index 00000000000..2e5b6620375 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.kt @@ -0,0 +1,37 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION + +abstract class Foo + +abstract class Bar : Foo(), Comparable> + +object Scope { + fun , S : T> greater(x: Bar, other: Foo) {} + + object Nested { + fun , S : T> greater(x: Bar, t: T) {} + + fun test(b: Bar) { + greater(b, b) + } + } +} + +object OnlyOne { + fun , S : T> greater(x: Bar, t: T) {} + + fun test(b: Bar) { + greater(b, b) + } +} + +object GoodOldCandidate { + fun , S : T> greater(x: Bar, t: T) {} + + object Nested { + fun , S : T> greater(x: Bar, other: Foo) {} + + fun test(b: Bar) { + greater(b, b) + } + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.txt b/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.txt new file mode 100644 index 00000000000..61d17839187 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.txt @@ -0,0 +1,59 @@ +package + +public abstract class Bar : Foo, kotlin.Comparable> { + public constructor Bar() + public abstract override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Bar): kotlin.Int + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + +public abstract class Foo { + public constructor Foo() + 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 object GoodOldCandidate { + private constructor GoodOldCandidate() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun , /*1*/ S : T> greater(/*0*/ x: Bar, /*1*/ t: T): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public object Nested { + private constructor Nested() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun , /*1*/ S : T> greater(/*0*/ x: Bar, /*1*/ other: Foo): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun test(/*0*/ b: Bar): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +public object OnlyOne { + private constructor OnlyOne() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun , /*1*/ S : T> greater(/*0*/ x: Bar, /*1*/ t: T): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun test(/*0*/ b: Bar): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public object Scope { + private constructor Scope() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun , /*1*/ S : T> greater(/*0*/ x: Bar, /*1*/ other: Foo): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public object Nested { + private constructor Nested() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun , /*1*/ S : T> greater(/*0*/ x: Bar, /*1*/ t: T): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun test(/*0*/ b: Bar): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.fir.kt b/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.fir.kt new file mode 100644 index 00000000000..79cf65fbf00 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.fir.kt @@ -0,0 +1,13 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION + +abstract class Foo + +abstract class Bar : Foo(), Comparable> + +fun , S : T> greater(x: Bar, t: T): Int = 0 +fun , S : T> greater(x: Bar, other: Foo): String = "" + +fun test(b: Bar) { + val result = greater(b, b) + result +} diff --git a/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.kt b/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.kt new file mode 100644 index 00000000000..30f4a95028c --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.kt @@ -0,0 +1,13 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION + +abstract class Foo + +abstract class Bar : Foo(), Comparable> + +fun , S : T> greater(x: Bar, t: T): Int = 0 +fun , S : T> greater(x: Bar, other: Foo): String = "" + +fun test(b: Bar) { + val result = greater(b, b) + result +} diff --git a/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.txt b/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.txt new file mode 100644 index 00000000000..9d4cf487cfb --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.txt @@ -0,0 +1,20 @@ +package + +public fun , /*1*/ S : T> greater(/*0*/ x: Bar, /*1*/ other: Foo): kotlin.String +public fun , /*1*/ S : T> greater(/*0*/ x: Bar, /*1*/ t: T): kotlin.Int +public fun test(/*0*/ b: Bar): kotlin.Unit + +public abstract class Bar : Foo, kotlin.Comparable> { + public constructor Bar() + public abstract override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Bar): kotlin.Int + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + +public abstract class Foo { + public constructor Foo() + 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 +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 6ac10915d26..b2b1c7e7ca1 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10066,6 +10066,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/inference/commonSuperTypeOfErrorTypes.kt"); } + @TestMetadata("compatibilityResolveWhenVariableHasComplexIntersectionType.kt") + public void testCompatibilityResolveWhenVariableHasComplexIntersectionType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.kt"); + } + @TestMetadata("completeInferenceIfManyFailed.kt") public void testCompleteInferenceIfManyFailed() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completeInferenceIfManyFailed.kt"); @@ -10216,6 +10221,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/inference/intersectionTypeMultipleBoundsAsReceiver.kt"); } + @TestMetadata("intersectionTypesWithContravariantTypes.kt") + public void testIntersectionTypesWithContravariantTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.kt"); + } + @TestMetadata("intersectionWithEnum.kt") public void testIntersectionWithEnum() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/intersectionWithEnum.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 7d56bba5ef8..a1ac0ebb72a 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -10061,6 +10061,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/commonSuperTypeOfErrorTypes.kt"); } + @TestMetadata("compatibilityResolveWhenVariableHasComplexIntersectionType.kt") + public void testCompatibilityResolveWhenVariableHasComplexIntersectionType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/compatibilityResolveWhenVariableHasComplexIntersectionType.kt"); + } + @TestMetadata("completeInferenceIfManyFailed.kt") public void testCompleteInferenceIfManyFailed() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completeInferenceIfManyFailed.kt"); @@ -10211,6 +10216,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/intersectionTypeMultipleBoundsAsReceiver.kt"); } + @TestMetadata("intersectionTypesWithContravariantTypes.kt") + public void testIntersectionTypesWithContravariantTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/intersectionTypesWithContravariantTypes.kt"); + } + @TestMetadata("intersectionWithEnum.kt") public void testIntersectionWithEnum() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/intersectionWithEnum.kt");