[FE 1.0] Don't fail candidates which were marked with compatibility resolve previously
^KT-52431 Fixed ^KT-52393 Fixed
This commit is contained in:
committed by
teamcity
parent
73d676d9de
commit
02a430875f
+12
@@ -15593,6 +15593,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt52364.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt52393.kt")
|
||||
public void testKt52393() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt52393.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt52431.kt")
|
||||
public void testKt52431() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt52431.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullableEmptyIntersection.kt")
|
||||
public void testNullableEmptyIntersection() throws Exception {
|
||||
|
||||
+12
@@ -15593,6 +15593,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt52364.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt52393.kt")
|
||||
public void testKt52393() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt52393.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt52431.kt")
|
||||
public void testKt52431() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt52431.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullableEmptyIntersection.kt")
|
||||
public void testNullableEmptyIntersection() throws Exception {
|
||||
|
||||
+12
@@ -15593,6 +15593,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt52364.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt52393.kt")
|
||||
public void testKt52393() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt52393.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt52431.kt")
|
||||
public void testKt52431() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt52431.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullableEmptyIntersection.kt")
|
||||
public void testNullableEmptyIntersection() throws Exception {
|
||||
|
||||
@@ -581,10 +581,10 @@ internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionStage() {
|
||||
val upperTypes = variableWithConstraints.constraints.extractUpperTypesToCheckIntersectionEmptiness()
|
||||
|
||||
// TODO: consider reporting errors on bounded type variables by incompatible types but with other lower constraints
|
||||
if (
|
||||
variableWithConstraints.constraints.none { it.kind.isLower() }
|
||||
&& upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty()
|
||||
) {
|
||||
if (upperTypes.size <= 1 || variableWithConstraints.constraints.any { it.kind.isLower() })
|
||||
continue
|
||||
|
||||
if (upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty()) {
|
||||
sink.yieldDiagnostic(
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
InferredEmptyIntersectionDiagnostic(
|
||||
|
||||
+2
-1
@@ -152,7 +152,8 @@ class InferredEmptyIntersectionError(
|
||||
|
||||
class OnlyInputTypesDiagnostic(val typeVariable: TypeVariableMarker) : ConstraintSystemError(INAPPLICABLE)
|
||||
|
||||
object LowerPriorityToPreserveCompatibility : ConstraintSystemError(RESOLVED_NEED_PRESERVE_COMPATIBILITY)
|
||||
class LowerPriorityToPreserveCompatibility(val needToReportWarning: Boolean) :
|
||||
ConstraintSystemError(RESOLVED_NEED_PRESERVE_COMPATIBILITY)
|
||||
|
||||
fun Constraint.isExpectedTypePosition() =
|
||||
position.from is ExpectedTypeConstraintPosition<*> || position.from is DelegatedPropertyConstraintPosition<*>
|
||||
|
||||
+5
-1
@@ -450,9 +450,13 @@ class NewConstraintSystemImpl(
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection)
|
||||
val upperTypes = intersectionTypeConstructor.supertypes()
|
||||
|
||||
// Diagnostic with these incompatible types has already been reported at the resolution stage
|
||||
if (upperTypes.size <= 1 || storage.errors.any { it is InferredEmptyIntersection && it.incompatibleTypes == upperTypes })
|
||||
return
|
||||
|
||||
if (upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty()) {
|
||||
// Remove existing errors from resolution stage because a completion error is more precise
|
||||
storage.errors.removeIf { it is InferredEmptyIntersectionError || it is InferredEmptyIntersectionWarning }
|
||||
storage.errors.removeIf { it is InferredEmptyIntersection }
|
||||
val errorFactory =
|
||||
if (isInferredEmptyIntersectionForbidden) ::InferredEmptyIntersectionError else ::InferredEmptyIntersectionWarning
|
||||
addError(errorFactory(upperTypes, variable))
|
||||
|
||||
+16
-11
@@ -892,18 +892,23 @@ internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionPart() {
|
||||
for (variableWithConstraints in getSystem().getBuilder().currentStorage().notFixedTypeVariables.values) {
|
||||
val upperTypes = variableWithConstraints.constraints.extractUpperTypesToCheckIntersectionEmptiness()
|
||||
|
||||
// TODO: consider reporting errors on bounded type variables by incompatible types but with other lower constraints
|
||||
if (
|
||||
variableWithConstraints.constraints.none { it.kind.isLower() }
|
||||
&& upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty()
|
||||
) {
|
||||
val isInferredEmptyIntersectionForbidden =
|
||||
callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection)
|
||||
when {
|
||||
// TODO: consider reporting errors on bounded type variables by incompatible types but with other lower constraints
|
||||
upperTypes.size <= 1 || variableWithConstraints.constraints.any { it.kind.isLower() } ->
|
||||
continue
|
||||
wasPreviouslyDiscriminated(upperTypes) -> {
|
||||
markCandidateForCompatibilityResolve(needToReportWarning = false)
|
||||
continue
|
||||
}
|
||||
upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty() -> {
|
||||
val isInferredEmptyIntersectionForbidden =
|
||||
callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection)
|
||||
|
||||
val errorFactory = if (isInferredEmptyIntersectionForbidden || wasPreviouslyDiscriminated(upperTypes))
|
||||
::InferredEmptyIntersectionError
|
||||
else ::InferredEmptyIntersectionWarning
|
||||
addError(errorFactory(upperTypes, variableWithConstraints.typeVariable))
|
||||
val errorFactory = if (isInferredEmptyIntersectionForbidden)
|
||||
::InferredEmptyIntersectionError
|
||||
else ::InferredEmptyIntersectionWarning
|
||||
addError(errorFactory(upperTypes, variableWithConstraints.typeVariable))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-4
@@ -160,12 +160,15 @@ open class MutableResolvedCallAtom(
|
||||
override fun toString(): String = "$atom, candidate = $candidateDescriptor"
|
||||
}
|
||||
|
||||
fun ResolutionCandidate.markCandidateForCompatibilityResolve() {
|
||||
fun ResolutionCandidate.markCandidateForCompatibilityResolve(needToReportWarning: Boolean = true) {
|
||||
if (callComponents.languageVersionSettings.supportsFeature(LanguageFeature.DisableCompatibilityModeForNewInference)) return
|
||||
addDiagnostic(LowerPriorityToPreserveCompatibility.asDiagnostic())
|
||||
addDiagnostic(LowerPriorityToPreserveCompatibility(needToReportWarning).asDiagnostic())
|
||||
}
|
||||
|
||||
fun CallableReferencesCandidateFactory.markCandidateForCompatibilityResolve(diagnostics: SmartList<KotlinCallDiagnostic>) {
|
||||
fun CallableReferencesCandidateFactory.markCandidateForCompatibilityResolve(
|
||||
diagnostics: SmartList<KotlinCallDiagnostic>,
|
||||
needToReportWarning: Boolean = true,
|
||||
) {
|
||||
if (callComponents.languageVersionSettings.supportsFeature(LanguageFeature.DisableCompatibilityModeForNewInference)) return
|
||||
diagnostics.add(LowerPriorityToPreserveCompatibility.asDiagnostic())
|
||||
diagnostics.add(LowerPriorityToPreserveCompatibility(needToReportWarning).asDiagnostic())
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.LowerPriorityToPreserveCompatibility
|
||||
import org.jetbrains.kotlin.resolve.calls.model.constraintSystemError
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
|
||||
import org.jetbrains.kotlin.resolve.scopes.HierarchicalScope
|
||||
@@ -437,13 +440,21 @@ class TowerResolver {
|
||||
}
|
||||
|
||||
if (firstGroupWithResolved == null) return null
|
||||
if (compatibilityCandidate != null && compatibilityGroup !== firstGroupWithResolved) {
|
||||
if (compatibilityCandidate != null
|
||||
&& compatibilityGroup !== firstGroupWithResolved
|
||||
&& needToReportCompatibilityWarning(compatibilityCandidate)
|
||||
) {
|
||||
firstGroupWithResolved.forEach { it.addCompatibilityWarning(compatibilityCandidate) }
|
||||
}
|
||||
|
||||
return firstGroupWithResolved.filter(::isSuccessfulCandidate)
|
||||
}
|
||||
|
||||
private fun needToReportCompatibilityWarning(candidate: C) = candidate is ResolutionCandidate &&
|
||||
candidate.diagnostics.any {
|
||||
(it.constraintSystemError as? LowerPriorityToPreserveCompatibility)?.needToReportWarning == true
|
||||
}
|
||||
|
||||
private fun isSuccessfulCandidate(candidate: C): Boolean {
|
||||
return candidate.resultingApplicability == CandidateApplicability.RESOLVED
|
||||
|| candidate.resultingApplicability == CandidateApplicability.RESOLVED_WITH_ERROR
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
class Wrapper<T>
|
||||
|
||||
class WrapperFunctions {
|
||||
infix fun <T : Comparable<T>, S : T?> Wrapper<in S>.greaterEq(t: T): Unit = Unit
|
||||
|
||||
infix fun <T : Comparable<T>, S : T?> Wrapper<in S>.greaterEq(other: Wrapper<in S>): Unit = Unit // if this function is removed, it also works
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val wrapper = Wrapper<Long>()
|
||||
val number: Int = 5 // doesn't work
|
||||
// val number: Long = 5 // works
|
||||
|
||||
with (WrapperFunctions()) {
|
||||
<!ARGUMENT_TYPE_MISMATCH!>wrapper <!NONE_APPLICABLE!>greaterEq<!> number<!>
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
class Wrapper<T>
|
||||
|
||||
class WrapperFunctions {
|
||||
infix fun <T : Comparable<T>, S : T?> Wrapper<in S>.greaterEq(t: T): Unit = Unit
|
||||
|
||||
infix fun <T : Comparable<T>, S : T?> Wrapper<in S>.greaterEq(other: Wrapper<in S>): Unit = Unit // if this function is removed, it also works
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val wrapper = Wrapper<Long>()
|
||||
val number: Int = 5 // doesn't work
|
||||
// val number: Long = 5 // works
|
||||
|
||||
with (WrapperFunctions()) {
|
||||
wrapper <!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>greaterEq<!> number
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package
|
||||
|
||||
public fun main(): kotlin.Unit
|
||||
|
||||
public final class Wrapper</*0*/ T> {
|
||||
public constructor Wrapper</*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 WrapperFunctions {
|
||||
public constructor WrapperFunctions()
|
||||
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 infix fun </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T?> Wrapper<in S>.greaterEq(/*0*/ t: T): kotlin.Unit
|
||||
public final infix fun </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T?> Wrapper<in S>.greaterEq(/*0*/ other: Wrapper<in S>): kotlin.Unit
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
interface Expression<K>
|
||||
|
||||
interface ExpressionWithColumnType<K> : Expression<K>
|
||||
|
||||
class Column<T>: ExpressionWithColumnType<T>
|
||||
|
||||
infix fun <T : Comparable<T>, S : T?> ExpressionWithColumnType<in S>.less(t: T) {}
|
||||
|
||||
infix fun <T : Comparable<T>, S : T?> Expression<in S>.less(other: Expression<in S>) {}
|
||||
|
||||
fun main(x: Column<Long?>, y: Double) {
|
||||
x <!NONE_APPLICABLE!>less<!> y // error in 1.7.20, no error in 1.7.0
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
interface Expression<K>
|
||||
|
||||
interface ExpressionWithColumnType<K> : Expression<K>
|
||||
|
||||
class Column<T>: ExpressionWithColumnType<T>
|
||||
|
||||
infix fun <T : Comparable<T>, S : T?> ExpressionWithColumnType<in S>.less(t: T) {}
|
||||
|
||||
infix fun <T : Comparable<T>, S : T?> Expression<in S>.less(other: Expression<in S>) {}
|
||||
|
||||
fun main(x: Column<Long?>, y: Double) {
|
||||
x <!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>less<!> y // error in 1.7.20, no error in 1.7.0
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package
|
||||
|
||||
public fun main(/*0*/ x: Column<kotlin.Long?>, /*1*/ y: kotlin.Double): kotlin.Unit
|
||||
public infix fun </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T?> Expression<in S>.less(/*0*/ other: Expression<in S>): kotlin.Unit
|
||||
public infix fun </*0*/ T : kotlin.Comparable<T>, /*1*/ S : T?> ExpressionWithColumnType<in S>.less(/*0*/ t: T): kotlin.Unit
|
||||
|
||||
public final class Column</*0*/ T> : ExpressionWithColumnType<T> {
|
||||
public constructor Column</*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 interface Expression</*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 ExpressionWithColumnType</*0*/ K> : Expression<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
|
||||
}
|
||||
@@ -8,5 +8,5 @@ fun <T : Comparable<T>, S : T?> Expression<in S>.greater(other: T): GreaterOp =
|
||||
fun foo(countExpr: Expression<Long>) {
|
||||
countExpr.greater(0)
|
||||
countExpr.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>greater<!>("0")
|
||||
countExpr.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>greater<!><String, Nothing>("0")
|
||||
countExpr.greater<String, Nothing>("0")
|
||||
}
|
||||
|
||||
Generated
+12
@@ -15599,6 +15599,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt52364.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt52393.kt")
|
||||
public void testKt52393() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt52393.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt52431.kt")
|
||||
public void testKt52431() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt52431.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullableEmptyIntersection.kt")
|
||||
public void testNullableEmptyIntersection() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user