Add compatibility resolve when variable has "bad" intersection type
#KT-39468 Fixed
This commit is contained in:
+10
@@ -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");
|
||||
|
||||
+6
@@ -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<KotlinType>): Boolean {
|
||||
return TypeIntersector.intersectTypes(types) == null
|
||||
}
|
||||
|
||||
override fun createConstraintSystemForOverloadResolution(
|
||||
constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns,
|
||||
): SimpleConstraintSystem {
|
||||
|
||||
+3
@@ -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<KotlinType>): Boolean
|
||||
|
||||
fun createConstraintSystemForOverloadResolution(
|
||||
constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns
|
||||
): SimpleConstraintSystem
|
||||
|
||||
+19
@@ -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(
|
||||
|
||||
+1
@@ -228,6 +228,7 @@ enum class KotlinCallKind(vararg resolutionPart: ResolutionPart) {
|
||||
CheckArgumentsInParenthesis,
|
||||
CheckExternalArgument,
|
||||
EagerResolveOfCallableReferences,
|
||||
CompatibilityOfTypeVariableAsIntersectionTypePart,
|
||||
PostponedVariablesInitializerResolutionPart
|
||||
),
|
||||
INVOKE(*FUNCTION.resolutionSequence.toTypedArray()),
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
|
||||
|
||||
abstract class Foo<T>
|
||||
|
||||
abstract class Bar<T> : Foo<T>(), Comparable<Bar<T>>
|
||||
|
||||
object Scope {
|
||||
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, other: Foo<T>) {}
|
||||
|
||||
object Nested {
|
||||
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T) {}
|
||||
|
||||
fun test(b: Bar<Long>) {
|
||||
<!DEBUG_INFO_CALL("fqName: Scope.Nested.greater; typeCall: function")!>greater(b, b)<!>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object OnlyOne {
|
||||
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T) {}
|
||||
|
||||
fun test(b: Bar<Long>) {
|
||||
<!DEBUG_INFO_CALL("fqName: OnlyOne.greater; typeCall: function")!>greater(b, b)<!>
|
||||
}
|
||||
}
|
||||
|
||||
object GoodOldCandidate {
|
||||
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T) {}
|
||||
|
||||
object Nested {
|
||||
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, other: Foo<T>) {}
|
||||
|
||||
fun test(b: Bar<Long>) {
|
||||
<!DEBUG_INFO_CALL("fqName: GoodOldCandidate.Nested.greater; typeCall: function")!>greater(b, b)<!>
|
||||
}
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
|
||||
|
||||
abstract class Foo<T>
|
||||
|
||||
abstract class Bar<T> : Foo<T>(), Comparable<Bar<T>>
|
||||
|
||||
object Scope {
|
||||
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, other: Foo<T>) {}
|
||||
|
||||
object Nested {
|
||||
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T) {}
|
||||
|
||||
fun test(b: Bar<Long>) {
|
||||
<!DEBUG_INFO_CALL("fqName: Scope.greater; typeCall: function")!><!COMPATIBILITY_WARNING!>greater<!>(b, b)<!>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object OnlyOne {
|
||||
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T) {}
|
||||
|
||||
fun test(b: Bar<Long>) {
|
||||
<!DEBUG_INFO_CALL("fqName: OnlyOne.greater; typeCall: function")!>greater(b, b)<!>
|
||||
}
|
||||
}
|
||||
|
||||
object GoodOldCandidate {
|
||||
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T) {}
|
||||
|
||||
object Nested {
|
||||
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, other: Foo<T>) {}
|
||||
|
||||
fun test(b: Bar<Long>) {
|
||||
<!DEBUG_INFO_CALL("fqName: GoodOldCandidate.Nested.greater; typeCall: function")!>greater(b, b)<!>
|
||||
}
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
package
|
||||
|
||||
public abstract class Bar</*0*/ T> : Foo<T>, kotlin.Comparable<Bar<T>> {
|
||||
public constructor Bar</*0*/ T>()
|
||||
public abstract override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Bar<T>): 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</*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 object GoodOldCandidate {
|
||||
private constructor GoodOldCandidate()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T> greater(/*0*/ x: Bar<in S>, /*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 </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T> greater(/*0*/ x: Bar<in S>, /*1*/ other: Foo<T>): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final fun test(/*0*/ b: Bar<kotlin.Long>): 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 </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T> greater(/*0*/ x: Bar<in S>, /*1*/ t: T): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final fun test(/*0*/ b: Bar<kotlin.Long>): 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 </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T> greater(/*0*/ x: Bar<in S>, /*1*/ other: Foo<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 </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T> greater(/*0*/ x: Bar<in S>, /*1*/ t: T): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final fun test(/*0*/ b: Bar<kotlin.Long>): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
|
||||
|
||||
abstract class Foo<T>
|
||||
|
||||
abstract class Bar<T> : Foo<T>(), Comparable<Bar<T>>
|
||||
|
||||
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T): Int = 0
|
||||
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, other: Foo<T>): String = ""
|
||||
|
||||
fun test(b: Bar<Long>) {
|
||||
val result = <!AMBIGUITY!>greater<!>(b, b)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Ambiguity: greater, [/greater, /greater]")!>result<!>
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
|
||||
|
||||
abstract class Foo<T>
|
||||
|
||||
abstract class Bar<T> : Foo<T>(), Comparable<Bar<T>>
|
||||
|
||||
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T): Int = 0
|
||||
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, other: Foo<T>): String = ""
|
||||
|
||||
fun test(b: Bar<Long>) {
|
||||
val result = greater(b, b)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>result<!>
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T> greater(/*0*/ x: Bar<in S>, /*1*/ other: Foo<T>): kotlin.String
|
||||
public fun </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T> greater(/*0*/ x: Bar<in S>, /*1*/ t: T): kotlin.Int
|
||||
public fun test(/*0*/ b: Bar<kotlin.Long>): kotlin.Unit
|
||||
|
||||
public abstract class Bar</*0*/ T> : Foo<T>, kotlin.Comparable<Bar<T>> {
|
||||
public constructor Bar</*0*/ T>()
|
||||
public abstract override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Bar<T>): 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</*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
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
Generated
+10
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user