[FIR] Fix K2 behavior according to RULES1

The compiler should only report diagnostics for
comparisons over builtins and identity-less types,
other incompatibilities should be reported
via inspections.

It's ok that in `equalityChecksOnIntegerTypes`
instead of `EQUALITY_NOT_APPLICABLE_WARNING` we get
`EQUALITY_NOT_APPLICABLE`, because
`ProperEqualityChecksInBuilderInferenceCalls`
is already active by default.

This change also replaces the notion of a representative superclass
with the least upper bound.
This makes complex types like
intersection/flexible transparent to
RULES1-based compatibility checks.
One way to look at it is to think
that this is an automatic way of handling
type parameters: automatic picking of
"interesting" bounds, and checking them against one another.

Note that `TypeIntersector.intersectTypes`
for `Int` and `T` where `T` is a type parameter
may return both `{Int & T}` or `null`
depending on `T`-s bounds. At the same time,
for type parameters `T` and `K` it will
always return `{T & K}`.

`ConeTypeIntersector.intersectTypes`, on the
other hand, will always return `{Int & T}`
irrespectively of the bounds. Meaning, the two
intersectors differ in corner cases.

`lowerBoundIfFlexible` call in `isLiterallyTypeParameter` is backed by
the `equalityOfFlexibleTypeParameters` test.

^KT-35134 #fixed-in-k2
^KT-22499 #fixed-in-k2
^KT-46383 #fixed-in-k2
This commit is contained in:
Nikolay Lunyak
2023-02-01 18:21:53 +02:00
committed by Space Team
parent 06e687addd
commit f0720c1d12
86 changed files with 1982 additions and 594 deletions
@@ -3848,6 +3848,46 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.INCOMPATIBLE_ENUM_COMPARISON) { firDiagnostic ->
IncompatibleEnumComparisonImpl(
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b),
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.FORBIDDEN_IDENTITY_EQUALS) { firDiagnostic ->
ForbiddenIdentityEqualsImpl(
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b),
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.FORBIDDEN_IDENTITY_EQUALS_WARNING) { firDiagnostic ->
ForbiddenIdentityEqualsWarningImpl(
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b),
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.DEPRECATED_IDENTITY_EQUALS) { firDiagnostic ->
DeprecatedIdentityEqualsImpl(
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b),
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.IMPLICIT_BOXING_IN_IDENTITY_EQUALS) { firDiagnostic ->
ImplicitBoxingInIdentityEqualsImpl(
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b),
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.INC_DEC_SHOULD_NOT_RETURN_UNIT) { firDiagnostic ->
IncDecShouldNotReturnUnitImpl(
firDiagnostic as KtPsiDiagnostic,
@@ -2684,6 +2684,36 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val rightType: KtType
}
abstract class IncompatibleEnumComparison : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = IncompatibleEnumComparison::class
abstract val leftType: KtType
abstract val rightType: KtType
}
abstract class ForbiddenIdentityEquals : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = ForbiddenIdentityEquals::class
abstract val leftType: KtType
abstract val rightType: KtType
}
abstract class ForbiddenIdentityEqualsWarning : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = ForbiddenIdentityEqualsWarning::class
abstract val leftType: KtType
abstract val rightType: KtType
}
abstract class DeprecatedIdentityEquals : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = DeprecatedIdentityEquals::class
abstract val leftType: KtType
abstract val rightType: KtType
}
abstract class ImplicitBoxingInIdentityEquals : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = ImplicitBoxingInIdentityEquals::class
abstract val leftType: KtType
abstract val rightType: KtType
}
abstract class IncDecShouldNotReturnUnit : KtFirDiagnostic<KtExpression>() {
override val diagnosticClass get() = IncDecShouldNotReturnUnit::class
}
@@ -3235,6 +3235,41 @@ internal class IncompatibleEnumComparisonErrorImpl(
override val token: KtLifetimeToken,
) : KtFirDiagnostic.IncompatibleEnumComparisonError(), KtAbstractFirDiagnostic<KtElement>
internal class IncompatibleEnumComparisonImpl(
override val leftType: KtType,
override val rightType: KtType,
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.IncompatibleEnumComparison(), KtAbstractFirDiagnostic<KtElement>
internal class ForbiddenIdentityEqualsImpl(
override val leftType: KtType,
override val rightType: KtType,
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.ForbiddenIdentityEquals(), KtAbstractFirDiagnostic<KtElement>
internal class ForbiddenIdentityEqualsWarningImpl(
override val leftType: KtType,
override val rightType: KtType,
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.ForbiddenIdentityEqualsWarning(), KtAbstractFirDiagnostic<KtElement>
internal class DeprecatedIdentityEqualsImpl(
override val leftType: KtType,
override val rightType: KtType,
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.DeprecatedIdentityEquals(), KtAbstractFirDiagnostic<KtElement>
internal class ImplicitBoxingInIdentityEqualsImpl(
override val leftType: KtType,
override val rightType: KtType,
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.ImplicitBoxingInIdentityEquals(), KtAbstractFirDiagnostic<KtElement>
internal class IncDecShouldNotReturnUnitImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,