[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,
@@ -159,6 +159,24 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/CompareToWithErrorType.kt");
}
@Test
@TestMetadata("comparingArbitraryClasses.kt")
public void testComparingArbitraryClasses() throws Exception {
runTest("compiler/testData/diagnostics/tests/comparingArbitraryClasses.kt");
}
@Test
@TestMetadata("comparingCallableReferencesWithInstanceOfJavaClass.kt")
public void testComparingCallableReferencesWithInstanceOfJavaClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt");
}
@Test
@TestMetadata("comparisonOfGenericInterfaceWithGenericClass.kt")
public void testComparisonOfGenericInterfaceWithGenericClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt");
}
@Test
@TestMetadata("Constants.kt")
public void testConstants() throws Exception {
@@ -243,6 +261,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/DiamondProperty.kt");
}
@Test
@TestMetadata("differentNumericTypesFromSmartCast.kt")
public void testDifferentNumericTypesFromSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt");
}
@Test
@TestMetadata("Dollar.kt")
public void testDollar() throws Exception {
@@ -255,6 +279,18 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/EnumEntryAsType.kt");
}
@Test
@TestMetadata("equalityComparisonToSelf.kt")
public void testEqualityComparisonToSelf() throws Exception {
runTest("compiler/testData/diagnostics/tests/equalityComparisonToSelf.kt");
}
@Test
@TestMetadata("equalityWithSmartCastInIfBlock.kt")
public void testEqualityWithSmartCastInIfBlock() throws Exception {
runTest("compiler/testData/diagnostics/tests/equalityWithSmartCastInIfBlock.kt");
}
@Test
@TestMetadata("ExtensionCallInvoke.kt")
public void testExtensionCallInvoke() throws Exception {
@@ -10392,6 +10428,18 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/enum/enumWithEmptyName.kt");
}
@Test
@TestMetadata("equalityOfEnumAndParameter.kt")
public void testEqualityOfEnumAndParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt");
}
@Test
@TestMetadata("equalityOfFlexibleTypeParameters.kt")
public void testEqualityOfFlexibleTypeParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/enum/equalityOfFlexibleTypeParameters.kt");
}
@Test
@TestMetadata("ExplicitConstructorCall.kt")
public void testExplicitConstructorCall() throws Exception {
@@ -35359,6 +35407,30 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/testsWithStdLib/commonCollections.kt");
}
@Test
@TestMetadata("comparingDifferentSubclassesCommonInterface.kt")
public void testComparingDifferentSubclassesCommonInterface() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt");
}
@Test
@TestMetadata("comparingPlatformTypes.kt")
public void testComparingPlatformTypes() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt");
}
@Test
@TestMetadata("comparingSmartCastValueToBoolean.kt")
public void testComparingSmartCastValueToBoolean() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingSmartCastValueToBoolean.kt");
}
@Test
@TestMetadata("comparingTripleWithPair.kt")
public void testComparingTripleWithPair() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt");
}
@Test
@TestMetadata("compileTimeUnsignedArray.kt")
public void testCompileTimeUnsignedArray() throws Exception {
@@ -35383,6 +35455,24 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/testsWithStdLib/enumEntryInitialization.kt");
}
@Test
@TestMetadata("equalityCompatibilityCommonCases.kt")
public void testEqualityCompatibilityCommonCases() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityCommonCases.kt");
}
@Test
@TestMetadata("equalityCompatibilityOldBehavior_Off.kt")
public void testEqualityCompatibilityOldBehavior_Off() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_Off.kt");
}
@Test
@TestMetadata("equalityCompatibilityOldBehavior_On.kt")
public void testEqualityCompatibilityOldBehavior_On() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_On.kt");
}
@Test
@TestMetadata("exitProcess.kt")
public void testExitProcess() throws Exception {
@@ -159,6 +159,24 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/CompareToWithErrorType.kt");
}
@Test
@TestMetadata("comparingArbitraryClasses.kt")
public void testComparingArbitraryClasses() throws Exception {
runTest("compiler/testData/diagnostics/tests/comparingArbitraryClasses.kt");
}
@Test
@TestMetadata("comparingCallableReferencesWithInstanceOfJavaClass.kt")
public void testComparingCallableReferencesWithInstanceOfJavaClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt");
}
@Test
@TestMetadata("comparisonOfGenericInterfaceWithGenericClass.kt")
public void testComparisonOfGenericInterfaceWithGenericClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt");
}
@Test
@TestMetadata("Constants.kt")
public void testConstants() throws Exception {
@@ -243,6 +261,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/DiamondProperty.kt");
}
@Test
@TestMetadata("differentNumericTypesFromSmartCast.kt")
public void testDifferentNumericTypesFromSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt");
}
@Test
@TestMetadata("Dollar.kt")
public void testDollar() throws Exception {
@@ -255,6 +279,18 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/EnumEntryAsType.kt");
}
@Test
@TestMetadata("equalityComparisonToSelf.kt")
public void testEqualityComparisonToSelf() throws Exception {
runTest("compiler/testData/diagnostics/tests/equalityComparisonToSelf.kt");
}
@Test
@TestMetadata("equalityWithSmartCastInIfBlock.kt")
public void testEqualityWithSmartCastInIfBlock() throws Exception {
runTest("compiler/testData/diagnostics/tests/equalityWithSmartCastInIfBlock.kt");
}
@Test
@TestMetadata("ExtensionCallInvoke.kt")
public void testExtensionCallInvoke() throws Exception {
@@ -10392,6 +10428,18 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/enum/enumWithEmptyName.kt");
}
@Test
@TestMetadata("equalityOfEnumAndParameter.kt")
public void testEqualityOfEnumAndParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt");
}
@Test
@TestMetadata("equalityOfFlexibleTypeParameters.kt")
public void testEqualityOfFlexibleTypeParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/enum/equalityOfFlexibleTypeParameters.kt");
}
@Test
@TestMetadata("ExplicitConstructorCall.kt")
public void testExplicitConstructorCall() throws Exception {
@@ -35359,6 +35407,30 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/testsWithStdLib/commonCollections.kt");
}
@Test
@TestMetadata("comparingDifferentSubclassesCommonInterface.kt")
public void testComparingDifferentSubclassesCommonInterface() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt");
}
@Test
@TestMetadata("comparingPlatformTypes.kt")
public void testComparingPlatformTypes() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt");
}
@Test
@TestMetadata("comparingSmartCastValueToBoolean.kt")
public void testComparingSmartCastValueToBoolean() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingSmartCastValueToBoolean.kt");
}
@Test
@TestMetadata("comparingTripleWithPair.kt")
public void testComparingTripleWithPair() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt");
}
@Test
@TestMetadata("compileTimeUnsignedArray.kt")
public void testCompileTimeUnsignedArray() throws Exception {
@@ -35383,6 +35455,24 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/testsWithStdLib/enumEntryInitialization.kt");
}
@Test
@TestMetadata("equalityCompatibilityCommonCases.kt")
public void testEqualityCompatibilityCommonCases() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityCommonCases.kt");
}
@Test
@TestMetadata("equalityCompatibilityOldBehavior_Off.kt")
public void testEqualityCompatibilityOldBehavior_Off() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_Off.kt");
}
@Test
@TestMetadata("equalityCompatibilityOldBehavior_On.kt")
public void testEqualityCompatibilityOldBehavior_On() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_On.kt");
}
@Test
@TestMetadata("exitProcess.kt")
public void testExitProcess() throws Exception {
@@ -33,7 +33,7 @@ fun case1(javaClass: JavaClass?) {
}
class Case1(val javaClass: JavaClass?) {
val x = if (javaClass != null) { it -> <!EQUALITY_NOT_APPLICABLE_WARNING!>it == javaClass<!> } else BooCase2.FILTER
val x = if (javaClass != null) { it -> it == javaClass } else BooCase2.FILTER
}
class BooCase1() {
@@ -101,7 +101,7 @@ fun test_9(a: Int, b: Int?) {
}
b<!UNSAFE_CALL!>.<!>inc()
if (a === b) {
if (<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a === b<!>) {
b.inc()
}
b<!UNSAFE_CALL!>.<!>inc()
@@ -111,7 +111,7 @@ fun test_9(a: Int, b: Int?) {
}
b<!UNSAFE_CALL!>.<!>inc()
if (b === a) {
if (<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>b === a<!>) {
b.inc()
}
b<!UNSAFE_CALL!>.<!>inc()
@@ -22,12 +22,12 @@ enum class Second {
val ONE = Second.THREE
fun foo(f: First) = <!NO_ELSE_IN_WHEN!>when<!> (f) {
<!INCOMPATIBLE_TYPES!>ONE<!> -> 1
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>ONE<!> -> 1
TWO -> 2
}
fun bar(s: Second) = <!NO_ELSE_IN_WHEN!>when<!> (s) {
<!INCOMPATIBLE_TYPES!>THREE<!> -> 3
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>THREE<!> -> 3
FOUR -> 4
}
@@ -1,4 +1,3 @@
/*
* UNEXPECTED BEHAVIOUR
* ISSUES: KT-37081
@@ -1,8 +1,9 @@
// FULL_JDK
// ISSUE: KT-48113
// STATUS: On a K2 technical meeting on Mar-27-2023 it was decided to report a warning
// WITH_EXTENDED_CHECKERS
fun collapse(path: String) {
val result = (path as <!PLATFORM_CLASS_MAPPED_TO_KOTLIN!>java.lang.String<!>).replace("123", "456")
if (result !== path) {}
if (<!EQUALITY_NOT_APPLICABLE_WARNING!>result !== path<!>) {}
}
@@ -159,6 +159,24 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/CompareToWithErrorType.kt");
}
@Test
@TestMetadata("comparingArbitraryClasses.kt")
public void testComparingArbitraryClasses() throws Exception {
runTest("compiler/testData/diagnostics/tests/comparingArbitraryClasses.kt");
}
@Test
@TestMetadata("comparingCallableReferencesWithInstanceOfJavaClass.kt")
public void testComparingCallableReferencesWithInstanceOfJavaClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt");
}
@Test
@TestMetadata("comparisonOfGenericInterfaceWithGenericClass.kt")
public void testComparisonOfGenericInterfaceWithGenericClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt");
}
@Test
@TestMetadata("Constants.kt")
public void testConstants() throws Exception {
@@ -243,6 +261,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/DiamondProperty.kt");
}
@Test
@TestMetadata("differentNumericTypesFromSmartCast.kt")
public void testDifferentNumericTypesFromSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt");
}
@Test
@TestMetadata("Dollar.kt")
public void testDollar() throws Exception {
@@ -255,6 +279,18 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/EnumEntryAsType.kt");
}
@Test
@TestMetadata("equalityComparisonToSelf.kt")
public void testEqualityComparisonToSelf() throws Exception {
runTest("compiler/testData/diagnostics/tests/equalityComparisonToSelf.kt");
}
@Test
@TestMetadata("equalityWithSmartCastInIfBlock.kt")
public void testEqualityWithSmartCastInIfBlock() throws Exception {
runTest("compiler/testData/diagnostics/tests/equalityWithSmartCastInIfBlock.kt");
}
@Test
@TestMetadata("ExtensionCallInvoke.kt")
public void testExtensionCallInvoke() throws Exception {
@@ -10392,6 +10428,18 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/enum/enumWithEmptyName.kt");
}
@Test
@TestMetadata("equalityOfEnumAndParameter.kt")
public void testEqualityOfEnumAndParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt");
}
@Test
@TestMetadata("equalityOfFlexibleTypeParameters.kt")
public void testEqualityOfFlexibleTypeParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/enum/equalityOfFlexibleTypeParameters.kt");
}
@Test
@TestMetadata("ExplicitConstructorCall.kt")
public void testExplicitConstructorCall() throws Exception {
@@ -35359,6 +35407,30 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/testsWithStdLib/commonCollections.kt");
}
@Test
@TestMetadata("comparingDifferentSubclassesCommonInterface.kt")
public void testComparingDifferentSubclassesCommonInterface() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt");
}
@Test
@TestMetadata("comparingPlatformTypes.kt")
public void testComparingPlatformTypes() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt");
}
@Test
@TestMetadata("comparingSmartCastValueToBoolean.kt")
public void testComparingSmartCastValueToBoolean() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingSmartCastValueToBoolean.kt");
}
@Test
@TestMetadata("comparingTripleWithPair.kt")
public void testComparingTripleWithPair() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt");
}
@Test
@TestMetadata("compileTimeUnsignedArray.kt")
public void testCompileTimeUnsignedArray() throws Exception {
@@ -35383,6 +35455,24 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/testsWithStdLib/enumEntryInitialization.kt");
}
@Test
@TestMetadata("equalityCompatibilityCommonCases.kt")
public void testEqualityCompatibilityCommonCases() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityCommonCases.kt");
}
@Test
@TestMetadata("equalityCompatibilityOldBehavior_Off.kt")
public void testEqualityCompatibilityOldBehavior_Off() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_Off.kt");
}
@Test
@TestMetadata("equalityCompatibilityOldBehavior_On.kt")
public void testEqualityCompatibilityOldBehavior_On() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_On.kt");
}
@Test
@TestMetadata("exitProcess.kt")
public void testExitProcess() throws Exception {
@@ -159,6 +159,24 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/CompareToWithErrorType.kt");
}
@Test
@TestMetadata("comparingArbitraryClasses.kt")
public void testComparingArbitraryClasses() throws Exception {
runTest("compiler/testData/diagnostics/tests/comparingArbitraryClasses.kt");
}
@Test
@TestMetadata("comparingCallableReferencesWithInstanceOfJavaClass.kt")
public void testComparingCallableReferencesWithInstanceOfJavaClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt");
}
@Test
@TestMetadata("comparisonOfGenericInterfaceWithGenericClass.kt")
public void testComparisonOfGenericInterfaceWithGenericClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt");
}
@Test
@TestMetadata("Constants.kt")
public void testConstants() throws Exception {
@@ -243,6 +261,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/DiamondProperty.kt");
}
@Test
@TestMetadata("differentNumericTypesFromSmartCast.kt")
public void testDifferentNumericTypesFromSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt");
}
@Test
@TestMetadata("Dollar.kt")
public void testDollar() throws Exception {
@@ -255,6 +279,18 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/EnumEntryAsType.kt");
}
@Test
@TestMetadata("equalityComparisonToSelf.kt")
public void testEqualityComparisonToSelf() throws Exception {
runTest("compiler/testData/diagnostics/tests/equalityComparisonToSelf.kt");
}
@Test
@TestMetadata("equalityWithSmartCastInIfBlock.kt")
public void testEqualityWithSmartCastInIfBlock() throws Exception {
runTest("compiler/testData/diagnostics/tests/equalityWithSmartCastInIfBlock.kt");
}
@Test
@TestMetadata("ExtensionCallInvoke.kt")
public void testExtensionCallInvoke() throws Exception {
@@ -10398,6 +10434,18 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/enum/enumWithEmptyName.kt");
}
@Test
@TestMetadata("equalityOfEnumAndParameter.kt")
public void testEqualityOfEnumAndParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt");
}
@Test
@TestMetadata("equalityOfFlexibleTypeParameters.kt")
public void testEqualityOfFlexibleTypeParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/enum/equalityOfFlexibleTypeParameters.kt");
}
@Test
@TestMetadata("ExplicitConstructorCall.kt")
public void testExplicitConstructorCall() throws Exception {
@@ -35455,6 +35503,30 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/testsWithStdLib/commonCollections.kt");
}
@Test
@TestMetadata("comparingDifferentSubclassesCommonInterface.kt")
public void testComparingDifferentSubclassesCommonInterface() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt");
}
@Test
@TestMetadata("comparingPlatformTypes.kt")
public void testComparingPlatformTypes() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt");
}
@Test
@TestMetadata("comparingSmartCastValueToBoolean.kt")
public void testComparingSmartCastValueToBoolean() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingSmartCastValueToBoolean.kt");
}
@Test
@TestMetadata("comparingTripleWithPair.kt")
public void testComparingTripleWithPair() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt");
}
@Test
@TestMetadata("compileTimeUnsignedArray.kt")
public void testCompileTimeUnsignedArray() throws Exception {
@@ -35479,6 +35551,24 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/testsWithStdLib/enumEntryInitialization.kt");
}
@Test
@TestMetadata("equalityCompatibilityCommonCases.kt")
public void testEqualityCompatibilityCommonCases() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityCommonCases.kt");
}
@Test
@TestMetadata("equalityCompatibilityOldBehavior_Off.kt")
public void testEqualityCompatibilityOldBehavior_Off() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_Off.kt");
}
@Test
@TestMetadata("equalityCompatibilityOldBehavior_On.kt")
public void testEqualityCompatibilityOldBehavior_On() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_On.kt");
}
@Test
@TestMetadata("exitProcess.kt")
public void testExitProcess() throws Exception {
@@ -1338,6 +1338,26 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
parameter<ConeKotlinType>("leftType")
parameter<ConeKotlinType>("rightType")
}
val INCOMPATIBLE_ENUM_COMPARISON by warning<KtElement> {
parameter<ConeKotlinType>("leftType")
parameter<ConeKotlinType>("rightType")
}
val FORBIDDEN_IDENTITY_EQUALS by error<KtElement> {
parameter<ConeKotlinType>("leftType")
parameter<ConeKotlinType>("rightType")
}
val FORBIDDEN_IDENTITY_EQUALS_WARNING by warning<KtElement> {
parameter<ConeKotlinType>("leftType")
parameter<ConeKotlinType>("rightType")
}
val DEPRECATED_IDENTITY_EQUALS by warning<KtElement> {
parameter<ConeKotlinType>("leftType")
parameter<ConeKotlinType>("rightType")
}
val IMPLICIT_BOXING_IN_IDENTITY_EQUALS by warning<KtElement> {
parameter<ConeKotlinType>("leftType")
parameter<ConeKotlinType>("rightType")
}
val INC_DEC_SHOULD_NOT_RETURN_UNIT by error<KtExpression>(PositioningStrategy.OPERATOR)
val ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT by error<KtExpression>(PositioningStrategy.OPERATOR) {
parameter<FirNamedFunctionSymbol>("functionSymbol")
@@ -693,6 +693,11 @@ object FirErrors {
val EQUALITY_NOT_APPLICABLE by error3<KtBinaryExpression, String, ConeKotlinType, ConeKotlinType>()
val EQUALITY_NOT_APPLICABLE_WARNING by warning3<KtBinaryExpression, String, ConeKotlinType, ConeKotlinType>()
val INCOMPATIBLE_ENUM_COMPARISON_ERROR by error2<KtElement, ConeKotlinType, ConeKotlinType>()
val INCOMPATIBLE_ENUM_COMPARISON by warning2<KtElement, ConeKotlinType, ConeKotlinType>()
val FORBIDDEN_IDENTITY_EQUALS by error2<KtElement, ConeKotlinType, ConeKotlinType>()
val FORBIDDEN_IDENTITY_EQUALS_WARNING by warning2<KtElement, ConeKotlinType, ConeKotlinType>()
val DEPRECATED_IDENTITY_EQUALS by warning2<KtElement, ConeKotlinType, ConeKotlinType>()
val IMPLICIT_BOXING_IN_IDENTITY_EQUALS by warning2<KtElement, ConeKotlinType, ConeKotlinType>()
val INC_DEC_SHOULD_NOT_RETURN_UNIT by error0<KtExpression>(SourceElementPositioningStrategies.OPERATOR)
val ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT by error2<KtExpression, FirNamedFunctionSymbol, String>(SourceElementPositioningStrategies.OPERATOR)
val PROPERTY_AS_OPERATOR by error1<PsiElement, FirPropertySymbol>(SourceElementPositioningStrategies.OPERATOR)
@@ -5,109 +5,247 @@
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.KtRealSourceElementKind
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.analysis.checkers.ConeTypeCompatibilityChecker
import org.jetbrains.kotlin.fir.analysis.checkers.ConeTypeCompatibilityChecker.isCompatible
import org.jetbrains.kotlin.KtRealSourceElementKind
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory2
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.collectUpperBounds
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
import org.jetbrains.kotlin.fir.declarations.utils.isInline
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirOperation
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression
import org.jetbrains.kotlin.fir.isPrimitiveType
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.text
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
object FirEqualityCompatibilityChecker : FirEqualityOperatorCallChecker() {
override fun check(expression: FirEqualityOperatorCall, context: CheckerContext, reporter: DiagnosticReporter) {
val arguments = expression.argumentList.arguments
if (arguments.size != 2) return
val lType = arguments[0].typeRef.coneType
val rType = arguments[1].typeRef.coneType
checkCompatibility(lType, rType, context, expression, reporter)
checkSensibleness(lType, rType, context, expression, reporter)
}
require(arguments.size == 2) { "Equality operator call with non-2 arguments" }
private fun checkCompatibility(
lType: ConeKotlinType,
rType: ConeKotlinType,
context: CheckerContext,
expression: FirEqualityOperatorCall,
reporter: DiagnosticReporter
) {
// If one of the type is already `Nothing?`, we skip reporting further comparison. This is to allow comparing with `null`, which has
// type `Nothing?`
if (lType.isNullableNothing || rType.isNullableNothing) return
val inferenceContext = context.session.typeContext
val l = arguments[0].toArgumentInfo(context)
val r = arguments[1].toArgumentInfo(context)
val compatibility = try {
inferenceContext.isCompatible(lType, rType)
} catch (e: Throwable) {
throw IllegalStateException(
"Exception while determining type compatibility: lType: $lType, rType: $rType, " +
"equality ${expression.render()}, " +
"file ${context.containingFile?.name}",
e
checkSenselessness(l.smartCastType, r.smartCastType, context, expression, reporter)
val checkApplicability = when (expression.operation) {
FirOperation.EQ, FirOperation.NOT_EQ -> ::checkEqualityApplicability
FirOperation.IDENTITY, FirOperation.NOT_IDENTITY -> ::checkIdentityApplicability
else -> error("Invalid operator of FirEqualityOperatorCall")
}
checkApplicability(l.originalTypeInfo, r.originalTypeInfo, context).ifInapplicable {
// Ideally this should match cases when K1
// sees a non-empty intersection and none of the
// types is an enum, but intersections in K1
// work differently from intersections in K2.
val isCaseMissedByK1 = it != Applicability.INAPPLICABLE_AS_ENUMS
&& l.originalTypeInfo.isLiterallyTypeParameter
&& r.originalTypeInfo.isLiterallyTypeParameter
val replicateK1Behavior = !context.languageVersionSettings.supportsFeature(LanguageFeature.ReportErrorsForComparisonOperators)
return reporter.reportInapplicabilityDiagnostic(
expression, it, expression.operation, forceWarning = isCaseMissedByK1 && replicateK1Behavior,
l.originalTypeInfo, r.originalTypeInfo,
l.userType, r.userType, context,
)
}
if (compatibility != ConeTypeCompatibilityChecker.Compatibility.COMPATIBLE) {
when (expression.source?.kind) {
KtRealSourceElementKind -> {
// Note: FE1.0 reports INCOMPATIBLE_ENUM_COMPARISON_ERROR only when TypeIntersector.isIntersectionEmpty() thinks the
// given types are compatible. Exactly mimicking the behavior of FE1.0 is difficult and does not seem to provide any
// value. So instead, we deterministically output INCOMPATIBLE_ENUM_COMPARISON_ERROR if at least one of the value is an
// enum.
if (compatibility == ConeTypeCompatibilityChecker.Compatibility.HARD_INCOMPATIBLE &&
(lType.isEnumType(context) || rType.isEnumType(context))
) {
reporter.reportOn(
expression.source,
FirErrors.INCOMPATIBLE_ENUM_COMPARISON_ERROR,
lType,
rType,
context
)
} else {
reporter.reportOn(
expression.source,
if (compatibility == ConeTypeCompatibilityChecker.Compatibility.HARD_INCOMPATIBLE) {
FirErrors.EQUALITY_NOT_APPLICABLE
} else {
FirErrors.EQUALITY_NOT_APPLICABLE_WARNING
},
expression.operation.operator,
lType,
rType,
context
)
}
}
else -> reporter.reportOn(
expression.source,
if (compatibility == ConeTypeCompatibilityChecker.Compatibility.HARD_INCOMPATIBLE) {
FirErrors.INCOMPATIBLE_TYPES
} else {
FirErrors.INCOMPATIBLE_TYPES_WARNING
},
lType,
rType,
context
)
}
if (l.argument !is FirSmartCastExpression && r.argument !is FirSmartCastExpression) {
return
}
checkApplicability(l.smartCastTypeInfo, r.smartCastTypeInfo, context).ifInapplicable {
return reporter.reportInapplicabilityDiagnostic(
expression, it, expression.operation, forceWarning = true,
l.smartCastTypeInfo, r.smartCastTypeInfo,
l.userType, r.userType, context,
)
}
}
private fun ConeKotlinType.isEnumType(
context: CheckerContext
): Boolean {
if (isEnum) return true
val firRegularClassSymbol = (this as? ConeClassLikeType)?.lookupTag?.toFirRegularClassSymbol(context.session) ?: return false
return firRegularClassSymbol.isEnumClass
private fun checkEqualityApplicability(l: TypeInfo, r: TypeInfo, context: CheckerContext): Applicability {
val oneIsBuiltin = l.isBuiltin || r.isBuiltin
// The compiler should only check comparisons
// when builtins are involved.
// Builtins' supertypes must not be present in
// the list of special fqNames described in RULES1
return when {
oneIsBuiltin && shouldReportAsPerRules1(l, r, context) -> getInapplicabilityFor(l, r)
else -> Applicability.APPLICABLE
}
}
private fun checkSensibleness(
private fun checkIdentityApplicability(l: TypeInfo, r: TypeInfo, context: CheckerContext): Applicability {
// The compiler should only check comparisons
// when identity-less types or builtins are involved.
val oneIsBuiltin = l.isBuiltin || r.isBuiltin
val oneIsNotNull = !l.type.isNullable || !r.type.isNullable
return when {
l.isIdentityLess || r.isIdentityLess -> Applicability.INAPPLICABLE_AS_IDENTITY_LESS
oneIsBuiltin && oneIsNotNull && shouldReportAsPerRules1(l, r, context) -> getInapplicabilityFor(l, r)
else -> Applicability.APPLICABLE
}
}
private fun getInapplicabilityFor(l: TypeInfo, r: TypeInfo): Applicability {
val isIntersectionEmpty = l.enforcesEmptyIntersection || r.enforcesEmptyIntersection
val isOneEnum = l.isEnumClass || r.isEnumClass
return when {
!isIntersectionEmpty && isOneEnum -> Applicability.INAPPLICABLE_AS_ENUMS
else -> Applicability.GENERALLY_INAPPLICABLE
}
}
private fun shouldReportAsPerRules1(l: TypeInfo, r: TypeInfo, context: CheckerContext): Boolean {
// Builtins are always final classes, so
// we only need to check if one is related
// to the other
fun TypeInfo.isSubclassOf(other: TypeInfo) = when {
other.enforcesEmptyIntersection -> type.classId == other.type.classId
else -> notNullType.isSubtypeOf(other.notNullType, context.session)
}
return when {
l.type.isNothingOrNullableNothing || r.type.isNothingOrNullableNothing -> false
else -> !l.isSubclassOf(r) && !r.isSubclassOf(l)
}
}
private enum class Applicability {
APPLICABLE,
GENERALLY_INAPPLICABLE,
INAPPLICABLE_AS_ENUMS,
INAPPLICABLE_AS_IDENTITY_LESS,
}
private inline fun Applicability.ifInapplicable(block: (Applicability) -> Unit) = when (this) {
Applicability.APPLICABLE -> {}
else -> block(this)
}
private fun getGeneralInapplicabilityDiagnostic(forceWarning: Boolean) = when {
forceWarning -> FirErrors.EQUALITY_NOT_APPLICABLE_WARNING
else -> FirErrors.EQUALITY_NOT_APPLICABLE
}
private fun getIdentityLessInapplicabilityDiagnostic(
l: TypeInfo,
r: TypeInfo,
forceWarning: Boolean,
context: CheckerContext,
): KtDiagnosticFactory2<ConeKotlinType, ConeKotlinType> {
val areBothPrimitives = l.isPrimitive && r.isPrimitive
val areSameTypes = l.type.classId == r.type.classId
val shouldProperlyReportError = context.languageVersionSettings.supportsFeature(LanguageFeature.ReportErrorsForComparisonOperators)
// In this case K1 reports nothing
val shouldRelaxDiagnostic = (l.type.isNullableNothing || r.type.isNullableNothing) && !shouldProperlyReportError
return when {
// See: KT-28252
areSameTypes && areBothPrimitives -> FirErrors.DEPRECATED_IDENTITY_EQUALS
// The same reason as above
isIdentityComparedWithImplicitBoxing(l, r, context.session) -> FirErrors.IMPLICIT_BOXING_IN_IDENTITY_EQUALS
forceWarning || shouldRelaxDiagnostic -> FirErrors.FORBIDDEN_IDENTITY_EQUALS_WARNING
else -> FirErrors.FORBIDDEN_IDENTITY_EQUALS
}
}
private fun isIdentityComparedWithImplicitBoxing(l: TypeInfo, r: TypeInfo, session: FirSession) =
isPrimitiveWithNonPrimitiveSupertype(l, r, session) || isPrimitiveWithNonPrimitiveSupertype(r, l, session)
private fun isPrimitiveWithNonPrimitiveSupertype(l: TypeInfo, r: TypeInfo, session: FirSession) =
l.isPrimitive && !r.isPrimitive && l.type.isSubtypeOf(r.type, session)
private fun getSourceLessInapplicabilityDiagnostic(forceWarning: Boolean) = when {
forceWarning -> FirErrors.INCOMPATIBLE_TYPES_WARNING
else -> FirErrors.INCOMPATIBLE_TYPES
}
private fun getEnumInapplicabilityDiagnostic(
l: TypeInfo,
r: TypeInfo,
forceWarning: Boolean,
context: CheckerContext,
): KtDiagnosticFactory2<ConeKotlinType, ConeKotlinType> {
// Preserving the behavior on the old test data
// simplifies detecting fir-differences,
// which is crucial for this checker
val isOldTestData = !context.languageVersionSettings.supportsFeature(
LanguageFeature.ProhibitComparisonOfIncompatibleEnums,
)
// In this corner case K1 reports nothing
val bothNullableEnums = l.isNullableEnum && r.isNullableEnum
// When comparing enums, for type parameters K1
// tries to pick the "representative" superclass
// instead of the proper intersection.
// We can't guarantee that in such cases
// K2 reports the same as K1
val areIntersectionsInvolved = l.type is ConeIntersectionType || r.type is ConeIntersectionType
val shouldProperlyReportError = context.languageVersionSettings.supportsFeature(LanguageFeature.ReportErrorsForComparisonOperators)
val shouldRelaxDiagnostic = (bothNullableEnums || areIntersectionsInvolved) && !shouldProperlyReportError
return when {
forceWarning || isOldTestData || shouldRelaxDiagnostic -> FirErrors.INCOMPATIBLE_ENUM_COMPARISON
else -> FirErrors.INCOMPATIBLE_ENUM_COMPARISON_ERROR
}
}
private fun DiagnosticReporter.reportInapplicabilityDiagnostic(
expression: FirEqualityOperatorCall,
applicability: Applicability,
operation: FirOperation,
forceWarning: Boolean,
l: TypeInfo,
r: TypeInfo,
lUserType: ConeKotlinType,
rUserType: ConeKotlinType,
context: CheckerContext,
): Unit = when {
applicability == Applicability.INAPPLICABLE_AS_IDENTITY_LESS -> reportOn(
expression.source, getIdentityLessInapplicabilityDiagnostic(l, r, forceWarning, context),
lUserType, rUserType, context,
)
applicability == Applicability.INAPPLICABLE_AS_ENUMS -> reportOn(
expression.source, getEnumInapplicabilityDiagnostic(l, r, forceWarning, context),
lUserType, rUserType, context,
)
// This check ensures K2 reports the same diagnostics as K1 used to.
expression.source?.kind !is KtRealSourceElementKind -> reportOn(
expression.source, getSourceLessInapplicabilityDiagnostic(forceWarning),
lUserType, rUserType, context,
)
applicability == Applicability.GENERALLY_INAPPLICABLE -> reportOn(
expression.source, getGeneralInapplicabilityDiagnostic(forceWarning),
operation.operator, lUserType, rUserType, context,
)
else -> error("Shouldn't be here")
}
private fun checkSenselessness(
lType: ConeKotlinType,
rType: ConeKotlinType,
context: CheckerContext,
@@ -139,3 +277,83 @@ object FirEqualityCompatibilityChecker : FirEqualityOperatorCallChecker() {
}
}
}
private class TypeInfo(
val type: ConeKotlinType,
val notNullType: ConeKotlinType,
val isFinalClass: Boolean,
val isEnumClass: Boolean,
val isPrimitive: Boolean,
val isBuiltin: Boolean,
val isValueClass: Boolean,
val isLiterallyTypeParameter: Boolean,
) {
override fun toString() = "$type"
}
private val FirClassSymbol<*>.isBuiltin get() = isPrimitiveType() || classId == StandardClassIds.String || isEnumClass
// This property is used to replicate K1 behavior, and it
// tries to predict empty intersections from the K1 point-of-view.
// Enum classes are final, but enum entries are their subclasses.
private val TypeInfo.enforcesEmptyIntersection get() = isFinalClass && !isEnumClass
private val TypeInfo.isNullableEnum get() = isEnumClass && type.isNullable
private val TypeInfo.isIdentityLess get() = isPrimitive || !type.isNullable && isValueClass
private val FirClassSymbol<*>.isFinalClass get() = isClass && isFinal
// NB: This is what RULES1 means then it says "class".
private val FirClassSymbol<*>.isClass get() = !isInterface
private fun ConeKotlinType.toTypeInfo(session: FirSession): TypeInfo {
val bounds = collectUpperBounds().map { type -> toKotlinType(type).replaceArgumentsWithStarProjections() }
val type = bounds.ifNotEmpty { ConeTypeIntersector.intersectTypes(session.typeContext, this) }
?: session.builtinTypes.nullableAnyType.type
val notNullType = type.withNullability(ConeNullability.NOT_NULL, session.typeContext)
return TypeInfo(
type, notNullType,
isFinalClass = bounds.any { it.toClassSymbol(session)?.isFinalClass == true },
isEnumClass = bounds.any { it.toClassSymbol(session)?.isEnumClass == true },
isPrimitive = bounds.any { it.isPrimitive },
isBuiltin = bounds.any { it.toClassSymbol(session)?.isBuiltin == true },
isValueClass = bounds.any { it.toClassSymbol(session)?.isInline == true },
isLiterallyTypeParameter = this.lowerBoundIfFlexible() is ConeTypeParameterType,
)
}
private fun toKotlinType(type: ConeClassLikeType): ConeClassLikeType {
// Type arguments are ignored by design
return ConeClassLikeTypeImpl(type.lookupTag, type.typeArguments, type.isNullable)
}
private class ArgumentInfo(
val argument: FirExpression,
val userType: ConeKotlinType,
val originalType: ConeKotlinType,
val session: FirSession,
) {
val smartCastType: ConeKotlinType by lazy {
if (argument !is FirSmartCastExpression) originalType else userType.fullyExpandedType(session)
}
val originalTypeInfo get() = originalType.toTypeInfo(session)
val smartCastTypeInfo get() = smartCastType.toTypeInfo(session)
override fun toString() = "${argument.source?.text} :: $userType"
}
@Suppress("RecursivePropertyAccessor")
private val FirExpression.mostOriginalTypeIfSmartCast: ConeKotlinType
get() = when (this) {
is FirSmartCastExpression -> originalExpression.mostOriginalTypeIfSmartCast
else -> typeRef.coneType
}
private fun FirExpression.toArgumentInfo(context: CheckerContext) =
ArgumentInfo(
this, typeRef.coneType, mostOriginalTypeIfSmartCast.fullyExpandedType(context.session), context.session,
)
@@ -221,7 +221,10 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FINAL_UPPER_BOUND
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FLOAT_LITERAL_OUT_OF_RANGE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_BINARY_MOD
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_PROPERTY_TYPE_IN_CONSTRUCTOR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_IDENTITY_EQUALS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FORBIDDEN_BINARY_MOD
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FORBIDDEN_IDENTITY_EQUALS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FORBIDDEN_IDENTITY_EQUALS_WARNING
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FORBIDDEN_VARARG_PARAMETER_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUNCTION_CALL_EXPECTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUNCTION_DECLARATION_WITH_NO_NAME
@@ -249,6 +252,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_SUSPEND_F
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_SUSPEND_PROPERTY_ACCESS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_UNDERSCORE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.IMPLEMENTATION_BY_DELEGATION_IN_EXPECT_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.IMPLICIT_BOXING_IN_IDENTITY_EQUALS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.IMPLICIT_NOTHING_PROPERTY_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.IMPLICIT_NOTHING_RETURN_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_CANDIDATE
@@ -262,6 +266,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_TARG
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_TARGET_PROPERTY_HAS_NO_BACKING_FIELD
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCOMPATIBLE_ENUM_COMPARISON
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCOMPATIBLE_ENUM_COMPARISON_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCOMPATIBLE_MODIFIERS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCOMPATIBLE_TYPES
@@ -2002,6 +2007,36 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
RENDER_TYPE,
RENDER_TYPE
)
map.put(
INCOMPATIBLE_ENUM_COMPARISON,
"Comparison of incompatible enums ''{0}'' and ''{1}'' is always unsuccessful",
RENDER_TYPE,
RENDER_TYPE
)
map.put(
FORBIDDEN_IDENTITY_EQUALS,
"Identity equality for arguments of types {0} and {1} is forbidden",
RENDER_TYPE,
RENDER_TYPE
)
map.put(
FORBIDDEN_IDENTITY_EQUALS_WARNING,
"Identity equality for arguments of types {0} and {1} is forbidden",
RENDER_TYPE,
RENDER_TYPE
)
map.put(
DEPRECATED_IDENTITY_EQUALS,
"Identity equality for arguments of types {0} and {1} is deprecated",
RENDER_TYPE,
RENDER_TYPE
)
map.put(
IMPLICIT_BOXING_IN_IDENTITY_EQUALS,
"Identity equality for arguments of types {0} and {1} can be unstable because of implicit boxing",
RENDER_TYPE,
RENDER_TYPE
)
map.put(INC_DEC_SHOULD_NOT_RETURN_UNIT, "Functions inc(), dec() shouldn't return Unit to be used by operators ++, --")
map.put(
ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT,
@@ -23,10 +23,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
@@ -607,6 +604,10 @@ fun ConeKotlinType.toRegularClassSymbol(session: FirSession): FirRegularClassSym
return (this as? ConeClassLikeType)?.toRegularClassSymbol(session)
}
fun ConeClassLikeType.toClassSymbol(session: FirSession): FirClassSymbol<*>? {
return fullyExpandedType(session).toSymbol(session) as? FirClassSymbol<*>
}
private fun lowerThanBound(context: ConeInferenceContext, argument: ConeKotlinType, typeParameterSymbol: FirTypeParameterSymbol): Boolean {
typeParameterSymbol.resolvedBounds.forEach { boundTypeRef ->
if (argument != boundTypeRef.coneType && argument.isSubtypeOf(context, boundTypeRef.coneType)) {
@@ -83,12 +83,18 @@ inline val FirClassSymbol<*>.isLocalClassOrAnonymousObject: Boolean
get() = classId.isLocal || this is FirAnonymousObjectSymbol
inline val FirClassSymbol<*>.isClass: Boolean
get() = classKind.isClass
inline val FirClassSymbol<*>.isInterface: Boolean
get() = classKind.isInterface
inline val FirClassSymbol<*>.isEnumClass: Boolean
get() = classKind.isEnumClass
inline val FirClassSymbol<*>.isEnumEntry: Boolean
get() = classKind.isEnumEntry
// ---------------------- specific callables ----------------------
inline val FirPropertyAccessorSymbol.allowsToHaveFakeOverride: Boolean get() = visibility.allowsToHaveFakeOverride
@@ -1,7 +1,7 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: JS_IR
// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6
// IGNORE_BACKEND_K1: NATIVE
const val minusOneVal = (-1).toByte()
const val oneVal = 1.toByte()
@@ -106,16 +106,16 @@ fun box(): String {
if (plus3 != 5) return "Fail 2.3"
if (plus4 != 4) return "Fail 2.4"
if (plus5 != 4) return "Fail 2.5"
if (plus6 != 4) return "Fail 2.6"
if (plus6 != 4L) return "Fail 2.6"
if (plus7 != 4.0f) return "Fail 2.7"
if (plus8 != 4.0f) return "Fail 2.8"
if (plus8 != 4.0) return "Fail 2.8"
if (minus1 != -1) return "Fail 3.1"
if (minus2 != 0) return "Fail 3.2"
if (minus3 != 1) return "Fail 3.3"
if (minus4 != 0) return "Fail 3.4"
if (minus5 != 0) return "Fail 3.5"
if (minus6 != 0) return "Fail 3.6"
if (minus6 != 0L) return "Fail 3.6"
if (minus7 != 0.0f) return "Fail 3.7"
if (minus8 != 0.0) return "Fail 3.8"
@@ -124,7 +124,7 @@ fun box(): String {
if (times3 != 6) return "Fail 4.3"
if (times4 != 4) return "Fail 4.4"
if (times5 != 4) return "Fail 4.5"
if (times6 != 4) return "Fail 4.6"
if (times6 != 4L) return "Fail 4.6"
if (times7 != 4.0f) return "Fail 4.7"
if (times8 != 4.0) return "Fail 4.8"
@@ -133,7 +133,7 @@ fun box(): String {
if (div3 != 1) return "Fail 5.3"
if (div4 != 1) return "Fail 5.4"
if (div5 != 1) return "Fail 5.5"
if (div6 != 1) return "Fail 5.6"
if (div6 != 1L) return "Fail 5.6"
if (div7 != 1.0f) return "Fail 5.7"
if (div8 != 1.0) return "Fail 5.8"
@@ -142,7 +142,7 @@ fun box(): String {
if (rem3 != 1) return "Fail 6.3"
if (rem4 != 0) return "Fail 6.4"
if (rem5 != 0) return "Fail 6.5"
if (rem6 != 0) return "Fail 6.6"
if (rem6 != 0L) return "Fail 6.6"
if (rem7 != 0.0f) return "Fail 6.7"
if (rem8 != 0.0) return "Fail 6.8"
@@ -151,11 +151,11 @@ fun box(): String {
if (unaryMinus1 != -1) return "Fail 7.3"
if (unaryMinus2 != 1) return "Fail 7.4"
if (convert1 != 1) return "Fail 8.1"
if (convert1 != 1.toByte()) return "Fail 8.1"
if (convert2 != '') return "Fail 8.2"
if (convert3 != 1) return "Fail 8.3"
if (convert3 != 1.toShort()) return "Fail 8.3"
if (convert4 != 1) return "Fail 8.4"
if (convert5 != 1) return "Fail 8.5"
if (convert5 != 1L) return "Fail 8.5"
if (convert6 != 1.0f) return "Fail 8.6"
if (convert7 != 1.0) return "Fail 8.7"
@@ -1,7 +1,7 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: JS_IR
// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6
// IGNORE_BACKEND_K1: NATIVE
const val minusOneVal = -1.0
const val oneVal = 1.0
@@ -101,59 +101,59 @@ fun box(): String {
if (compareTo7 != 0) return "Fail 1.7"
if (compareTo8 != 0) return "Fail 1.8"
if (plus1 != 3) return "Fail 2.1"
if (plus2 != 4) return "Fail 2.2"
if (plus3 != 5) return "Fail 2.3"
if (plus4 != 4) return "Fail 2.4"
if (plus5 != 4) return "Fail 2.5"
if (plus6 != 4) return "Fail 2.6"
if (plus7 != 4.0f) return "Fail 2.7"
if (plus1 != 3.0) return "Fail 2.1"
if (plus2 != 4.0) return "Fail 2.2"
if (plus3 != 5.0) return "Fail 2.3"
if (plus4 != 4.0) return "Fail 2.4"
if (plus5 != 4.0) return "Fail 2.5"
if (plus6 != 4.0) return "Fail 2.6"
if (plus7 != 4.0) return "Fail 2.7"
if (plus8 != 4.0) return "Fail 2.8"
if (minus1 != -1) return "Fail 3.1"
if (minus2 != 0) return "Fail 3.2"
if (minus3 != 1) return "Fail 3.3"
if (minus4 != 0) return "Fail 3.4"
if (minus5 != 0) return "Fail 3.5"
if (minus6 != 0) return "Fail 3.6"
if (minus7 != 0.0f) return "Fail 3.7"
if (minus1 != -1.0) return "Fail 3.1"
if (minus2 != 0.0) return "Fail 3.2"
if (minus3 != 1.0) return "Fail 3.3"
if (minus4 != 0.0) return "Fail 3.4"
if (minus5 != 0.0) return "Fail 3.5"
if (minus6 != 0.0) return "Fail 3.6"
if (minus7 != 0.0) return "Fail 3.7"
if (minus8 != 0.0) return "Fail 3.8"
if (times1 != 2) return "Fail 4.1"
if (times2 != 4) return "Fail 4.2"
if (times3 != 6) return "Fail 4.3"
if (times4 != 4) return "Fail 4.4"
if (times5 != 4) return "Fail 4.5"
if (times6 != 4) return "Fail 4.6"
if (times7 != 4.0f) return "Fail 4.7"
if (times1 != 2.0) return "Fail 4.1"
if (times2 != 4.0) return "Fail 4.2"
if (times3 != 6.0) return "Fail 4.3"
if (times4 != 4.0) return "Fail 4.4"
if (times5 != 4.0) return "Fail 4.5"
if (times6 != 4.0) return "Fail 4.6"
if (times7 != 4.0) return "Fail 4.7"
if (times8 != 4.0) return "Fail 4.8"
if (div1 != 0.5) return "Fail 5.1"
if (div2 != 1.0) return "Fail 5.2"
if (div3 != 1.5) return "Fail 5.3"
if (div4 != 1) return "Fail 5.4"
if (div5 != 1) return "Fail 5.5"
if (div6 != 1) return "Fail 5.6"
if (div7 != 1.0f) return "Fail 5.7"
if (div4 != 1.0) return "Fail 5.4"
if (div5 != 1.0) return "Fail 5.5"
if (div6 != 1.0) return "Fail 5.6"
if (div7 != 1.0) return "Fail 5.7"
if (div8 != 1.0) return "Fail 5.8"
if (rem1 != 1) return "Fail 6.1"
if (rem2 != 0) return "Fail 6.2"
if (rem3 != 1) return "Fail 6.3"
if (rem4 != 0) return "Fail 6.4"
if (rem5 != 0) return "Fail 6.5"
if (rem6 != 0) return "Fail 6.6"
if (rem7 != 0.0f) return "Fail 6.7"
if (rem1 != 1.0) return "Fail 6.1"
if (rem2 != 0.0) return "Fail 6.2"
if (rem3 != 1.0) return "Fail 6.3"
if (rem4 != 0.0) return "Fail 6.4"
if (rem5 != 0.0) return "Fail 6.5"
if (rem6 != 0.0) return "Fail 6.6"
if (rem7 != 0.0) return "Fail 6.7"
if (rem8 != 0.0) return "Fail 6.8"
if (unaryPlus1 != 1) return "Fail 7.1"
if (unaryPlus2 != -1) return "Fail 7.2"
if (unaryMinus1 != -1) return "Fail 7.3"
if (unaryMinus2 != 1) return "Fail 7.4"
if (unaryPlus1 != 1.0) return "Fail 7.1"
if (unaryPlus2 != -1.0) return "Fail 7.2"
if (unaryMinus1 != -1.0) return "Fail 7.3"
if (unaryMinus2 != 1.0) return "Fail 7.4"
if (convert1 != '') return "Fail 8.1"
if (convert2 != 1) return "Fail 8.2"
if (convert3 != 1) return "Fail 8.3"
if (convert3 != 1L) return "Fail 8.3"
if (convert4 != 1.0f) return "Fail 8.4"
if (convert5 != 1.0) return "Fail 8.5"
@@ -1,7 +1,7 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: JS_IR
// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6
// IGNORE_BACKEND_K1: NATIVE
const val minusOneVal = -1.0f
const val oneVal = 1.0f
@@ -101,59 +101,59 @@ fun box(): String {
if (compareTo7 != 0) return "Fail 1.7"
if (compareTo8 != 0) return "Fail 1.8"
if (plus1 != 3) return "Fail 2.1"
if (plus2 != 4) return "Fail 2.2"
if (plus3 != 5) return "Fail 2.3"
if (plus4 != 4) return "Fail 2.4"
if (plus5 != 4) return "Fail 2.5"
if (plus6 != 4) return "Fail 2.6"
if (plus1 != 3f) return "Fail 2.1"
if (plus2 != 4f) return "Fail 2.2"
if (plus3 != 5f) return "Fail 2.3"
if (plus4 != 4f) return "Fail 2.4"
if (plus5 != 4f) return "Fail 2.5"
if (plus6 != 4f) return "Fail 2.6"
if (plus7 != 4.0f) return "Fail 2.7"
if (plus8 != 4.0) return "Fail 2.8"
if (minus1 != -1) return "Fail 3.1"
if (minus2 != 0) return "Fail 3.2"
if (minus3 != 1) return "Fail 3.3"
if (minus4 != 0) return "Fail 3.4"
if (minus5 != 0) return "Fail 3.5"
if (minus6 != 0) return "Fail 3.6"
if (minus1 != -1f) return "Fail 3.1"
if (minus2 != 0f) return "Fail 3.2"
if (minus3 != 1f) return "Fail 3.3"
if (minus4 != 0f) return "Fail 3.4"
if (minus5 != 0f) return "Fail 3.5"
if (minus6 != 0f) return "Fail 3.6"
if (minus7 != 0.0f) return "Fail 3.7"
if (minus8 != 0.0) return "Fail 3.8"
if (times1 != 2) return "Fail 4.1"
if (times2 != 4) return "Fail 4.2"
if (times3 != 6) return "Fail 4.3"
if (times4 != 4) return "Fail 4.4"
if (times5 != 4) return "Fail 4.5"
if (times6 != 4) return "Fail 4.6"
if (times1 != 2f) return "Fail 4.1"
if (times2 != 4f) return "Fail 4.2"
if (times3 != 6f) return "Fail 4.3"
if (times4 != 4f) return "Fail 4.4"
if (times5 != 4f) return "Fail 4.5"
if (times6 != 4f) return "Fail 4.6"
if (times7 != 4.0f) return "Fail 4.7"
if (times8 != 4.0) return "Fail 4.8"
if (div1 != 0.5f) return "Fail 5.1"
if (div2 != 1.0f) return "Fail 5.2"
if (div3 != 1.5f) return "Fail 5.3"
if (div4 != 1) return "Fail 5.4"
if (div5 != 1) return "Fail 5.5"
if (div6 != 1) return "Fail 5.6"
if (div4 != 1f) return "Fail 5.4"
if (div5 != 1f) return "Fail 5.5"
if (div6 != 1f) return "Fail 5.6"
if (div7 != 1.0f) return "Fail 5.7"
if (div8 != 1.0) return "Fail 5.8"
if (rem1 != 1) return "Fail 6.1"
if (rem2 != 0) return "Fail 6.2"
if (rem3 != 1) return "Fail 6.3"
if (rem4 != 0) return "Fail 6.4"
if (rem5 != 0) return "Fail 6.5"
if (rem6 != 0) return "Fail 6.6"
if (rem1 != 1f) return "Fail 6.1"
if (rem2 != 0f) return "Fail 6.2"
if (rem3 != 1f) return "Fail 6.3"
if (rem4 != 0f) return "Fail 6.4"
if (rem5 != 0f) return "Fail 6.5"
if (rem6 != 0f) return "Fail 6.6"
if (rem7 != 0.0f) return "Fail 6.7"
if (rem8 != 0.0) return "Fail 6.8"
if (unaryPlus1 != 1) return "Fail 7.1"
if (unaryPlus2 != -1) return "Fail 7.2"
if (unaryMinus1 != -1) return "Fail 7.3"
if (unaryMinus2 != 1) return "Fail 7.4"
if (unaryPlus1 != 1f) return "Fail 7.1"
if (unaryPlus2 != -1f) return "Fail 7.2"
if (unaryMinus1 != -1f) return "Fail 7.3"
if (unaryMinus2 != 1f) return "Fail 7.4"
if (convert1 != '') return "Fail 8.1"
if (convert2 != 1) return "Fail 8.2"
if (convert3 != 1) return "Fail 8.3"
if (convert3 != 1L) return "Fail 8.3"
if (convert4 != 1.0f) return "Fail 8.4"
if (convert5 != 1.0) return "Fail 8.5"
@@ -1,7 +1,7 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: JS_IR
// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6
// IGNORE_BACKEND_K1: NATIVE
const val minusOneVal = -1
const val oneVal = 1
@@ -106,7 +106,7 @@ fun box(): String {
if (plus3 != 5) return "Fail 2.3"
if (plus4 != 4) return "Fail 2.4"
if (plus5 != 4) return "Fail 2.5"
if (plus6 != 4) return "Fail 2.6"
if (plus6 != 4L) return "Fail 2.6"
if (plus7 != 4.0f) return "Fail 2.7"
if (plus8 != 4.0) return "Fail 2.8"
@@ -115,7 +115,7 @@ fun box(): String {
if (minus3 != 1) return "Fail 3.3"
if (minus4 != 0) return "Fail 3.4"
if (minus5 != 0) return "Fail 3.5"
if (minus6 != 0) return "Fail 3.6"
if (minus6 != 0L) return "Fail 3.6"
if (minus7 != 0.0f) return "Fail 3.7"
if (minus8 != 0.0) return "Fail 3.8"
@@ -124,7 +124,7 @@ fun box(): String {
if (times3 != 6) return "Fail 4.3"
if (times4 != 4) return "Fail 4.4"
if (times5 != 4) return "Fail 4.5"
if (times6 != 4) return "Fail 4.6"
if (times6 != 4L) return "Fail 4.6"
if (times7 != 4.0f) return "Fail 4.7"
if (times8 != 4.0) return "Fail 4.8"
@@ -133,7 +133,7 @@ fun box(): String {
if (div3 != 1) return "Fail 5.3"
if (div4 != 1) return "Fail 5.4"
if (div5 != 1) return "Fail 5.5"
if (div6 != 1) return "Fail 5.6"
if (div6 != 1L) return "Fail 5.6"
if (div7 != 1.0f) return "Fail 5.7"
if (div8 != 1.0) return "Fail 5.8"
@@ -142,7 +142,7 @@ fun box(): String {
if (rem3 != 1) return "Fail 6.3"
if (rem4 != 0) return "Fail 6.4"
if (rem5 != 0) return "Fail 6.5"
if (rem6 != 0) return "Fail 6.6"
if (rem6 != 0L) return "Fail 6.6"
if (rem7 != 0.0f) return "Fail 6.7"
if (rem8 != 0.0) return "Fail 6.8"
@@ -151,11 +151,11 @@ fun box(): String {
if (unaryMinus1 != -1) return "Fail 7.3"
if (unaryMinus2 != 1) return "Fail 7.4"
if (convert1 != 1) return "Fail 8.1"
if (convert1 != 1.toByte()) return "Fail 8.1"
if (convert2 != '') return "Fail 8.2"
if (convert3 != 1) return "Fail 8.3"
if (convert3 != 1.toShort()) return "Fail 8.3"
if (convert4 != 1) return "Fail 8.4"
if (convert5 != 1) return "Fail 8.5"
if (convert5 != 1L) return "Fail 8.5"
if (convert6 != 1.0f) return "Fail 8.6"
if (convert7 != 1.0) return "Fail 8.7"
@@ -1,7 +1,7 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: JS_IR
// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6
// IGNORE_BACKEND_K1: NATIVE
const val minusOneVal = -1L
const val oneVal = 1L
@@ -101,61 +101,61 @@ fun box(): String {
if (compareTo7 != 0) return "Fail 1.7"
if (compareTo8 != 0) return "Fail 1.8"
if (plus1 != 3) return "Fail 2.1"
if (plus2 != 4) return "Fail 2.2"
if (plus3 != 5) return "Fail 2.3"
if (plus4 != 4) return "Fail 2.4"
if (plus5 != 4) return "Fail 2.5"
if (plus6 != 4) return "Fail 2.6"
if (plus1 != 3L) return "Fail 2.1"
if (plus2 != 4L) return "Fail 2.2"
if (plus3 != 5L) return "Fail 2.3"
if (plus4 != 4L) return "Fail 2.4"
if (plus5 != 4L) return "Fail 2.5"
if (plus6 != 4L) return "Fail 2.6"
if (plus7 != 4.0f) return "Fail 2.7"
if (plus8 != 4.0) return "Fail 2.8"
if (minus1 != -1) return "Fail 3.1"
if (minus2 != 0) return "Fail 3.2"
if (minus3 != 1) return "Fail 3.3"
if (minus4 != 0) return "Fail 3.4"
if (minus5 != 0) return "Fail 3.5"
if (minus6 != 0) return "Fail 3.6"
if (minus1 != -1L) return "Fail 3.1"
if (minus2 != 0L) return "Fail 3.2"
if (minus3 != 1L) return "Fail 3.3"
if (minus4 != 0L) return "Fail 3.4"
if (minus5 != 0L) return "Fail 3.5"
if (minus6 != 0L) return "Fail 3.6"
if (minus7 != 0.0f) return "Fail 3.7"
if (minus8 != 0.0) return "Fail 3.8"
if (times1 != 2) return "Fail 4.1"
if (times2 != 4) return "Fail 4.2"
if (times3 != 6) return "Fail 4.3"
if (times4 != 4) return "Fail 4.4"
if (times5 != 4) return "Fail 4.5"
if (times6 != 4) return "Fail 4.6"
if (times1 != 2L) return "Fail 4.1"
if (times2 != 4L) return "Fail 4.2"
if (times3 != 6L) return "Fail 4.3"
if (times4 != 4L) return "Fail 4.4"
if (times5 != 4L) return "Fail 4.5"
if (times6 != 4L) return "Fail 4.6"
if (times7 != 4.0f) return "Fail 4.7"
if (times8 != 4.0) return "Fail 4.8"
if (div1 != 0) return "Fail 5.1"
if (div2 != 1) return "Fail 5.2"
if (div3 != 1) return "Fail 5.3"
if (div4 != 1) return "Fail 5.4"
if (div5 != 1) return "Fail 5.5"
if (div6 != 1) return "Fail 5.6"
if (div1 != 0L) return "Fail 5.1"
if (div2 != 1L) return "Fail 5.2"
if (div3 != 1L) return "Fail 5.3"
if (div4 != 1L) return "Fail 5.4"
if (div5 != 1L) return "Fail 5.5"
if (div6 != 1L) return "Fail 5.6"
if (div7 != 1.0f) return "Fail 5.7"
if (div8 != 1.0) return "Fail 5.8"
if (rem1 != 1) return "Fail 6.1"
if (rem2 != 0) return "Fail 6.2"
if (rem3 != 1) return "Fail 6.3"
if (rem4 != 0) return "Fail 6.4"
if (rem5 != 0) return "Fail 6.5"
if (rem6 != 0) return "Fail 6.6"
if (rem1 != 1L) return "Fail 6.1"
if (rem2 != 0L) return "Fail 6.2"
if (rem3 != 1L) return "Fail 6.3"
if (rem4 != 0L) return "Fail 6.4"
if (rem5 != 0L) return "Fail 6.5"
if (rem6 != 0L) return "Fail 6.6"
if (rem7 != 0.0f) return "Fail 6.7"
if (rem8 != 0.0) return "Fail 6.8"
if (unaryPlus1 != 1) return "Fail 7.1"
if (unaryPlus2 != -1) return "Fail 7.2"
if (unaryMinus1 != -1) return "Fail 7.3"
if (unaryMinus2 != 1) return "Fail 7.4"
if (unaryPlus1 != 1L) return "Fail 7.1"
if (unaryPlus2 != -1L) return "Fail 7.2"
if (unaryMinus1 != -1L) return "Fail 7.3"
if (unaryMinus2 != 1L) return "Fail 7.4"
if (convert1 != 1) return "Fail 8.1"
if (convert1 != 1.toByte()) return "Fail 8.1"
if (convert2 != '') return "Fail 8.2"
if (convert3 != 1) return "Fail 8.3"
if (convert3 != 1.toShort()) return "Fail 8.3"
if (convert4 != 1) return "Fail 8.4"
if (convert5 != 1) return "Fail 8.5"
if (convert5 != 1L) return "Fail 8.5"
if (convert6 != 1.0f) return "Fail 8.6"
if (convert7 != 1.0) return "Fail 8.7"
@@ -1,7 +1,7 @@
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: JS_IR
// IGNORE_BACKEND_K1: JVM_IR, NATIVE, JS_IR, JS_IR_ES6
// IGNORE_BACKEND_K1: NATIVE
const val minusOneVal = (-1).toShort()
const val oneVal = 1.toShort()
@@ -106,7 +106,7 @@ fun box(): String {
if (plus3 != 5) return "Fail 2.3"
if (plus4 != 4) return "Fail 2.4"
if (plus5 != 4) return "Fail 2.5"
if (plus6 != 4) return "Fail 2.6"
if (plus6 != 4L) return "Fail 2.6"
if (plus7 != 4.0f) return "Fail 2.7"
if (plus8 != 4.0) return "Fail 2.8"
@@ -115,7 +115,7 @@ fun box(): String {
if (minus3 != 1) return "Fail 3.3"
if (minus4 != 0) return "Fail 3.4"
if (minus5 != 0) return "Fail 3.5"
if (minus6 != 0) return "Fail 3.6"
if (minus6 != 0L) return "Fail 3.6"
if (minus7 != 0.0f) return "Fail 3.7"
if (minus8 != 0.0) return "Fail 3.8"
@@ -124,7 +124,7 @@ fun box(): String {
if (times3 != 6) return "Fail 4.3"
if (times4 != 4) return "Fail 4.4"
if (times5 != 4) return "Fail 4.5"
if (times6 != 4) return "Fail 4.6"
if (times6 != 4L) return "Fail 4.6"
if (times7 != 4.0f) return "Fail 4.7"
if (times8 != 4.0) return "Fail 4.8"
@@ -133,7 +133,7 @@ fun box(): String {
if (div3 != 1) return "Fail 5.3"
if (div4 != 1) return "Fail 5.4"
if (div5 != 1) return "Fail 5.5"
if (div6 != 1) return "Fail 5.6"
if (div6 != 1L) return "Fail 5.6"
if (div7 != 1.0f) return "Fail 5.7"
if (div8 != 1.0) return "Fail 5.8"
@@ -142,7 +142,7 @@ fun box(): String {
if (rem3 != 1) return "Fail 6.3"
if (rem4 != 0) return "Fail 6.4"
if (rem5 != 0) return "Fail 6.5"
if (rem6 != 0) return "Fail 6.6"
if (rem6 != 0L) return "Fail 6.6"
if (rem7 != 0.0f) return "Fail 6.7"
if (rem8 != 0.0) return "Fail 6.8"
@@ -151,11 +151,11 @@ fun box(): String {
if (unaryMinus1 != -1) return "Fail 7.3"
if (unaryMinus2 != 1) return "Fail 7.4"
if (convert1 != 1) return "Fail 8.1"
if (convert1 != 1.toByte()) return "Fail 8.1"
if (convert2 != '') return "Fail 8.2"
if (convert3 != 1) return "Fail 8.3"
if (convert3 != 1.toShort()) return "Fail 8.3"
if (convert4 != 1) return "Fail 8.4"
if (convert5 != 1) return "Fail 8.5"
if (convert5 != 1L) return "Fail 8.5"
if (convert6 != 1.0f) return "Fail 8.6"
if (convert7 != 1.0) return "Fail 8.7"
@@ -10,16 +10,16 @@ fun f(): Unit {
x <!UNSAFE_OPERATOR_CALL!><<!> 1
<!ASSIGNMENT_TYPE_MISMATCH!>x += 1<!>
x == 1
x != 1
<!EQUALITY_NOT_APPLICABLE_WARNING!>x == 1<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>x != 1<!>
<!EQUALITY_NOT_APPLICABLE!>A() == 1<!>
x === "1"
x !== "1"
<!EQUALITY_NOT_APPLICABLE!>x === "1"<!>
<!EQUALITY_NOT_APPLICABLE!>x !== "1"<!>
x === 1
x !== 1
<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>x === 1<!>
<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>x !== 1<!>
x..2
x in 1..2
@@ -22,60 +22,60 @@ val a: Any = 0
val na: Any? = 0
// Identity for primitive values of same type
val test_zz = z === z || z !== z
val test_bb = b === b || b !== b
val test_ss = s === s || s !== s
val test_ii = i === i || i !== i
val test_jj = j === j || j !== j
val test_ff = f === f || f !== f
val test_dd = d === d || d !== d
val test_cc = c === c || c !== c
val test_zz = <!DEPRECATED_IDENTITY_EQUALS!>z === z<!> || <!DEPRECATED_IDENTITY_EQUALS!>z !== z<!>
val test_bb = <!DEPRECATED_IDENTITY_EQUALS!>b === b<!> || <!DEPRECATED_IDENTITY_EQUALS!>b !== b<!>
val test_ss = <!DEPRECATED_IDENTITY_EQUALS!>s === s<!> || <!DEPRECATED_IDENTITY_EQUALS!>s !== s<!>
val test_ii = <!DEPRECATED_IDENTITY_EQUALS!>i === i<!> || <!DEPRECATED_IDENTITY_EQUALS!>i !== i<!>
val test_jj = <!DEPRECATED_IDENTITY_EQUALS!>j === j<!> || <!DEPRECATED_IDENTITY_EQUALS!>j !== j<!>
val test_ff = <!DEPRECATED_IDENTITY_EQUALS!>f === f<!> || <!DEPRECATED_IDENTITY_EQUALS!>f !== f<!>
val test_dd = <!DEPRECATED_IDENTITY_EQUALS!>d === d<!> || <!DEPRECATED_IDENTITY_EQUALS!>d !== d<!>
val test_cc = <!DEPRECATED_IDENTITY_EQUALS!>c === c<!> || <!DEPRECATED_IDENTITY_EQUALS!>c !== c<!>
// Identity for primitive values of different types (no extra error)
val test_zb = <!EQUALITY_NOT_APPLICABLE_WARNING!>z === b<!> || <!EQUALITY_NOT_APPLICABLE_WARNING!>z !== b<!>
val test_zb = <!FORBIDDEN_IDENTITY_EQUALS!>z === b<!> || <!FORBIDDEN_IDENTITY_EQUALS!>z !== b<!>
// Primitive vs nullable
val test_znz = z === nz || nz === z || z !== nz || nz !== z
val test_bnb = b === nb || nb === b || b !== nb || nb !== b
val test_sns = s === ns || ns === s || s !== ns || ns !== s
val test_ini = i === ni || ni === i || i !== ni || ni !== i
val test_jnj = j === nj || nj === j || j !== nj || nj !== j
val test_fnf = f === nf || nf === f || f !== nf || nf !== f
val test_dnd = d === nd || nd === d || d !== nd || nd !== d
val test_cnc = c === nc || nc === c || c !== nc || nc !== c
val test_znz = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>z === nz<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nz === z<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>z !== nz<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nz !== z<!>
val test_bnb = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>b === nb<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nb === b<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>b !== nb<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nb !== b<!>
val test_sns = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>s === ns<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>ns === s<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>s !== ns<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>ns !== s<!>
val test_ini = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>i === ni<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>ni === i<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>i !== ni<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>ni !== i<!>
val test_jnj = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>j === nj<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nj === j<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>j !== nj<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nj !== j<!>
val test_fnf = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>f === nf<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nf === f<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>f !== nf<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nf !== f<!>
val test_dnd = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>d === nd<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nd === d<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>d !== nd<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nd !== d<!>
val test_cnc = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>c === nc<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nc === c<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>c !== nc<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nc !== c<!>
// Primitive number vs Number
val test_bn = b === n || n === b || b !== n || n !== b
val test_sn = s === n || n === s || s !== n || n !== s
val test_in = i === n || n === i || i !== n || n !== i
val test_jn = j === n || n === j || j !== n || n !== j
val test_fn = f === n || n === f || f !== n || n !== f
val test_dn = d === n || n === d || d !== n || n !== d
val test_bn = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>b === n<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>n === b<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>b !== n<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>n !== b<!>
val test_sn = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>s === n<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>n === s<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>s !== n<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>n !== s<!>
val test_in = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>i === n<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>n === i<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>i !== n<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>n !== i<!>
val test_jn = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>j === n<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>n === j<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>j !== n<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>n !== j<!>
val test_fn = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>f === n<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>n === f<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>f !== n<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>n !== f<!>
val test_dn = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>d === n<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>n === d<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>d !== n<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>n !== d<!>
// Primitive number vs Number?
val test_bnn = b === nn || nn === b || b !== nn || nn !== b
val test_snn = s === nn || nn === s || s !== nn || nn !== s
val test_inn = i === nn || nn === i || i !== nn || nn !== i
val test_jnn = j === nn || nn === j || j !== nn || nn !== j
val test_fnn = f === nn || nn === f || f !== nn || nn !== f
val test_dnn = d === nn || nn === d || d !== nn || nn !== d
val test_bnn = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>b === nn<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nn === b<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>b !== nn<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nn !== b<!>
val test_snn = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>s === nn<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nn === s<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>s !== nn<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nn !== s<!>
val test_inn = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>i === nn<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nn === i<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>i !== nn<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nn !== i<!>
val test_jnn = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>j === nn<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nn === j<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>j !== nn<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nn !== j<!>
val test_fnn = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>f === nn<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nn === f<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>f !== nn<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nn !== f<!>
val test_dnn = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>d === nn<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nn === d<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>d !== nn<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>nn !== d<!>
// Primitive vs Any
val test_za = z === a || a === z || z !== a || a !== z
val test_ba = b === a || a === b || b !== a || a !== b
val test_sa = s === a || a === s || s !== a || a !== s
val test_ia = i === a || a === i || i !== a || a !== i
val test_ja = j === a || a === j || j !== a || a !== j
val test_fa = f === a || a === f || f !== a || a !== f
val test_da = d === a || a === d || d !== a || a !== d
val test_ca = c === a || a === c || c !== a || a !== c
val test_za = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>z === a<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a === z<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>z !== a<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a !== z<!>
val test_ba = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>b === a<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a === b<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>b !== a<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a !== b<!>
val test_sa = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>s === a<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a === s<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>s !== a<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a !== s<!>
val test_ia = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>i === a<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a === i<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>i !== a<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a !== i<!>
val test_ja = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>j === a<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a === j<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>j !== a<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a !== j<!>
val test_fa = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>f === a<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a === f<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>f !== a<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a !== f<!>
val test_da = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>d === a<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a === d<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>d !== a<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a !== d<!>
val test_ca = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>c === a<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a === c<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>c !== a<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a !== c<!>
// Primitive vs Any?
val test_zna = z === na || na === z || z !== na || na !== z
val test_bna = b === na || na === b || b !== na || na !== b
val test_sna = s === na || na === s || s !== na || na !== s
val test_ina = i === na || na === i || i !== na || na !== i
val test_jna = j === na || na === j || j !== na || na !== j
val test_fna = f === na || na === f || f !== na || na !== f
val test_dna = d === na || na === d || d !== na || na !== d
val test_cna = c === na || na === c || c !== na || na !== c
val test_zna = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>z === na<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>na === z<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>z !== na<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>na !== z<!>
val test_bna = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>b === na<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>na === b<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>b !== na<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>na !== b<!>
val test_sna = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>s === na<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>na === s<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>s !== na<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>na !== s<!>
val test_ina = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>i === na<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>na === i<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>i !== na<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>na !== i<!>
val test_jna = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>j === na<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>na === j<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>j !== na<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>na !== j<!>
val test_fna = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>f === na<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>na === f<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>f !== na<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>na !== f<!>
val test_dna = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>d === na<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>na === d<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>d !== na<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>na !== d<!>
val test_cna = <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>c === na<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>na === c<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>c !== na<!> || <!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>na !== c<!>
@@ -5,5 +5,5 @@ class Bar3 : Foo<Bar3>
fun test(b1: Bar1, b2: Bar2, b3: Bar3) {
b1 == b2
<!EQUALITY_NOT_APPLICABLE_WARNING!>b1 == b3<!>
b1 == b3
}
@@ -0,0 +1,9 @@
// ISSUE: KT-29316
// ISSUE: KT-24284
class A
class B
fun main() {
A() == B()
A() === B()
}
@@ -0,0 +1,9 @@
// ISSUE: KT-29316
// ISSUE: KT-24284
class A
class B
fun main() {
<!EQUALITY_NOT_APPLICABLE!>A() == B()<!>
<!EQUALITY_NOT_APPLICABLE!>A() === B()<!>
}
@@ -0,0 +1,23 @@
// FIR_IDENTICAL
// ISSUE: KT-13451
// FILE: J.java
public class J {
}
// FILE: Main.kt
class K {
fun f() {}
}
fun test (j: J, k: K) {
j == K::f
j == k::f
when (j) {
k::f -> ""
K::f -> ""
}
}
@@ -0,0 +1,7 @@
// FIR_IDENTICAL
// ISSUE: KT-47884
interface A<X>
class B<T>
fun foo(a: A<*>, b: B<*>): Boolean = a == b
@@ -0,0 +1,7 @@
// ISSUE: KT-22499
fun test(x: Any, y: Any) =
x is Float && y is Double && <!EQUALITY_NOT_APPLICABLE_WARNING!>x == y<!>
fun test(x: Float, y: Double) =
<!EQUALITY_NOT_APPLICABLE!>x == y<!>
@@ -0,0 +1,7 @@
// ISSUE: KT-22499
fun test(x: Any, y: Any) =
x is Float && y is Double && x == y
fun test(x: Float, y: Double) =
<!EQUALITY_NOT_APPLICABLE!>x == y<!>
@@ -1,17 +0,0 @@
// !LANGUAGE: -ProhibitComparisonOfIncompatibleEnums
// FILE: JavaEnumA.java
public enum JavaEnumA {}
// FILE: JavaEnumB.java
public enum JavaEnumB {}
// FILE: test.kt
enum class KotlinEnumA
enum class KotlinEnumB
fun jj(a: JavaEnumA, b: JavaEnumB) = <!EQUALITY_NOT_APPLICABLE_WARNING!>a == b<!>
fun jk(a: JavaEnumA, b: KotlinEnumB) = <!EQUALITY_NOT_APPLICABLE_WARNING!>a == b<!>
fun kk(a: KotlinEnumA, b: KotlinEnumB) = <!EQUALITY_NOT_APPLICABLE_WARNING!>a == b<!>
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: -ProhibitComparisonOfIncompatibleEnums
// FILE: JavaEnumA.java
@@ -0,0 +1,63 @@
interface Buffered {
fun flush()
}
interface AIPowered {
fun getAvatarReleaseYear(): Int
}
enum class BufferedEnum : Buffered {
A, B;
override fun flush() {}
}
enum class UsualEnum {
C, D;
}
enum class CleverEnum : Buffered, AIPowered {
E, F;
override fun flush() {}
override fun getAvatarReleaseYear() = 2022
}
fun <P> processInfo1(info: String, printer: P) where P: Buffered, P: AIPowered {
<!EQUALITY_NOT_APPLICABLE!>printer == 20<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>printer == BufferedEnum.A<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>printer == UsualEnum.C<!>
printer == CleverEnum.E
}
fun <P> processInfo2(info: String, printer: P) where P: AIPowered, P: Buffered {
<!EQUALITY_NOT_APPLICABLE!>printer == 20<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>printer == BufferedEnum.A<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>printer == UsualEnum.C<!>
printer == CleverEnum.E
}
abstract class Printer {
abstract fun print(command: String)
}
fun <P> processInfo3(info: String, printer: P) where P: Buffered, P: Printer {
<!EQUALITY_NOT_APPLICABLE!>printer == 20<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>printer == BufferedEnum.A<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>printer == UsualEnum.C<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>printer == CleverEnum.E<!>
}
fun test(a: Int, b: Any?) {
<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a === b<!>
}
fun <<!CONFLICTING_UPPER_BOUNDS, INCONSISTENT_TYPE_PARAMETER_BOUNDS, MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>T: <!FINAL_UPPER_BOUND!>Int<!><!>> rest(a: T, b: Any?) where T : <!FINAL_UPPER_BOUND, ONLY_ONE_CLASS_BOUND_ALLOWED!>String<!> {
<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a === b<!>
}
fun <<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>T: Any?<!>> nest(a: Int, b: T) where T : <!FINAL_UPPER_BOUND, ONLY_ONE_CLASS_BOUND_ALLOWED!>String<!> {
<!FORBIDDEN_IDENTITY_EQUALS!>a === b<!>
}
fun <<!CONFLICTING_UPPER_BOUNDS, INCONSISTENT_TYPE_PARAMETER_BOUNDS, MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>T: <!FINAL_UPPER_BOUND!>Int<!><!>, <!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>K: Any?<!>> mest(a: T, b: K) where T : <!FINAL_UPPER_BOUND, ONLY_ONE_CLASS_BOUND_ALLOWED!>String<!>, K: <!FINAL_UPPER_BOUND, ONLY_ONE_CLASS_BOUND_ALLOWED!>Boolean<!> {
<!FORBIDDEN_IDENTITY_EQUALS_WARNING!>a === b<!>
}
@@ -0,0 +1,63 @@
interface Buffered {
fun flush()
}
interface AIPowered {
fun getAvatarReleaseYear(): Int
}
enum class BufferedEnum : Buffered {
A, B;
override fun flush() {}
}
enum class UsualEnum {
C, D;
}
enum class CleverEnum : Buffered, AIPowered {
E, F;
override fun flush() {}
override fun getAvatarReleaseYear() = 2022
}
fun <P> processInfo1(info: String, printer: P) where P: Buffered, P: AIPowered {
<!EQUALITY_NOT_APPLICABLE!>printer == 20<!>
printer == BufferedEnum.A
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>printer == UsualEnum.C<!>
printer == CleverEnum.E
}
fun <P> processInfo2(info: String, printer: P) where P: AIPowered, P: Buffered {
<!EQUALITY_NOT_APPLICABLE!>printer == 20<!>
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>printer == BufferedEnum.A<!>
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>printer == UsualEnum.C<!>
printer == CleverEnum.E
}
abstract class Printer {
abstract fun print(command: String)
}
fun <P> processInfo3(info: String, printer: P) where P: Buffered, P: Printer {
<!EQUALITY_NOT_APPLICABLE!>printer == 20<!>
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>printer == BufferedEnum.A<!>
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>printer == UsualEnum.C<!>
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>printer == CleverEnum.E<!>
}
fun test(a: Int, b: Any?) {
<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a === b<!>
}
fun <<!INCONSISTENT_TYPE_PARAMETER_BOUNDS, MISPLACED_TYPE_PARAMETER_CONSTRAINTS!><!CONFLICTING_UPPER_BOUNDS!>T<!>: <!FINAL_UPPER_BOUND!>Int<!><!>> rest(a: T, b: Any?) where T : <!FINAL_UPPER_BOUND, ONLY_ONE_CLASS_BOUND_ALLOWED!>String<!> {
a === b
}
fun <<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>T: Any?<!>> nest(a: Int, b: T) where T : <!FINAL_UPPER_BOUND, ONLY_ONE_CLASS_BOUND_ALLOWED!>String<!> {
<!EQUALITY_NOT_APPLICABLE!>a === b<!>
}
fun <<!INCONSISTENT_TYPE_PARAMETER_BOUNDS, MISPLACED_TYPE_PARAMETER_CONSTRAINTS!><!CONFLICTING_UPPER_BOUNDS!>T<!>: <!FINAL_UPPER_BOUND!>Int<!><!>, <!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>K: Any?<!>> mest(a: T, b: K) where T : <!FINAL_UPPER_BOUND, ONLY_ONE_CLASS_BOUND_ALLOWED!>String<!>, K: <!FINAL_UPPER_BOUND, ONLY_ONE_CLASS_BOUND_ALLOWED!>Boolean<!> {
a === b
}
@@ -0,0 +1,13 @@
// FILE: A.java
class MyHelpers {
public static <T> T id(T it) {
return it;
}
}
// FILE: B.kt
fun <<!CONFLICTING_UPPER_BOUNDS, INCONSISTENT_TYPE_PARAMETER_BOUNDS, MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>T: <!FINAL_UPPER_BOUND!>Int<!><!>, <!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>K: Any?<!>> mest(a: T, b: K) where T : <!FINAL_UPPER_BOUND, ONLY_ONE_CLASS_BOUND_ALLOWED!>String<!>, K: <!FINAL_UPPER_BOUND, ONLY_ONE_CLASS_BOUND_ALLOWED!>Boolean<!> {
<!FORBIDDEN_IDENTITY_EQUALS_WARNING!>MyHelpers.id(a) === MyHelpers.id(b)<!>
}
@@ -0,0 +1,13 @@
// FILE: A.java
class MyHelpers {
public static <T> T id(T it) {
return it;
}
}
// FILE: B.kt
fun <<!INCONSISTENT_TYPE_PARAMETER_BOUNDS, MISPLACED_TYPE_PARAMETER_CONSTRAINTS!><!CONFLICTING_UPPER_BOUNDS!>T<!>: <!FINAL_UPPER_BOUND!>Int<!><!>, <!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>K: Any?<!>> mest(a: T, b: K) where T : <!FINAL_UPPER_BOUND, ONLY_ONE_CLASS_BOUND_ALLOWED!>String<!>, K: <!FINAL_UPPER_BOUND, ONLY_ONE_CLASS_BOUND_ALLOWED!>Boolean<!> {
MyHelpers.id(a) === MyHelpers.id(b)
}
@@ -1,92 +0,0 @@
// !LANGUAGE: -ProhibitComparisonOfIncompatibleEnums
interface I {
fun foo()
}
enum class E1 : I {
A {
override fun foo() {
<!EQUALITY_NOT_APPLICABLE_WARNING!>this == E2.A<!>
val q = this
when (q) {
this -> {}
E1.A -> {}
E1.B -> {}
<!INCOMPATIBLE_TYPES_WARNING!>E2.A<!> -> {}
<!INCOMPATIBLE_TYPES_WARNING!>E2.B<!> -> {}
else -> {}
}
}
},
B {
override fun foo() {
}
}
}
enum class E2 : I {
A {
override fun foo() {
}
},
B {
override fun foo() {
}
}
}
fun foo1(e1: E1, e2: E2) {
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == e2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 != e2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == E2.A<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>E1.B == e2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>E1.A == E2.B<!>
e1 == E1.A
E1.A == e1
e2 == E2.B
E2.B == e2
}
fun foo2(e1: E1, e2: E2) {
when (e1) {
E1.A -> {}
<!INCOMPATIBLE_TYPES_WARNING!>E2.A<!> -> {}
<!INCOMPATIBLE_TYPES_WARNING!>E2.B<!> -> {}
e1 -> {}
<!INCOMPATIBLE_TYPES_WARNING!>e2<!> -> {}
else -> {}
}
}
fun foo3(e1: Enum<E1>, e2: Enum<E2>, e: Enum<*>) {
e1 == e
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == e2<!>
e1 == E1.A
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == E2.A<!>
when (e1) {
e1 -> {}
<!INCOMPATIBLE_TYPES_WARNING!>e2<!> -> {}
e -> {}
E1.A -> {}
<!INCOMPATIBLE_TYPES_WARNING!>E2.A<!> -> {}
else -> {}
}
when (e) {
e -> {}
e2 -> {}
E1.A -> {}
E2.A -> {}
else -> {}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: -ProhibitComparisonOfIncompatibleEnums
interface I {
@@ -9,13 +9,13 @@ enum class E2 {
}
fun foo1(e1: E1, e2: E2) {
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == e2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 != e2<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>e1 == e2<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>e1 != e2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == E2.A<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>E1.B == e2<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>e1 == E2.A<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>E1.B == e2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>E1.A == E2.B<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>E1.A == E2.B<!>
e1 == E1.A
E1.A == e1
@@ -26,27 +26,27 @@ fun foo1(e1: E1, e2: E2) {
fun foo2(e1: E1, e2: E2) {
when (e1) {
E1.A -> {}
<!INCOMPATIBLE_TYPES_WARNING!>E2.A<!> -> {}
<!INCOMPATIBLE_TYPES_WARNING!>E2.B<!> -> {}
<!INCOMPATIBLE_ENUM_COMPARISON!>E2.A<!> -> {}
<!INCOMPATIBLE_ENUM_COMPARISON!>E2.B<!> -> {}
e1 -> {}
<!INCOMPATIBLE_TYPES_WARNING!>e2<!> -> {}
<!INCOMPATIBLE_ENUM_COMPARISON!>e2<!> -> {}
else -> {}
}
}
fun foo3(e1: Enum<E1>, e2: Enum<E2>, e: Enum<*>) {
e1 == e
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == e2<!>
e1 == e2
e1 == E1.A
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == E2.A<!>
e1 == E2.A
when (e1) {
e1 -> {}
<!INCOMPATIBLE_TYPES_WARNING!>e2<!> -> {}
e2 -> {}
e -> {}
E1.A -> {}
<!INCOMPATIBLE_TYPES_WARNING!>E2.A<!> -> {}
E2.A -> {}
else -> {}
}
@@ -63,15 +63,15 @@ interface MyInterface
open class MyOpenClass
fun foo4(e1: E1, i: MyInterface, c: MyOpenClass) {
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == i<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>i == e1<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>e1 == i<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>i == e1<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == c<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>c == e1<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>e1 == c<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>c == e1<!>
when (e1) {
<!INCOMPATIBLE_TYPES_WARNING!>i<!> -> {}
<!INCOMPATIBLE_TYPES_WARNING!>c<!> -> {}
<!INCOMPATIBLE_ENUM_COMPARISON!>i<!> -> {}
<!INCOMPATIBLE_ENUM_COMPARISON!>c<!> -> {}
else -> {}
}
}
@@ -90,10 +90,10 @@ fun foo6(e1: E1?, e2: E2) {
e1 == null
null == e1
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == E2.A<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>E2.A == e1<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == e2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>e2 == e1<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>e1 == E2.A<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>E2.A == e1<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>e1 == e2<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>e2 == e1<!>
<!SENSELESS_COMPARISON!>e2 == null<!>
<!SENSELESS_COMPARISON!>null == e2<!>
@@ -102,7 +102,7 @@ fun foo6(e1: E1?, e2: E2) {
}
fun foo7(e1: E1?, e2: E2?) {
e1 == e2 // There should be an IDE-inspection for such cases
<!INCOMPATIBLE_ENUM_COMPARISON!>e1 == e2<!> // There should be an IDE-inspection for such cases
}
fun <T> foo8(e1: E1?, e2: E2, t: T) {
@@ -117,16 +117,16 @@ fun <T> foo8(e1: E1?, e2: E2, t: T) {
}
fun <T, K> foo9(e1: E1?, e2: E2, t: T, k: K) where T : MyInterface, T : MyOpenClass, K : MyInterface {
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == t<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>t == e1<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>e1 == t<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>t == e1<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>e2 == t<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>t == e2<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>e2 == t<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>t == e2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>E1.A == t<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>t == E1.A<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>E1.A == t<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>t == E1.A<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>E3.X == t<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>E3.X == t<!>
E3.X == k
k == E3.X
@@ -137,9 +137,9 @@ interface Inv<T>
enum class E4 : Inv<Int> { A }
fun foo10(e4: E4, invString: Inv<String>) {
<!EQUALITY_NOT_APPLICABLE_WARNING!>e4 == invString<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>invString == e4<!>
e4 == invString
invString == e4
<!EQUALITY_NOT_APPLICABLE_WARNING!>E4.A == invString<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>invString == E4.A<!>
E4.A == invString
invString == E4.A
}
@@ -26,27 +26,27 @@ fun foo1(e1: E1, e2: E2) {
fun foo2(e1: E1, e2: E2) {
when (e1) {
E1.A -> {}
<!INCOMPATIBLE_TYPES!>E2.A<!> -> {}
<!INCOMPATIBLE_TYPES!>E2.B<!> -> {}
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>E2.A<!> -> {}
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>E2.B<!> -> {}
e1 -> {}
<!INCOMPATIBLE_TYPES!>e2<!> -> {}
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>e2<!> -> {}
else -> {}
}
}
fun foo3(e1: Enum<E1>, e2: Enum<E2>, e: Enum<*>) {
e1 == e
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>e1 == e2<!>
e1 == e2
e1 == E1.A
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>e1 == E2.A<!>
e1 == E2.A
when (e1) {
e1 -> {}
<!INCOMPATIBLE_TYPES!>e2<!> -> {}
e2 -> {}
e -> {}
E1.A -> {}
<!INCOMPATIBLE_TYPES!>E2.A<!> -> {}
E2.A -> {}
else -> {}
}
@@ -70,8 +70,8 @@ fun foo4(e1: E1, i: MyInterface, c: MyOpenClass) {
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>c == e1<!>
when (e1) {
<!INCOMPATIBLE_TYPES!>i<!> -> {}
<!INCOMPATIBLE_TYPES!>c<!> -> {}
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>i<!> -> {}
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>c<!> -> {}
else -> {}
}
}
@@ -102,7 +102,7 @@ fun foo6(e1: E1?, e2: E2) {
}
fun foo7(e1: E1?, e2: E2?) {
e1 == e2 // There should be an IDE-inspection for such cases
<!INCOMPATIBLE_ENUM_COMPARISON!>e1 == e2<!> // There should be an IDE-inspection for such cases
}
fun <T> foo8(e1: E1?, e2: E2, t: T) {
@@ -117,16 +117,16 @@ fun <T> foo8(e1: E1?, e2: E2, t: T) {
}
fun <T, K> foo9(e1: E1?, e2: E2, t: T, k: K) where T : MyInterface, T : MyOpenClass, K : MyInterface {
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == t<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>t == e1<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>e1 == t<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>t == e1<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>e2 == t<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>t == e2<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>e2 == t<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>t == e2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>E1.A == t<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>t == E1.A<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>E1.A == t<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>t == E1.A<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>E3.X == t<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>E3.X == t<!>
E3.X == k
k == E3.X
@@ -137,9 +137,9 @@ interface Inv<T>
enum class E4 : Inv<Int> { A }
fun foo10(e4: E4, invString: Inv<String>) {
<!EQUALITY_NOT_APPLICABLE_WARNING!>e4 == invString<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>invString == e4<!>
e4 == invString
invString == e4
<!EQUALITY_NOT_APPLICABLE_WARNING!>E4.A == invString<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>invString == E4.A<!>
E4.A == invString
invString == E4.A
}
@@ -56,47 +56,47 @@ fun foo(
<!EQUALITY_NOT_APPLICABLE!>"" == 2<!>
<!EQUALITY_NOT_APPLICABLE!>string == int<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>strings == ints<!>
strings == ints
<!EQUALITY_NOT_APPLICABLE_WARNING!>aString == aInt<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aOutString == aOutInt<!>
aString == aInt
aOutString == aOutInt
aInString == aInInt
<!EQUALITY_NOT_APPLICABLE_WARNING!>aOutString == aInInt<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aInString == aOutInt<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aOutString == aInt<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aInString == aInt<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aOutString2 == aOutInt2<!>
aOutString == aInInt
aInString == aOutInt
aOutString == aInt
aInString == aInt
aOutString2 == aOutInt2
aInString2 == aInInt2
<!EQUALITY_NOT_APPLICABLE_WARNING!>aOutString2 == aInInt2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aInString2 == aOutInt2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aString == a2<!>
aOutString2 == aInInt2
aInString2 == aOutInt2
aString == a2
<!EQUALITY_NOT_APPLICABLE_WARNING!>bString == bInt<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>bOutString == bOutInt<!>
bString == bInt
bOutString == bOutInt
bInString == bInInt
<!EQUALITY_NOT_APPLICABLE_WARNING!>bOutString == bInInt<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>bInString == bOutInt<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>bOutString == bInt<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>bInString == bInt<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>bOutString2 == bOutInt2<!>
bOutString == bInInt
bInString == bOutInt
bOutString == bInt
bInString == bInt
bOutString2 == bOutInt2
bInString2 == bInInt2
<!EQUALITY_NOT_APPLICABLE_WARNING!>bOutString2 == bInInt2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>bInString2 == bOutInt2<!>
bOutString2 == bInInt2
bInString2 == bOutInt2
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>e == i<!>
<!EQUALITY_NOT_APPLICABLE!>"" == i<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>ac == ad<!>
ac == ad
<!EQUALITY_NOT_APPLICABLE_WARNING!>tSub1 == tSub2<!>
tSub1 == tSub2
<!EQUALITY_NOT_APPLICABLE_WARNING!>aString == bString<!>
aString == bString
<!EQUALITY_NOT_APPLICABLE_WARNING!>aListInt == aSetInt<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aSetInt == aListString<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aListString == aListInt<!>
aListInt == aSetInt
aSetInt == aListString
aListString == aListInt
<!EQUALITY_NOT_APPLICABLE_WARNING!>aString == aListString<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>bString == aListString<!>
aString == aListString
bString == aListString
<!EQUALITY_NOT_APPLICABLE_WARNING!>mutableListAny == listString<!>
mutableListAny == listString
}
@@ -0,0 +1,7 @@
// FIR_IDENTICAL
// ISSUE: KTIJ-15380
fun test() {
var x = 0
if (x == x) {}
}
@@ -0,0 +1,8 @@
// ISSUE: KT-46383
fun test(a: Any, b: Any, s: String, i: Int) {
if (a is String && b is Int) {
<!EQUALITY_NOT_APPLICABLE_WARNING!>a == b<!>
}
<!EQUALITY_NOT_APPLICABLE!>s == i<!>
}
@@ -0,0 +1,8 @@
// ISSUE: KT-46383
fun test(a: Any, b: Any, s: String, i: Int) {
if (a is String && b is Int) {
a == b
}
<!EQUALITY_NOT_APPLICABLE!>s == i<!>
}
@@ -3,18 +3,18 @@
fun main(x: Long, y: Int) {
sequence {
<!EQUALITY_NOT_APPLICABLE_WARNING!>1L == 3<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>x == 3<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>3 == 1L<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>3 == x<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>y == x<!>
<!EQUALITY_NOT_APPLICABLE!>1L == 3<!>
<!EQUALITY_NOT_APPLICABLE!>x == 3<!>
<!EQUALITY_NOT_APPLICABLE!>3 == 1L<!>
<!EQUALITY_NOT_APPLICABLE!>3 == x<!>
<!EQUALITY_NOT_APPLICABLE!>y == x<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>1L === 3<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>x === 3<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>3 === 1L<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>3 === x<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>y === x<!>
<!FORBIDDEN_IDENTITY_EQUALS!>1L === 3<!>
<!FORBIDDEN_IDENTITY_EQUALS!>x === 3<!>
<!FORBIDDEN_IDENTITY_EQUALS!>3 === 1L<!>
<!FORBIDDEN_IDENTITY_EQUALS!>3 === x<!>
<!FORBIDDEN_IDENTITY_EQUALS!>y === x<!>
yield("")
}
}
}
@@ -3,18 +3,18 @@
fun main(x: Long, y: Int) {
sequence {
<!EQUALITY_NOT_APPLICABLE_WARNING!>1L == 3<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>x == 3<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>3 == 1L<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>3 == x<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>y == x<!>
<!EQUALITY_NOT_APPLICABLE!>1L == 3<!>
<!EQUALITY_NOT_APPLICABLE!>x == 3<!>
<!EQUALITY_NOT_APPLICABLE!>3 == 1L<!>
<!EQUALITY_NOT_APPLICABLE!>3 == x<!>
<!EQUALITY_NOT_APPLICABLE!>y == x<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>1L === 3<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>x === 3<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>3 === 1L<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>3 === x<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>y === x<!>
<!FORBIDDEN_IDENTITY_EQUALS!>1L === 3<!>
<!FORBIDDEN_IDENTITY_EQUALS!>x === 3<!>
<!FORBIDDEN_IDENTITY_EQUALS!>3 === 1L<!>
<!FORBIDDEN_IDENTITY_EQUALS!>3 === x<!>
<!FORBIDDEN_IDENTITY_EQUALS!>y === x<!>
yield("")
}
}
}
@@ -5,18 +5,18 @@ inline class Foo(val x: Int)
inline class Bar(val y: String)
fun test(f1: Foo, f2: Foo, b1: Bar, fn1: Foo?, fn2: Foo?) {
val a1 = f1 === f2 || f1 !== f2
val a2 = f1 === f1
val a3 = <!EQUALITY_NOT_APPLICABLE!>f1 === b1<!> || <!EQUALITY_NOT_APPLICABLE!>f1 !== b1<!>
val a1 = <!FORBIDDEN_IDENTITY_EQUALS!>f1 === f2<!> || <!FORBIDDEN_IDENTITY_EQUALS!>f1 !== f2<!>
val a2 = <!FORBIDDEN_IDENTITY_EQUALS!>f1 === f1<!>
val a3 = <!FORBIDDEN_IDENTITY_EQUALS!>f1 === b1<!> || <!FORBIDDEN_IDENTITY_EQUALS!>f1 !== b1<!>
val c1 = fn1 === fn2 || fn1 !== fn2
val c2 = f1 === fn1 || f1 !== fn1
val c3 = <!EQUALITY_NOT_APPLICABLE!>b1 === fn1<!> || <!EQUALITY_NOT_APPLICABLE!>b1 !== fn1<!>
val c2 = <!FORBIDDEN_IDENTITY_EQUALS!>f1 === fn1<!> || <!FORBIDDEN_IDENTITY_EQUALS!>f1 !== fn1<!>
val c3 = <!FORBIDDEN_IDENTITY_EQUALS!>b1 === fn1<!> || <!FORBIDDEN_IDENTITY_EQUALS!>b1 !== fn1<!>
val any = Any()
val d1 = any === f1 || any !== f1
val d2 = f1 === any || f1 !== any
val d1 = <!FORBIDDEN_IDENTITY_EQUALS!>any === f1<!> || <!FORBIDDEN_IDENTITY_EQUALS!>any !== f1<!>
val d2 = <!FORBIDDEN_IDENTITY_EQUALS!>f1 === any<!> || <!FORBIDDEN_IDENTITY_EQUALS!>f1 !== any<!>
val d3 = any === fn1 || any !== fn1
val d4 = fn1 === any || fn1 !== any
}
@@ -3,12 +3,12 @@
const val equalsBoolean1 = true.equals(true)
const val equalsBoolean2 = false != true
const val equalsBoolean3 = false.equals(1)
const val equalsBoolean4 = <!EQUALITY_NOT_APPLICABLE_WARNING!>false == 1<!>
const val equalsBoolean4 = <!EQUALITY_NOT_APPLICABLE!>false == 1<!>
const val equalsChar1 = '1'.equals('2')
const val equalsChar2 = '2' == '2'
const val equalsChar3 = '1'.equals(1)
const val equalsChar4 = <!EQUALITY_NOT_APPLICABLE_WARNING!>'1' == 1<!>
const val equalsChar4 = <!EQUALITY_NOT_APPLICABLE!>'1' == 1<!>
const val equalsByte1 = 1.toByte().equals(2.toByte())
const val equalsByte2 = 2.toByte() == 2.toByte()
@@ -3,12 +3,12 @@
const val equalsBoolean1 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>true.equals(true)<!>
const val equalsBoolean2 = false != true
const val equalsBoolean3 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>false.equals(1)<!>
const val equalsBoolean4 = <!EQUALITY_NOT_APPLICABLE_WARNING!>false == 1<!>
const val equalsBoolean4 = <!EQUALITY_NOT_APPLICABLE!>false == 1<!>
const val equalsChar1 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>'1'.equals('2')<!>
const val equalsChar2 = '2' == '2'
const val equalsChar3 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>'1'.equals(1)<!>
const val equalsChar4 = <!EQUALITY_NOT_APPLICABLE_WARNING!>'1' == 1<!>
const val equalsChar4 = <!EQUALITY_NOT_APPLICABLE!>'1' == 1<!>
const val equalsByte1 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1.toByte().equals(2.toByte())<!>
const val equalsByte2 = 2.toByte() == 2.toByte()
@@ -8,8 +8,8 @@ import checkSubtype
fun main(args : Array<String>) {
val x = checkSubtype<Any>(args[0])
if(x is <!PLATFORM_CLASS_MAPPED_TO_KOTLIN!>java.lang.CharSequence<!>) {
if (<!EQUALITY_NOT_APPLICABLE!>"a" == x<!>) x.<!FUNCTION_CALL_EXPECTED!>length<!> else x.length() // OK
if (<!EQUALITY_NOT_APPLICABLE!>"a" == x<!> || <!EQUALITY_NOT_APPLICABLE!>"b" == x<!>) x.<!FUNCTION_CALL_EXPECTED!>length<!> else x.length() // < THEN ERROR
if (<!EQUALITY_NOT_APPLICABLE!>"a" == x<!> && <!EQUALITY_NOT_APPLICABLE!>"a" == x<!>) x.<!FUNCTION_CALL_EXPECTED!>length<!> else x.length() // < ELSE ERROR
if (<!EQUALITY_NOT_APPLICABLE_WARNING!>"a" == x<!>) x.<!FUNCTION_CALL_EXPECTED!>length<!> else x.length() // OK
if (<!EQUALITY_NOT_APPLICABLE_WARNING!>"a" == x<!> || <!EQUALITY_NOT_APPLICABLE_WARNING!>"b" == x<!>) x.<!FUNCTION_CALL_EXPECTED!>length<!> else x.length() // < THEN ERROR
if (<!EQUALITY_NOT_APPLICABLE_WARNING!>"a" == x<!> && <!EQUALITY_NOT_APPLICABLE_WARNING!>"a" == x<!>) x.<!FUNCTION_CALL_EXPECTED!>length<!> else x.length() // < ELSE ERROR
}
}
@@ -11,7 +11,7 @@ sealed class Tree {
fun maxIsClass(): Int = <!NO_ELSE_IN_WHEN!>when<!>(this) {
Empty -> -1
<!INCOMPATIBLE_TYPES, NO_COMPANION_OBJECT!>Leaf<!> -> 0
<!NO_COMPANION_OBJECT!>Leaf<!> -> 0
is Node -> this.left.max()
}
@@ -6,18 +6,18 @@ fun test(
ui1: UInt, ui2: UInt,
ul1: ULong, ul2: ULong
) {
val ub = ub1 === ub2 || ub1 !== ub2
val us = us1 === us2 || us1 !== us2
val ui = ui1 === ui2 || ui1 !== ui2
val ul = ul1 === ul2 || ul1 !== ul2
val ub = <!FORBIDDEN_IDENTITY_EQUALS!>ub1 === ub2<!> || <!FORBIDDEN_IDENTITY_EQUALS!>ub1 !== ub2<!>
val us = <!FORBIDDEN_IDENTITY_EQUALS!>us1 === us2<!> || <!FORBIDDEN_IDENTITY_EQUALS!>us1 !== us2<!>
val ui = <!FORBIDDEN_IDENTITY_EQUALS!>ui1 === ui2<!> || <!FORBIDDEN_IDENTITY_EQUALS!>ui1 !== ui2<!>
val ul = <!FORBIDDEN_IDENTITY_EQUALS!>ul1 === ul2<!> || <!FORBIDDEN_IDENTITY_EQUALS!>ul1 !== ul2<!>
val u = <!EQUALITY_NOT_APPLICABLE!>ub1 === ul1<!>
val u = <!FORBIDDEN_IDENTITY_EQUALS!>ub1 === ul1<!>
val a1 = 1u === 2u || 1u !== 2u
val a2 = 0xFFFF_FFFF_FFFF_FFFFu === 0xFFFF_FFFF_FFFF_FFFFu
val a1 = <!FORBIDDEN_IDENTITY_EQUALS!>1u === 2u<!> || <!FORBIDDEN_IDENTITY_EQUALS!>1u !== 2u<!>
val a2 = <!FORBIDDEN_IDENTITY_EQUALS!>0xFFFF_FFFF_FFFF_FFFFu === 0xFFFF_FFFF_FFFF_FFFFu<!>
val bu1 = 1u
val bu2 = 1u
val c1 = bu1 === bu2 || bu1 !== bu2
val c1 = <!FORBIDDEN_IDENTITY_EQUALS!>bu1 === bu2<!> || <!FORBIDDEN_IDENTITY_EQUALS!>bu1 !== bu2<!>
}
@@ -13,18 +13,18 @@ value class Foo(val x: Int)
value class Bar(val y: String)
fun test(f1: Foo, f2: Foo, b1: Bar, fn1: Foo?, fn2: Foo?) {
val a1 = f1 === f2 || f1 !== f2
val a2 = f1 === f1
val a3 = <!EQUALITY_NOT_APPLICABLE!>f1 === b1<!> || <!EQUALITY_NOT_APPLICABLE!>f1 !== b1<!>
val a1 = <!FORBIDDEN_IDENTITY_EQUALS!>f1 === f2<!> || <!FORBIDDEN_IDENTITY_EQUALS!>f1 !== f2<!>
val a2 = <!FORBIDDEN_IDENTITY_EQUALS!>f1 === f1<!>
val a3 = <!FORBIDDEN_IDENTITY_EQUALS!>f1 === b1<!> || <!FORBIDDEN_IDENTITY_EQUALS!>f1 !== b1<!>
val c1 = fn1 === fn2 || fn1 !== fn2
val c2 = f1 === fn1 || f1 !== fn1
val c3 = <!EQUALITY_NOT_APPLICABLE!>b1 === fn1<!> || <!EQUALITY_NOT_APPLICABLE!>b1 !== fn1<!>
val c2 = <!FORBIDDEN_IDENTITY_EQUALS!>f1 === fn1<!> || <!FORBIDDEN_IDENTITY_EQUALS!>f1 !== fn1<!>
val c3 = <!FORBIDDEN_IDENTITY_EQUALS!>b1 === fn1<!> || <!FORBIDDEN_IDENTITY_EQUALS!>b1 !== fn1<!>
val any = Any()
val d1 = any === f1 || any !== f1
val d2 = f1 === any || f1 !== any
val d1 = <!FORBIDDEN_IDENTITY_EQUALS!>any === f1<!> || <!FORBIDDEN_IDENTITY_EQUALS!>any !== f1<!>
val d2 = <!FORBIDDEN_IDENTITY_EQUALS!>f1 === any<!> || <!FORBIDDEN_IDENTITY_EQUALS!>f1 !== any<!>
val d3 = any === fn1 || any !== fn1
val d4 = fn1 === any || fn1 !== any
}
+1 -1
View File
@@ -22,7 +22,7 @@ fun foo() : Int {
<!USELESS_IS_CHECK!>!is Int<!> -> 1
<!USELESS_IS_CHECK!>is Any?<!> -> 1
<!USELESS_IS_CHECK!>is Any<!> -> 1
s -> 1
<!INCOMPATIBLE_TYPES!>s<!> -> 1
1 -> 1
1 <!OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> <!UNRESOLVED_REFERENCE!>a<!> -> 1
in 1..<!UNRESOLVED_REFERENCE!>a<!> -> 1
@@ -47,8 +47,8 @@ fun testWithSubject_ok(x: Boolean, y: Boolean?, any: Any, z: Boolean) {
x <!OVERLOAD_RESOLUTION_AMBIGUITY!>>=<!> x -> {}
x == x -> {}
x != x -> {}
x === x -> {}
x !== x -> {}
<!DEPRECATED_IDENTITY_EQUALS!>x === x<!> -> {}
<!DEPRECATED_IDENTITY_EQUALS!>x !== x<!> -> {}
x && x -> {}
x || x -> {}
}
@@ -0,0 +1,10 @@
// ISSUE: KT-54473
interface I
class A : I
class B : I
fun test(a: A, b: B) {
a == b
a == b as I
}
@@ -0,0 +1,10 @@
// ISSUE: KT-54473
interface I
class A : I
class B : I
fun test(a: A, b: B) {
<!EQUALITY_NOT_APPLICABLE!>a == b<!>
a == b as I
}
@@ -0,0 +1,14 @@
// ISSUE: KT-25808
// WITH_STDLIB
// B.java
public class B {
}
// test.kt
class A
fun main(args: Array<String>) {
(1 to A()) == A()
(1 to B()) == B()
}
@@ -0,0 +1,14 @@
// ISSUE: KT-25808
// WITH_STDLIB
// B.java
public class B {
}
// test.kt
class A
fun main(args: Array<String>) {
<!EQUALITY_NOT_APPLICABLE!>(1 to A()) == A()<!>
<!EQUALITY_NOT_APPLICABLE!>(1 to B()) == B()<!>
}
@@ -0,0 +1,23 @@
// ISSUE: KT-35134
interface A
fun foo(a: Any) {
if (a is A) {
if (<!EQUALITY_NOT_APPLICABLE_WARNING!>a == (<!EQUALITY_NOT_APPLICABLE_WARNING!>a == 1<!>)<!>) {
println(1)
}
when (a) {
<!CONFUSING_BRANCH_CONDITION_ERROR, EQUALITY_NOT_APPLICABLE_WARNING, INCOMPATIBLE_TYPES!>a == 1<!> -> print("1")
}
if (<!EQUALITY_NOT_APPLICABLE!>(a <!USELESS_CAST!>as A<!>) == (<!EQUALITY_NOT_APPLICABLE_WARNING!>a == 1<!>)<!>) {
println(1)
}
when (a <!USELESS_CAST!>as A<!>) {
<!CONFUSING_BRANCH_CONDITION_ERROR, EQUALITY_NOT_APPLICABLE_WARNING, INCOMPATIBLE_TYPES!>a == 1<!> -> print("1")
}
}
}
@@ -0,0 +1,23 @@
// ISSUE: KT-35134
interface A
fun foo(a: Any) {
if (a is A) {
if (a == (a == 1)) {
println(1)
}
when (a) {
<!CONFUSING_BRANCH_CONDITION_ERROR!>a == 1<!> -> print("1")
}
if (<!EQUALITY_NOT_APPLICABLE!>(a <!USELESS_CAST!>as A<!>) == (a == 1)<!>) {
println(1)
}
when (a <!USELESS_CAST!>as A<!>) {
<!CONFUSING_BRANCH_CONDITION_ERROR, INCOMPATIBLE_TYPES!>a == 1<!> -> print("1")
}
}
}
@@ -0,0 +1,10 @@
// ISSUE: KT-47979
enum class Foo { A, B }
fun test() {
if (Triple(Foo.A, 1, 2) == Pair("a", "b")) println("Doesn't compile")
if (Triple(0, 1, 2) == Pair(Foo.A, "a")) println("Doesn't compile")
if (Triple(0, 1, 2) == Pair("a", "b")) println("Doesn't compile")
if (Triple(Foo.A, 1, 2) == Pair(Foo.A, "a")) println("Compiles, but why?")
}
@@ -0,0 +1,10 @@
// ISSUE: KT-47979
enum class Foo { A, B }
fun test() {
if (<!EQUALITY_NOT_APPLICABLE!>Triple(Foo.A, 1, 2) == Pair("a", "b")<!>) println("Doesn't compile")
if (<!EQUALITY_NOT_APPLICABLE!>Triple(0, 1, 2) == Pair(Foo.A, "a")<!>) println("Doesn't compile")
if (<!EQUALITY_NOT_APPLICABLE!>Triple(0, 1, 2) == Pair("a", "b")<!>) println("Doesn't compile")
if (Triple(Foo.A, 1, 2) == Pair(Foo.A, "a")) println("Compiles, but why?")
}
@@ -0,0 +1,74 @@
interface B
fun equalityNotApplicable(a: Int, b: B) {
<!EQUALITY_NOT_APPLICABLE!>a == b<!>
}
fun equalityNotApplicableSmartCast(a: Any?, b: Any?) {
if (a is Int && b is B) {
<!EQUALITY_NOT_APPLICABLE_WARNING!>a == b<!>
}
}
@JvmInline
value class C(val int: Int)
@JvmInline
value class D(val bool: Boolean)
fun forbiddenIdentityEquals(c: C, d: D) {
<!FORBIDDEN_IDENTITY_EQUALS!>c === d<!>
}
fun forbiddenIdentityEqualsSmartCast(c: Any?, d: Any?) {
if (c is C && d is D) {
<!FORBIDDEN_IDENTITY_EQUALS_WARNING!>c === d<!>
}
}
fun implicitBoxingInIdentityEquals(i: Int, a: Any?) {
<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>i === a<!>
}
fun implicitBoxingInIdentityEqualsSmartCast(i: Any?, a: Any?) {
if (i is Int) {
<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>i === a<!>
}
}
fun deprecatedIdentityEquals(a: Int, b: Int) {
<!DEPRECATED_IDENTITY_EQUALS!>a === b<!>
}
fun deprecatedIdentityEqualsSmartCast(a: Any?, b: Any?) {
if (a is Int && b is Int) {
<!DEPRECATED_IDENTITY_EQUALS!>a === b<!>
}
}
fun incompatibleTypes(a: Int) = when(a) {
<!INCOMPATIBLE_TYPES!>C(10)<!> -> 1
else -> 2
}
fun incompatibleTypesSmartCast(a: Any?) {
if (a is Int) {
when(a) {
<!INCOMPATIBLE_TYPES!>C(10)<!> -> 1
else -> 2
}
}
}
enum class E {
A, B
}
fun incompatibleEnumComparison(c: B, e: E) {
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>c == e<!>
}
fun incompatibleEnumComparisonSmartCast(c: Any?, e: Any?) {
if (c is B && e is E) {
<!INCOMPATIBLE_ENUM_COMPARISON!>c == e<!>
}
}
@@ -0,0 +1,74 @@
interface B
fun equalityNotApplicable(a: Int, b: B) {
<!EQUALITY_NOT_APPLICABLE!>a == b<!>
}
fun equalityNotApplicableSmartCast(a: Any?, b: Any?) {
if (a is Int && b is B) {
a == b
}
}
@JvmInline
value class C(val int: Int)
@JvmInline
value class D(val bool: Boolean)
fun forbiddenIdentityEquals(c: C, d: D) {
<!EQUALITY_NOT_APPLICABLE, FORBIDDEN_IDENTITY_EQUALS!>c === d<!>
}
fun forbiddenIdentityEqualsSmartCast(c: Any?, d: Any?) {
if (c is C && d is D) {
c === d
}
}
fun implicitBoxingInIdentityEquals(i: Int, a: Any?) {
<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>i === a<!>
}
fun implicitBoxingInIdentityEqualsSmartCast(i: Any?, a: Any?) {
if (i is Int) {
i === a
}
}
fun deprecatedIdentityEquals(a: Int, b: Int) {
<!DEPRECATED_IDENTITY_EQUALS!>a === b<!>
}
fun deprecatedIdentityEqualsSmartCast(a: Any?, b: Any?) {
if (a is Int && b is Int) {
a === b
}
}
fun incompatibleTypes(a: Int) = when(a) {
<!INCOMPATIBLE_TYPES!>C(10)<!> -> 1
else -> 2
}
fun incompatibleTypesSmartCast(a: Any?) {
if (a is Int) {
when(<!DEBUG_INFO_SMARTCAST!>a<!>) {
C(10) -> 1
else -> 2
}
}
}
enum class E {
A, B
}
fun incompatibleEnumComparison(c: B, e: E) {
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>c == e<!>
}
fun incompatibleEnumComparisonSmartCast(c: Any?, e: Any?) {
if (c is B && e is E) {
c == e
}
}
@@ -0,0 +1,38 @@
// LANGUAGE: +ReportErrorsForComparisonOperators
fun nullableNothingIdentity(a: Int, b: Nothing?) {
<!FORBIDDEN_IDENTITY_EQUALS, SENSELESS_COMPARISON!>a === b<!>
}
fun samePrimitiveIdentity(a: Int, b: Int) {
<!DEPRECATED_IDENTITY_EQUALS!>a === b<!>
}
fun identityWithImplicitBoxing(a: Int, b: Any?) {
<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a === b<!>
}
enum class E1 { A, B }
enum class E2 { C, D }
fun nullableEnums(a: E1?, b: E2?) {
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>a == b<!>
}
fun <T> enumAsTypeParameterBound(a: T, b: Int) where T : Any, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>E1<!> {
<!EQUALITY_NOT_APPLICABLE!>a == b<!>
}
fun <T, K> twoTypeParameters(a: T, b: K) where T : Number, K : <!FINAL_UPPER_BOUND!>String<!> {
<!EQUALITY_NOT_APPLICABLE!>a == b<!>
}
interface I1
interface I2
enum class E3 : I1 { A, B }
fun <A> compareTypeParameterWithEnum(a: A) where A: I1, A: I2 {
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>a == E1.A<!>
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>a == E3.A<!>
}
@@ -0,0 +1,38 @@
// LANGUAGE: +ReportErrorsForComparisonOperators
fun nullableNothingIdentity(a: Int, b: Nothing?) {
a === <!DEBUG_INFO_CONSTANT!>b<!>
}
fun samePrimitiveIdentity(a: Int, b: Int) {
<!DEPRECATED_IDENTITY_EQUALS!>a === b<!>
}
fun identityWithImplicitBoxing(a: Int, b: Any?) {
<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a === b<!>
}
enum class E1 { A, B }
enum class E2 { C, D }
fun nullableEnums(a: E1?, b: E2?) {
a == b
}
fun <T> enumAsTypeParameterBound(a: T, b: Int) where T : Any, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>E1<!> {
<!EQUALITY_NOT_APPLICABLE!>a == b<!>
}
fun <T, K> twoTypeParameters(a: T, b: K) where T : Number, K : <!FINAL_UPPER_BOUND!>String<!> {
a == b
}
interface I1
interface I2
enum class E3 : I1 { A, B }
fun <A> compareTypeParameterWithEnum(a: A) where A: I1, A: I2 {
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>a == E1.A<!>
a == E3.A
}
@@ -0,0 +1,38 @@
// LANGUAGE: -ReportErrorsForComparisonOperators
fun nullableNothingIdentity(a: Int, b: Nothing?) {
<!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>a === b<!>
}
fun samePrimitiveIdentity(a: Int, b: Int) {
<!DEPRECATED_IDENTITY_EQUALS!>a === b<!>
}
fun identityWithImplicitBoxing(a: Int, b: Any?) {
<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a === b<!>
}
enum class E1 { A, B }
enum class E2 { C, D }
fun nullableEnums(a: E1?, b: E2?) {
<!INCOMPATIBLE_ENUM_COMPARISON!>a == b<!>
}
fun <T> enumAsTypeParameterBound(a: T, b: Int) where T : Any, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>E1<!> {
<!EQUALITY_NOT_APPLICABLE!>a == b<!>
}
fun <T, K> twoTypeParameters(a: T, b: K) where T : Number, K : <!FINAL_UPPER_BOUND!>String<!> {
<!EQUALITY_NOT_APPLICABLE_WARNING!>a == b<!>
}
interface I1
interface I2
enum class E3 : I1 { A, B }
fun <A> compareTypeParameterWithEnum(a: A) where A: I1, A: I2 {
<!INCOMPATIBLE_ENUM_COMPARISON!>a == E1.A<!>
<!INCOMPATIBLE_ENUM_COMPARISON!>a == E3.A<!>
}
@@ -0,0 +1,38 @@
// LANGUAGE: -ReportErrorsForComparisonOperators
fun nullableNothingIdentity(a: Int, b: Nothing?) {
a === <!DEBUG_INFO_CONSTANT!>b<!>
}
fun samePrimitiveIdentity(a: Int, b: Int) {
<!DEPRECATED_IDENTITY_EQUALS!>a === b<!>
}
fun identityWithImplicitBoxing(a: Int, b: Any?) {
<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a === b<!>
}
enum class E1 { A, B }
enum class E2 { C, D }
fun nullableEnums(a: E1?, b: E2?) {
a == b
}
fun <T> enumAsTypeParameterBound(a: T, b: Int) where T : Any, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>E1<!> {
<!EQUALITY_NOT_APPLICABLE!>a == b<!>
}
fun <T, K> twoTypeParameters(a: T, b: K) where T : Number, K : <!FINAL_UPPER_BOUND!>String<!> {
a == b
}
interface I1
interface I2
enum class E3 : I1 { A, B }
fun <A> compareTypeParameterWithEnum(a: A) where A: I1, A: I2 {
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>a == E1.A<!>
a == E3.A
}
@@ -159,6 +159,24 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/CompareToWithErrorType.kt");
}
@Test
@TestMetadata("comparingArbitraryClasses.kt")
public void testComparingArbitraryClasses() throws Exception {
runTest("compiler/testData/diagnostics/tests/comparingArbitraryClasses.kt");
}
@Test
@TestMetadata("comparingCallableReferencesWithInstanceOfJavaClass.kt")
public void testComparingCallableReferencesWithInstanceOfJavaClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt");
}
@Test
@TestMetadata("comparisonOfGenericInterfaceWithGenericClass.kt")
public void testComparisonOfGenericInterfaceWithGenericClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt");
}
@Test
@TestMetadata("Constants.kt")
public void testConstants() throws Exception {
@@ -243,6 +261,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/DiamondProperty.kt");
}
@Test
@TestMetadata("differentNumericTypesFromSmartCast.kt")
public void testDifferentNumericTypesFromSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt");
}
@Test
@TestMetadata("Dollar.kt")
public void testDollar() throws Exception {
@@ -255,6 +279,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/EnumEntryAsType.kt");
}
@Test
@TestMetadata("equalityComparisonToSelf.kt")
public void testEqualityComparisonToSelf() throws Exception {
runTest("compiler/testData/diagnostics/tests/equalityComparisonToSelf.kt");
}
@Test
@TestMetadata("equalityWithSmartCastInIfBlock.kt")
public void testEqualityWithSmartCastInIfBlock() throws Exception {
runTest("compiler/testData/diagnostics/tests/equalityWithSmartCastInIfBlock.kt");
}
@Test
@TestMetadata("ExtensionCallInvoke.kt")
public void testExtensionCallInvoke() throws Exception {
@@ -10398,6 +10434,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/enum/enumWithEmptyName.kt");
}
@Test
@TestMetadata("equalityOfEnumAndParameter.kt")
public void testEqualityOfEnumAndParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt");
}
@Test
@TestMetadata("equalityOfFlexibleTypeParameters.kt")
public void testEqualityOfFlexibleTypeParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/enum/equalityOfFlexibleTypeParameters.kt");
}
@Test
@TestMetadata("ExplicitConstructorCall.kt")
public void testExplicitConstructorCall() throws Exception {
@@ -36203,6 +36251,30 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/testsWithStdLib/commonCollections.kt");
}
@Test
@TestMetadata("comparingDifferentSubclassesCommonInterface.kt")
public void testComparingDifferentSubclassesCommonInterface() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt");
}
@Test
@TestMetadata("comparingPlatformTypes.kt")
public void testComparingPlatformTypes() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt");
}
@Test
@TestMetadata("comparingSmartCastValueToBoolean.kt")
public void testComparingSmartCastValueToBoolean() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingSmartCastValueToBoolean.kt");
}
@Test
@TestMetadata("comparingTripleWithPair.kt")
public void testComparingTripleWithPair() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt");
}
@Test
@TestMetadata("compileTimeUnsignedArray.kt")
public void testCompileTimeUnsignedArray() throws Exception {
@@ -36227,6 +36299,24 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/testsWithStdLib/enumEntryInitialization.kt");
}
@Test
@TestMetadata("equalityCompatibilityCommonCases.kt")
public void testEqualityCompatibilityCommonCases() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityCommonCases.kt");
}
@Test
@TestMetadata("equalityCompatibilityOldBehavior_Off.kt")
public void testEqualityCompatibilityOldBehavior_Off() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_Off.kt");
}
@Test
@TestMetadata("equalityCompatibilityOldBehavior_On.kt")
public void testEqualityCompatibilityOldBehavior_On() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/equalityCompatibilityOldBehavior_On.kt");
}
@Test
@TestMetadata("exitProcess.kt")
public void testExitProcess() throws Exception {
@@ -21,7 +21,7 @@ fun case_1(x: Any?) {
// TESTCASE NUMBER: 3
fun case_3() {
if (<!SENSELESS_COMPARISON!>Object.prop_1 == null !== null<!>)
if (<!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>Object.prop_1 == null !== null<!>)
else {
Object.prop_1
Object.prop_1<!UNSAFE_CALL!>.<!>equals(null)
@@ -56,7 +56,7 @@ fun case_4(x: Char?) {
fun case_5() {
val x: Unit? = null
if (<!EQUALITY_NOT_APPLICABLE!>x !== <!USELESS_IS_CHECK!>null is Boolean?<!><!>) <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit?")!>x<!>
if (<!FORBIDDEN_IDENTITY_EQUALS!>x !== <!USELESS_IS_CHECK!>null is Boolean?<!><!>) <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit?")!>x<!>
if (<!SENSELESS_COMPARISON!>x !== null == null<!>) <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit?")!>x<!><!UNSAFE_CALL!>.<!>equals(null)
if (<!SENSELESS_COMPARISON!>x !== null == null<!>) <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit?")!>x<!>.propT
if (<!SENSELESS_COMPARISON!>x !== null == null<!>) <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit?")!>x<!><!UNSAFE_CALL!>.<!>propAny
@@ -88,7 +88,7 @@ fun case_6(x: EmptyClass?) {
// TESTCASE NUMBER: 7
fun case_7() {
if (nullableNumberProperty != null || <!SENSELESS_COMPARISON!><!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number? & kotlin.Nothing?")!>nullableNumberProperty<!> != null is Boolean<!>) {
if (nullableNumberProperty != null || <!EQUALITY_NOT_APPLICABLE, SENSELESS_COMPARISON!><!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number? & kotlin.Nothing?")!>nullableNumberProperty<!> != null is Boolean<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number?")!>nullableNumberProperty<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number?")!>nullableNumberProperty<!><!UNSAFE_CALL!>.<!>equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number?")!>nullableNumberProperty<!>.propT
@@ -104,13 +104,13 @@ fun case_7() {
// TESTCASE NUMBER: 8
fun case_8(x: TypealiasNullableString) {
if (<!SENSELESS_COMPARISON!>x !== null === null<!> && <!SENSELESS_COMPARISON!><!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!> != null != null<!>) <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!><!UNSAFE_CALL!>.<!>get(0)
if (<!SENSELESS_COMPARISON!>x !== null != null<!> && <!SENSELESS_COMPARISON!><!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!> != null === null<!>) <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!><!UNSAFE_CALL!>.<!>get(0)
if (<!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>x !== null === null<!> && <!SENSELESS_COMPARISON!><!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!> != null != null<!>) <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!><!UNSAFE_CALL!>.<!>get(0)
if (<!SENSELESS_COMPARISON!>x !== null != null<!> && <!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!><!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!> != null === null<!>) <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!><!UNSAFE_CALL!>.<!>get(0)
}
// TESTCASE NUMBER: 9
fun case_9(x: TypealiasNullableString<!REDUNDANT_NULLABLE!>?<!>) {
if (<!SENSELESS_COMPARISON!>x === null === null<!>) {
if (<!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>x === null === null<!>) {
} else if (<!USELESS_IS_CHECK!>false is Boolean<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString?")!>x<!>
@@ -123,7 +123,7 @@ fun case_10() {
val a = Class()
if (a.prop_4 === null || <!USELESS_IS_CHECK!>true is Boolean<!>) {
if (<!SENSELESS_COMPARISON!>a.prop_4 != null !== null<!>) {
if (<!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>a.prop_4 != null !== null<!>) {
a.prop_4
a.prop_4<!UNSAFE_CALL!>.<!>equals(null)
a.prop_4.propT
@@ -166,8 +166,8 @@ fun case_11(x: TypealiasNullableStringIndirect<!REDUNDANT_NULLABLE!>?<!>, y: Typ
// TESTCASE NUMBER: 12
fun case_12(x: TypealiasNullableStringIndirect, y: TypealiasNullableStringIndirect) =
if (<!USELESS_IS_CHECK!>(x == null) !is Boolean<!> === false) "1"
else if (<!USELESS_IS_CHECK!>(<!SENSELESS_COMPARISON!>y === null !== null<!>) is Boolean<!>) <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableStringIndirect")!>x<!>
if (<!DEPRECATED_IDENTITY_EQUALS!><!USELESS_IS_CHECK!>(x == null) !is Boolean<!> === false<!>) "1"
else if (<!USELESS_IS_CHECK!>(<!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>y === null !== null<!>) is Boolean<!>) <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableStringIndirect")!>x<!>
else if (<!SENSELESS_COMPARISON!>y === null != null<!>) <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableStringIndirect")!>x<!>.equals(null)
else if (<!SENSELESS_COMPARISON!>y === null != null<!>) <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableStringIndirect")!>x<!>.propT
else if (<!SENSELESS_COMPARISON!>y === null != null<!>) <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableStringIndirect")!>x<!><!UNSAFE_CALL!>.<!>propAny
@@ -181,7 +181,7 @@ fun case_12(x: TypealiasNullableStringIndirect, y: TypealiasNullableStringIndire
// TESTCASE NUMBER: 13
fun case_13(x: <!UNRESOLVED_REFERENCE!>otherpackage.Case13<!>?) =
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Boolean")!>if ((x == null !is Boolean) !== true) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Boolean")!>if (<!DEPRECATED_IDENTITY_EQUALS!>(x == null !is Boolean) !== true<!>) {
throw Exception()
} else {
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Symbol not found for otherpackage.Case13? & kotlin.Boolean")!>x<!>
@@ -204,18 +204,18 @@ fun case_14() {
if (a.x != null == true) {
if (<!SENSELESS_COMPARISON!>a.x !== null<!> == false) {
if (<!SENSELESS_COMPARISON!><!SENSELESS_COMPARISON!>a.x != null<!> == null<!>) {
if (<!SENSELESS_COMPARISON!><!SENSELESS_COMPARISON!>a.x != null<!> !== null<!>) {
if (<!SENSELESS_COMPARISON!>a.x != null<!> === true) {
if (<!SENSELESS_COMPARISON!>a.x !== null<!> === <!USELESS_IS_CHECK!>true !is Boolean<!> == true) {
if (<!SENSELESS_COMPARISON!>a.x != null<!> !== false) {
if (<!SENSELESS_COMPARISON!>a.x != null<!> === false) {
if (<!SENSELESS_COMPARISON!>a.x !== null<!> === true) {
if (<!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!><!SENSELESS_COMPARISON!>a.x != null<!> !== null<!>) {
if (<!DEPRECATED_IDENTITY_EQUALS!><!SENSELESS_COMPARISON!>a.x != null<!> === true<!>) {
if (<!DEPRECATED_IDENTITY_EQUALS!><!SENSELESS_COMPARISON!>a.x !== null<!> === <!USELESS_IS_CHECK!>true !is Boolean<!><!> == true) {
if (<!DEPRECATED_IDENTITY_EQUALS!><!SENSELESS_COMPARISON!>a.x != null<!> !== false<!>) {
if (<!DEPRECATED_IDENTITY_EQUALS!><!SENSELESS_COMPARISON!>a.x != null<!> === false<!>) {
if (<!DEPRECATED_IDENTITY_EQUALS!><!SENSELESS_COMPARISON!>a.x !== null<!> === true<!>) {
if (<!USELESS_IS_CHECK!>(<!SENSELESS_COMPARISON!>a.x != null<!> != true) !is Boolean<!>) {
if (a.x != null is Boolean) {
if (a.x != <!USELESS_IS_CHECK!>null is Boolean is Boolean<!>) {
if (a.x !== null is Boolean) {
if (<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a.x !== null is Boolean<!>) {
if (a.x != null is Boolean) {
if ((a.x !== null !is Boolean) == false) {
if ((<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>a.x !== null !is Boolean<!>) == false) {
a.x
a.x.equals(a.x)
}
@@ -238,7 +238,7 @@ fun case_14() {
// TESTCASE NUMBER: 15
fun case_15(x: EmptyObject) {
val t = if (<!EQUALITY_NOT_APPLICABLE!>x === <!USELESS_IS_CHECK!><!USELESS_IS_CHECK!>null is Boolean is Boolean<!> is Boolean<!><!>) "" else {
val t = if (<!FORBIDDEN_IDENTITY_EQUALS!>x === <!USELESS_IS_CHECK!><!USELESS_IS_CHECK!>null is Boolean is Boolean<!> is Boolean<!><!>) "" else {
<!DEBUG_INFO_EXPRESSION_TYPE("EmptyObject")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("EmptyObject")!>x<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("EmptyObject")!>x<!>.propT
@@ -256,7 +256,7 @@ fun case_15(x: EmptyObject) {
fun case_16() {
val x: TypealiasNullableNothing = null
if (<!EQUALITY_NOT_APPLICABLE!>x != <!USELESS_IS_CHECK!><!USELESS_IS_CHECK!><!USELESS_IS_CHECK!><!USELESS_IS_CHECK!>null !is Boolean !is Boolean<!> !is Boolean<!> !is Boolean<!> !is Boolean<!><!>) {
if (<!SENSELESS_COMPARISON!>x != <!USELESS_IS_CHECK!><!USELESS_IS_CHECK!><!USELESS_IS_CHECK!><!USELESS_IS_CHECK!>null !is Boolean !is Boolean<!> !is Boolean<!> !is Boolean<!> !is Boolean<!><!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableNothing")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableNothing")!>x<!><!UNSAFE_CALL!>.<!>java
}
@@ -270,7 +270,7 @@ val case_17 = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>if (nullableIntPrope
//TESTCASE NUMBER: 18
fun case_18(a: DeepObject.A.B.C.D.E.F.G.J?) {
if (<!SENSELESS_COMPARISON!>a != null !== null<!>) {
if (<!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>a != null !== null<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("DeepObject.A.B.C.D.E.F.G.J?")!>a<!>
<!DEBUG_INFO_EXPRESSION_TYPE("DeepObject.A.B.C.D.E.F.G.J?")!>a<!><!UNSAFE_CALL!>.<!>equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("DeepObject.A.B.C.D.E.F.G.J?")!>a<!>.propT
@@ -304,7 +304,7 @@ fun case_19(b: Boolean) {
}
} else null
if (<!EQUALITY_NOT_APPLICABLE!>a != null !is Boolean<!> && <!EQUALITY_NOT_APPLICABLE!>a<!UNSAFE_CALL!>.<!>B19 != null is Boolean<!> && <!EQUALITY_NOT_APPLICABLE!>a<!UNSAFE_CALL!>.<!>B19<!UNSAFE_CALL!>.<!>C19 != null is Boolean<!> && <!SENSELESS_COMPARISON!>a<!UNSAFE_CALL!>.<!>B19<!UNSAFE_CALL!>.<!>C19<!UNSAFE_CALL!>.<!>D19 != null == null<!> && <!SENSELESS_COMPARISON!>a<!UNSAFE_CALL!>.<!>B19<!UNSAFE_CALL!>.<!>C19<!UNSAFE_CALL!>.<!>D19<!UNSAFE_CALL!>.<!>x != null !== null<!>) {
if (<!EQUALITY_NOT_APPLICABLE!>a != null !is Boolean<!> && <!EQUALITY_NOT_APPLICABLE!>a<!UNSAFE_CALL!>.<!>B19 != null is Boolean<!> && <!EQUALITY_NOT_APPLICABLE!>a<!UNSAFE_CALL!>.<!>B19<!UNSAFE_CALL!>.<!>C19 != null is Boolean<!> && <!SENSELESS_COMPARISON!>a<!UNSAFE_CALL!>.<!>B19<!UNSAFE_CALL!>.<!>C19<!UNSAFE_CALL!>.<!>D19 != null == null<!> && <!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>a<!UNSAFE_CALL!>.<!>B19<!UNSAFE_CALL!>.<!>C19<!UNSAFE_CALL!>.<!>D19<!UNSAFE_CALL!>.<!>x != null !== null<!>) {
a<!UNSAFE_CALL!>.<!>B19<!UNSAFE_CALL!>.<!>C19<!UNSAFE_CALL!>.<!>D19<!UNSAFE_CALL!>.<!>x
a<!UNSAFE_CALL!>.<!>B19<!UNSAFE_CALL!>.<!>C19<!UNSAFE_CALL!>.<!>D19<!UNSAFE_CALL!>.<!>x<!UNSAFE_CALL!>.<!>equals(null)
a<!UNSAFE_CALL!>.<!>B19<!UNSAFE_CALL!>.<!>C19<!UNSAFE_CALL!>.<!>D19<!UNSAFE_CALL!>.<!>x.propT
@@ -330,7 +330,7 @@ fun case_20(b: Boolean) {
}
}
if (<!EQUALITY_NOT_APPLICABLE!>a.B19.C19.D19 !== null !is Boolean<!>) {
if (<!FORBIDDEN_IDENTITY_EQUALS!>a.B19.C19.D19 !== null !is Boolean<!>) {
a.B19.C19.D19
a.B19.C19.D19<!UNSAFE_CALL!>.<!>equals(null)
a.B19.C19.D19.propT
@@ -346,7 +346,7 @@ fun case_20(b: Boolean) {
// TESTCASE NUMBER: 21
fun case_21() {
if (<!EQUALITY_NOT_APPLICABLE_WARNING!>EnumClassWithNullableProperty.B.prop_1 !== null is Boolean<!> == <!USELESS_IS_CHECK!>true !is Boolean<!> != true) {
if (<!FORBIDDEN_IDENTITY_EQUALS!>EnumClassWithNullableProperty.B.prop_1 !== null is Boolean<!> == <!USELESS_IS_CHECK!>true !is Boolean<!> != true) {
EnumClassWithNullableProperty.B.prop_1
EnumClassWithNullableProperty.B.prop_1<!UNSAFE_CALL!>.<!>equals(null)
EnumClassWithNullableProperty.B.prop_1.propT
@@ -378,7 +378,7 @@ fun case_22(a: (() -> Unit)?) {
// TESTCASE NUMBER: 23
fun case_23(a: ((Float) -> Int?)?, b: Float?) {
if (<!EQUALITY_NOT_APPLICABLE!>a != null !is Boolean<!> && <!EQUALITY_NOT_APPLICABLE_WARNING!>b !== null is Boolean<!>) {
if (<!EQUALITY_NOT_APPLICABLE!>a != null !is Boolean<!> && <!FORBIDDEN_IDENTITY_EQUALS!>b !== null is Boolean<!>) {
val x = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Float?")!>b<!>)<!>
if (x != null) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>x<!>
@@ -397,7 +397,7 @@ fun case_23(a: ((Float) -> Int?)?, b: Float?) {
// TESTCASE NUMBER: 24
fun case_24(a: ((() -> Unit) -> Unit)?, b: (() -> Unit)?) =
if (<!EQUALITY_NOT_APPLICABLE!>a !== null is Boolean<!> && <!EQUALITY_NOT_APPLICABLE!>b !== null !is Boolean<!>) {
if (<!FORBIDDEN_IDENTITY_EQUALS!>a !== null is Boolean<!> && <!FORBIDDEN_IDENTITY_EQUALS!>b !== null !is Boolean<!>) {
<!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function0<kotlin.Unit>?")!>b<!>)
<!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>(b)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function0<kotlin.Unit>?")!>b<!><!UNSAFE_CALL!>.<!>equals(null)
@@ -421,10 +421,10 @@ fun case_25(b: Boolean) {
val y = if (b) x else null
if (y !== null === true) {
if (<!DEPRECATED_IDENTITY_EQUALS!>y !== null === true<!>) {
val z = <!DEBUG_INFO_EXPRESSION_TYPE("<anonymous>?")!>y()<!>
if (z != null !== false) {
if (<!DEPRECATED_IDENTITY_EQUALS!>z != null !== false<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("<anonymous>? & <anonymous>")!>z<!>.a
<!DEBUG_INFO_EXPRESSION_TYPE("<anonymous>? & <anonymous>")!>z<!>.a.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("<anonymous>? & <anonymous>")!>z<!>.a.propT
@@ -443,7 +443,7 @@ fun case_25(b: Boolean) {
fun case_26(a: ((Float) -> Int?)?, b: Float?) {
if (a != null == true == false && b != null == true == false) {
val x = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Float? & kotlin.Nothing?")!>b<!>)<!>
if (x != null == true === false) {
if (<!DEPRECATED_IDENTITY_EQUALS!>x != null == true === false<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Nothing?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Nothing?")!>x<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Nothing?")!>x<!>.propT
@@ -322,7 +322,7 @@ fun case_15(x: EmptyObject) {
fun case_16() {
val x: TypealiasNullableNothing = null
if (x != null) {
if (<!SENSELESS_COMPARISON!>x != null<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableNothing & kotlin.Nothing")!>x<!>
}
}
@@ -16,7 +16,7 @@ fun case_1(x: Any?) {
* ISSUES: KT-28329
*/
fun case_2(x: Any) {
if (x is Int === true) {
if (<!DEPRECATED_IDENTITY_EQUALS!>x is Int === true<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.Int")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.Int")!>x<!>.inv()
}
@@ -60,7 +60,7 @@ fun case_6(x: Any?) {
* ISSUES: KT-28329
*/
fun case_7(x: Any) {
if (!(x is DeepObject.A.B.C.D.E.F.G.J) !== false) else {
if (<!DEPRECATED_IDENTITY_EQUALS!>!(x is DeepObject.A.B.C.D.E.F.G.J) !== false<!>) else {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & DeepObject.A.B.C.D.E.F.G.J")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & DeepObject.A.B.C.D.E.F.G.J")!>x<!>.prop_1
}
@@ -72,7 +72,7 @@ fun case_7(x: Any) {
* ISSUES: KT-28329
*/
fun case_8(x: Any?) {
if (!(x is Int?) !== false !== false !== false) else {
if (<!DEPRECATED_IDENTITY_EQUALS!><!DEPRECATED_IDENTITY_EQUALS!><!DEPRECATED_IDENTITY_EQUALS!>!(x is Int?) !== false<!> !== false<!> !== false<!>) else {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Int?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Int?")!>x<!>?.inv()
}
@@ -84,7 +84,7 @@ fun case_8(x: Any?) {
* ISSUES: KT-28329
*/
fun case_9(x: Any?) {
if (!!(x !is TypealiasNullableStringIndirect<!REDUNDANT_NULLABLE!>?<!>) !== false === true) else {
if (<!DEPRECATED_IDENTITY_EQUALS!><!DEPRECATED_IDENTITY_EQUALS!>!!(x !is TypealiasNullableStringIndirect<!REDUNDANT_NULLABLE!>?<!>) !== false<!> === true<!>) else {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & TypealiasNullableStringIndirect?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & TypealiasNullableStringIndirect?")!>x<!>?.get(0)
}
@@ -96,7 +96,7 @@ fun case_9(x: Any?) {
* ISSUES: KT-28329
*/
fun case_10(x: Any?) {
if (!!(x !is Interface3) === true && true) else {
if (<!DEPRECATED_IDENTITY_EQUALS!>!!(x !is Interface3) === true<!> && true) else {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>.<!UNRESOLVED_REFERENCE!>itest<!>()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>.<!UNRESOLVED_REFERENCE!>itest3<!>()
@@ -161,7 +161,7 @@ inline fun <reified T>case_17(x: Any?) {
* ISSUES: KT-30369, KT-28262, KT-29878
*/
inline fun <reified T>case_18(x: Any?) {
if (x?.equals(10) === null === true) else {
if (<!DEPRECATED_IDENTITY_EQUALS!>x?.equals(10) === null === true<!>) else {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>.equals(10)
}
@@ -173,7 +173,7 @@ inline fun <reified T>case_18(x: Any?) {
* ISSUES: KT-30369, KT-28262, KT-29878
*/
inline fun <reified T>case_19(x: Any?) {
if (x?.equals(10) !== null === true) {
if (<!DEPRECATED_IDENTITY_EQUALS!>x?.equals(10) !== null === true<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>.equals(10)
}
@@ -185,7 +185,7 @@ inline fun <reified T>case_19(x: Any?) {
* ISSUES: KT-30369, KT-28262, KT-29878
*/
inline fun <reified T>case_20(x: Any?) {
if (x?.equals(10) === null !== false) else {
if (<!DEPRECATED_IDENTITY_EQUALS!>x?.equals(10) === null !== false<!>) else {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>.equals(10)
}
@@ -197,7 +197,7 @@ inline fun <reified T>case_20(x: Any?) {
* ISSUES: KT-30369, KT-28262, KT-29878
*/
inline fun <reified T>case_21(x: Any?) {
if (x?.equals(10) !== null !== false) {
if (<!DEPRECATED_IDENTITY_EQUALS!>x?.equals(10) !== null !== false<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>.equals(10)
}
@@ -209,7 +209,7 @@ inline fun <reified T>case_21(x: Any?) {
* ISSUES: KT-30369, KT-28262, KT-29878
*/
inline fun <reified T>case_22(x: Any?) {
if (x?.equals(10) !== null !== true) else {
if (<!DEPRECATED_IDENTITY_EQUALS!>x?.equals(10) !== null !== true<!>) else {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>.equals(10)
}
@@ -221,7 +221,7 @@ inline fun <reified T>case_22(x: Any?) {
* ISSUES: KT-30369, KT-28262, KT-29878
*/
inline fun <reified T>case_23(x: Any?) {
if (x?.equals(10) === null === false) {
if (<!DEPRECATED_IDENTITY_EQUALS!>x?.equals(10) === null === false<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>.equals(10)
}
@@ -257,7 +257,7 @@ inline fun <reified T>case_25(x: Any?) {
* ISSUES: KT-30369, KT-29878
*/
inline fun <reified T>case_26(x: Any?) {
if (x?.equals(10) != null === false) else {
if (<!DEPRECATED_IDENTITY_EQUALS!>x?.equals(10) != null === false<!>) else {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>.equals(10)
}
@@ -269,7 +269,7 @@ inline fun <reified T>case_26(x: Any?) {
* ISSUES: KT-30369, KT-29878
*/
inline fun <reified T>case_27(x: Any?) {
if (x?.equals(10) == null === false) {
if (<!DEPRECATED_IDENTITY_EQUALS!>x?.equals(10) == null === false<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>.equals(10)
}
@@ -181,7 +181,7 @@ fun case_15(x: TypealiasNullableString) {
fun case_16() {
val x: TypealiasNullableNothing = null
if (x == null || false || false || false) {
if (<!SENSELESS_COMPARISON!>x == null<!> || false || false || false) {
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableNothing")!>x<!>
}
}
@@ -127,7 +127,7 @@ fun case_10(x: Any?, z: Any, b: Boolean?) {
false -> return
null -> throw Exception()
}
z === y || if (b == true) return else if (b === false) null!! else throw Exception()
z === y || if (b == true) return else if (<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>b === false<!>) null!! else throw Exception()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>y<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>y<!>.equals(10)
@@ -137,7 +137,7 @@ fun case_10(x: Any?, z: Any, b: Boolean?) {
fun case_11(x: Any?, z: Any, b: Boolean?) {
while (true) {
var y = x ?: if (b == true) continue<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!> else if (!(b != false)) return else break <!USELESS_ELVIS!>?: break::class<!>
z !== y && if (b == true) return else if (b === false) null!!else throw Exception()
z !== y && if (b == true) return else if (<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>b === false<!>) null!!else throw Exception()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>y<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>y<!>.equals(10)
@@ -148,7 +148,7 @@ fun case_11(x: Any?, z: Any, b: Boolean?) {
fun case_12(x: Any?, z: Any, b: Boolean?) {
while (true) {
var y = select(x) ?: if (b == true) continue<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!> else if (!(b != false)) return else break <!USELESS_ELVIS!>?: break::class<!>
select(z) !== y && if (b == true) return else if (b === false) null!!else throw Exception()
select(z) !== y && if (b == true) return else if (<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>b === false<!>) null!!else throw Exception()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>y<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>y<!>.equals(10)
@@ -77,7 +77,7 @@ fun case_6(x: Boolean?) {
// TESTCASE NUMBER: 7
fun case_7(x: Boolean?) {
while (true) {
if (!(x === false)) return
if (!(<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>x === false<!>)) return
}
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Boolean?")!>x<!>
@@ -257,7 +257,7 @@ fun case_22(a: (() -> Unit)) {
fun case_23(a: ((Float) -> Int), b: Float) {
if (<!SENSELESS_COMPARISON!>a == null<!> && <!SENSELESS_COMPARISON!>b == null<!>) {
val x = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>a(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Float & kotlin.Nothing")!>b<!>)<!>
if (<!SENSELESS_COMPARISON!>x !== null<!>) {
if (<!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>x !== null<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>x<!>
}
}
@@ -282,7 +282,7 @@ fun case_25(a: (() -> Unit) -> Unit, b: (() -> Unit) -> Unit = if (<!SENSELESS_C
}
// TESTCASE NUMBER: 26
fun case_26(a: Int, b: Int = if (<!SENSELESS_COMPARISON!>a === null<!>) <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int & kotlin.Nothing")!>a<!> else 0) {
fun case_26(a: Int, b: Int = if (<!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>a === null<!>) <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int & kotlin.Nothing")!>a<!> else 0) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>a<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>b<!>
}
@@ -21,7 +21,7 @@ fun case_1(x: Any?, y: Any?) {
* ISSUES: KT-30317
*/
fun case_2(x: Any?, y: Any?) {
if (x as Int === y) {
if (<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>x as Int === y<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Int")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Int")!>x<!>.inv(<!TOO_MANY_ARGUMENTS!>10<!>)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Int")!>y<!>
@@ -49,7 +49,7 @@ fun case_3(x: Any?, y: Any?) {
* ISSUES: KT-30317
*/
fun case_4(x: Any?, y: Any?) {
if (y === x as Int) {
if (<!IMPLICIT_BOXING_IN_IDENTITY_EQUALS!>y === x as Int<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Int")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Int")!>x<!>.inv(<!TOO_MANY_ARGUMENTS!>10<!>)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Int")!>y<!>
@@ -26,7 +26,7 @@ fun case_2() {
do {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
x = x<!UNSAFE_CALL!>.<!>equals(10)
} while (<!SENSELESS_COMPARISON!>x !== null<!>)
} while (<!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>x !== null<!>)
}
// TESTCASE NUMBER: 3
@@ -58,7 +58,7 @@ fun case_5() {
do {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
x = x<!UNSAFE_CALL!>.<!>equals(10)
} while (<!SENSELESS_COMPARISON!>x !== null<!>)
} while (<!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>x !== null<!>)
}
/*
@@ -86,7 +86,7 @@ fun case_7() {
do {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
x = x<!UNSAFE_CALL!>.<!>equals(10)
} while (<!SENSELESS_COMPARISON!>x !== null<!>)
} while (<!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>x !== null<!>)
}
/*
@@ -114,7 +114,7 @@ fun case_9() {
do {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
x = x<!UNSAFE_CALL!>.<!>equals(10)
} while (<!SENSELESS_COMPARISON!>x !== null<!>)
} while (<!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>x !== null<!>)
}
/*
@@ -300,7 +300,7 @@ fun case_16() {
val x: TypealiasNullableNothing = null
val y: Nothing? = null
if (x !== y) {
if (<!SENSELESS_COMPARISON!>x !== y<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableNothing & kotlin.Nothing")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableNothing & kotlin.Nothing")!>x<!>.hashCode()
}
@@ -437,7 +437,7 @@ fun case_22(a: (() -> Unit)?) {
// TESTCASE NUMBER: 23
fun case_23(a: ((Float) -> Int?)?, b: Float?, z: Nothing?) {
if (a != z && b !== z && <!SENSELESS_COMPARISON!>b !== z<!>) {
if (a != z && b !== z && <!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>b !== z<!>) {
val x = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>a(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Float? & kotlin.Float")!>b<!>)<!>
if (x != z || <!SENSELESS_COMPARISON!>x !== implicitNullableNothingProperty<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>x<!>
@@ -577,7 +577,7 @@ fun case_29(x: Boolean) {
if (false || false || false || false || y !== v) {
val t = <!DEBUG_INFO_EXPRESSION_TYPE("<anonymous>?")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>y<!>()<!>
if (<!EQUALITY_NOT_APPLICABLE_WARNING!>z !== t<!> || false) {
if (z !== t || false) {
<!DEBUG_INFO_EXPRESSION_TYPE("<anonymous>?")!>t<!><!UNSAFE_CALL!>.<!>a
<!DEBUG_INFO_EXPRESSION_TYPE("<anonymous>?")!>t<!><!UNSAFE_CALL!>.<!>equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("<anonymous>?")!>t<!>.propT
@@ -677,7 +677,7 @@ fun case_33(a: ((Float) -> Int?)?, b: Float?, c: Boolean?) {
fun case_34(z1: Boolean?) {
var z = null
if (true && true && true && true && EnumClassWithNullableProperty.A.prop_1 != implicitNullableNothingProperty && <!SENSELESS_COMPARISON!>EnumClassWithNullableProperty.A.prop_1 !== null<!> && <!SENSELESS_COMPARISON!>EnumClassWithNullableProperty.A.prop_1 !== z<!> || z1 != implicitNullableNothingProperty || z1!! && true && true) {
if (true && true && true && true && EnumClassWithNullableProperty.A.prop_1 != implicitNullableNothingProperty && <!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>EnumClassWithNullableProperty.A.prop_1 !== null<!> && <!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>EnumClassWithNullableProperty.A.prop_1 !== z<!> || z1 != implicitNullableNothingProperty || z1!! && true && true) {
} else {
EnumClassWithNullableProperty.A.prop_1
@@ -910,7 +910,7 @@ fun case_51() {
val x: TypealiasNullableNothing = null
val z: Nothing? = null
if (x === z || <!SENSELESS_COMPARISON!>z == x<!> && <!SENSELESS_COMPARISON!>x == z<!> || false || false || false) {
if (<!SENSELESS_COMPARISON!>x === z<!> || <!SENSELESS_COMPARISON!>z == x<!> && <!SENSELESS_COMPARISON!>x == z<!> || false || false || false) {
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableNothing")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableNothing")!>x<!>.hashCode()
}
@@ -1401,7 +1401,7 @@ fun case_75(t: Any?, z: Nothing?) {
}
// TESTCASE NUMBER: 76
fun case_76(a: Any?, b: Int = if (a !is Number? === true || a !is Int? == true || a != null == false == true) 0 else <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Int")!>a<!>) {
fun case_76(a: Any?, b: Int = if (<!DEPRECATED_IDENTITY_EQUALS!>a !is Number? === true<!> || a !is Int? == true || a != null == false == true) 0 else <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Int")!>a<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>a<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>b<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>b<!>.equals(null)
@@ -168,7 +168,7 @@ fun case_9(x: TypealiasNullableString<!REDUNDANT_NULLABLE!>?<!>) {
fun case_10() {
val a = Class()
if (a.prop_4 === null || <!SENSELESS_COMPARISON!>a.prop_4 === null<!> || true) {
if (a.prop_4 === null || <!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>a.prop_4 === null<!> || true) {
if (a.prop_4 != null) {
a.prop_4
a.prop_4.equals(null)
@@ -283,14 +283,14 @@ fun case_16() {
val x: TypealiasNothing? = null
val y: Nothing? = null
if (x != null || x !== null || x != y) {
if (<!SENSELESS_COMPARISON!>x != null<!> || <!SENSELESS_COMPARISON!>x !== null<!> || <!SENSELESS_COMPARISON!>x != y<!>) {
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNothing? & kotlin.Nothing")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNothing? & kotlin.Nothing")!>x<!>.hashCode()
}
}
// TESTCASE NUMBER: 17
val case_17 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>if (nullableIntProperty == null || <!SENSELESS_COMPARISON!>nullableNothingProperty === nullableIntProperty<!>) 0 else {
val case_17 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>if (nullableIntProperty == null || <!FORBIDDEN_IDENTITY_EQUALS_WARNING, SENSELESS_COMPARISON!>nullableNothingProperty === nullableIntProperty<!>) 0 else {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>nullableIntProperty<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>nullableIntProperty<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>nullableIntProperty<!>.propAny
@@ -307,6 +307,10 @@ enum class LanguageFeature(
// When this feature is enabled, no such errors are reported.
NoBuilderInferenceWithoutAnnotationRestriction(sinceVersion = null, kind = OTHER),
// Disabled for indefinite time. Forces K2 report errors (instead of warnings) for incompatible
// equality & identity operators in cases where K1 would report warnings or would not report anything.
ReportErrorsForComparisonOperators(sinceVersion = null, kind = BUG_FIX),
// Experimental features
BreakContinueInInlineLambdas(null), // KT-1436