diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirEqualityCompatibilityChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirEqualityCompatibilityChecker.kt index 120096616fa..2c4949004f2 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirEqualityCompatibilityChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirEqualityCompatibilityChecker.kt @@ -25,7 +25,6 @@ import org.jetbrains.kotlin.fir.expressions.* 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.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.name.StandardClassIds @@ -101,15 +100,11 @@ object FirEqualityCompatibilityChecker : FirEqualityOperatorCallChecker(MppCheck } 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) + oneIsNotNull && shouldReportAsPerRules1(l, r, context) -> getInapplicabilityFor(l, r) else -> Applicability.APPLICABLE } } @@ -126,13 +121,12 @@ object FirEqualityCompatibilityChecker : FirEqualityOperatorCallChecker(MppCheck } 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 + val oneIsFinal = l.isFinal || r.isFinal return when { l.type.isNothingOrNullableNothing || r.type.isNothingOrNullableNothing -> false - else -> !l.isSubtypeOf(r, context) && !r.isSubtypeOf(l, context) + oneIsFinal -> !l.isSubtypeOf(r, context) && !r.isSubtypeOf(l, context) + else -> false } } @@ -302,6 +296,7 @@ private class TypeInfo( val isPrimitive: Boolean, val isBuiltin: Boolean, val isValueClass: Boolean, + val isFinal: Boolean, val canHaveSubtypesAccordingToK1: Boolean, ) { override fun toString() = "$type" @@ -309,20 +304,6 @@ private class TypeInfo( private val FirClassSymbol<*>.isBuiltin get() = isPrimitiveType() || classId == StandardClassIds.String || isEnumClass -// This property is used to replicate K1 behavior, and it -// tries to match the `TypeUtils.canHaveSubtypes(typeChecker, type)` -// check in the K1 intersector. -// In K2 enum classes are final, though enum entries are their subclasses. -private fun ConeKotlinType.canHaveSubtypesAccordingToK1(session: FirSession): Boolean { - val symbol = toSymbol(session) - - return when { - symbol is FirRegularClassSymbol && symbol.isEnumClass -> true - symbol is FirClassSymbol<*> && symbol.isFinalClass -> false - else -> true - } -} - private val TypeInfo.isNullableEnum get() = isEnumClass && type.isNullable private val TypeInfo.isIdentityLess get() = isPrimitive || isValueClass @@ -350,7 +331,9 @@ private fun ConeKotlinType.toTypeInfo(session: FirSession): TypeInfo { isPrimitive = bounds.any { it.isPrimitiveOrNullablePrimitive }, isBuiltin = bounds.any { it.toClassSymbol(session)?.isBuiltin == true }, isValueClass = bounds.any { it.toClassSymbol(session)?.isInline == true }, - canHaveSubtypesAccordingToK1(session), + isFinal = bounds.any { it.toClassSymbol(session)?.isFinalClass == true }, + // In K1's intersector, `canHaveSubtypes()` is called for `nullabilityStripped`. + withNullability(ConeNullability.NOT_NULL, session.typeContext).canHaveSubtypes(session), ) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirPrivateToThisAccessChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirPrivateToThisAccessChecker.kt index 1929335ee98..0d3c331fa99 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirPrivateToThisAccessChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirPrivateToThisAccessChecker.kt @@ -38,7 +38,8 @@ object FirPrivateToThisAccessChecker : FirQualifiedAccessExpressionChecker(MppCh // If there was a visibility diagnostic, no need to report another one about visibility when (reference.diagnostic) { is ConeVisibilityError, - is ConeSetterVisibilityError -> return + is ConeSetterVisibilityError + -> return } } val dispatchReceiver = expression.dispatchReceiver ?: return @@ -147,12 +148,4 @@ object FirPrivateToThisAccessChecker : FirQualifiedAccessExpressionChecker(MppCh } return false } - - private val ConeTypeProjection.variance: Variance - get() = when (this.kind) { - ProjectionKind.STAR -> Variance.OUT_VARIANCE - ProjectionKind.IN -> Variance.IN_VARIANCE - ProjectionKind.OUT -> Variance.OUT_VARIANCE - ProjectionKind.INVARIANT -> Variance.INVARIANT - } } diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeProjection.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeProjection.kt index 0a765a24e5c..ac4e46c7362 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeProjection.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeProjection.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.types +import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.model.TypeArgumentMarker enum class ProjectionKind { @@ -84,3 +85,11 @@ fun ConeKotlinTypeProjection.replaceType(newType: ConeKotlinType): ConeKotlinTyp is ConeKotlinTypeConflictingProjection -> ConeKotlinTypeConflictingProjection(newType) } } + +val ConeTypeProjection.variance: Variance + get() = when (this.kind) { + ProjectionKind.STAR -> Variance.OUT_VARIANCE + ProjectionKind.IN -> Variance.IN_VARIANCE + ProjectionKind.OUT -> Variance.OUT_VARIANCE + ProjectionKind.INVARIANT -> Variance.INVARIANT + } diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt index 1104d3a19fb..6df5ece3d9f 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt @@ -584,12 +584,16 @@ fun FirCallableDeclaration.isSubtypeOf( ) } +/** + * The original K1 function: [org.jetbrains.kotlin.types.TypeUtils.canHaveSubtypes]. + */ fun ConeKotlinType.canHaveSubtypes(session: FirSession): Boolean { if (this.isMarkedNullable) { return true } val expandedType = fullyExpandedType(session) val classSymbol = expandedType.toSymbol(session) as? FirRegularClassSymbol ?: return true + // In K2 enum classes are final, though enum entries are their subclasses (which is a compiler implementation detail). if (classSymbol.isEnumClass || classSymbol.isExpect || classSymbol.modality != Modality.FINAL) { return true } @@ -603,49 +607,18 @@ fun ConeKotlinType.canHaveSubtypes(session: FirSession): Boolean { val argument = typeProjection.type!! //safe because it is not a star - when (typeParameterSymbol.variance) { - Variance.INVARIANT -> - when (typeProjection.kind) { - ProjectionKind.INVARIANT -> - if (lowerThanBound(session.typeContext, argument, typeParameterSymbol) || argument.canHaveSubtypes(session)) { - return true - } + val canHaveSubtypes = when (typeProjection.variance) { + Variance.OUT_VARIANCE -> argument.canHaveSubtypes(session) + Variance.IN_VARIANCE -> argument.lowerThanBound(typeParameterSymbol, session) + Variance.INVARIANT -> when (typeParameterSymbol.variance) { + Variance.OUT_VARIANCE -> argument.canHaveSubtypes(session) + Variance.IN_VARIANCE -> argument.lowerThanBound(typeParameterSymbol, session) + Variance.INVARIANT -> argument.canHaveSubtypes(session) || argument.lowerThanBound(typeParameterSymbol, session) + } + } - ProjectionKind.IN -> - if (lowerThanBound(session.typeContext, argument, typeParameterSymbol)) { - return true - } - - ProjectionKind.OUT -> - if (argument.canHaveSubtypes(session)) { - return true - } - - ProjectionKind.STAR -> - return true - } - - Variance.IN_VARIANCE -> - if (typeProjection.kind != ProjectionKind.OUT) { - if (lowerThanBound(session.typeContext, argument, typeParameterSymbol)) { - return true - } - } else { - if (argument.canHaveSubtypes(session)) { - return true - } - } - - Variance.OUT_VARIANCE -> - if (typeProjection.kind != ProjectionKind.IN) { - if (argument.canHaveSubtypes(session)) { - return true - } - } else { - if (lowerThanBound(session.typeContext, argument, typeParameterSymbol)) { - return true - } - } + if (canHaveSubtypes) { + return true } } @@ -668,9 +641,14 @@ fun ConeClassLikeType.toClassSymbol(session: FirSession): FirClassSymbol<*>? { return fullyExpandedType(session).toSymbol(session) as? FirClassSymbol<*> } -private fun lowerThanBound(context: ConeInferenceContext, argument: ConeKotlinType, typeParameterSymbol: FirTypeParameterSymbol): Boolean { +/** + * The original K1 function: [org.jetbrains.kotlin.types.TypeUtils.lowerThanBound]. + * This function returns `true` if `argument` suits any bound rather than the + * intersection of them all, and it expects there to be at least a single bound. + */ +private fun ConeKotlinType.lowerThanBound(typeParameterSymbol: FirTypeParameterSymbol, session: FirSession): Boolean { typeParameterSymbol.resolvedBounds.forEach { boundTypeRef -> - if (argument != boundTypeRef.coneType && argument.isSubtypeOf(context, boundTypeRef.coneType)) { + if (this != boundTypeRef.coneType && isSubtypeOf(session.typeContext, boundTypeRef.coneType)) { return true } } diff --git a/compiler/testData/diagnostics/tests/comparingArbitraryClasses.fir.kt b/compiler/testData/diagnostics/tests/comparingArbitraryClasses.fir.kt index 3542584195c..3b988f820cf 100644 --- a/compiler/testData/diagnostics/tests/comparingArbitraryClasses.fir.kt +++ b/compiler/testData/diagnostics/tests/comparingArbitraryClasses.fir.kt @@ -5,5 +5,5 @@ class A class B fun main() { A() == B() - A() === B() + A() === B() } diff --git a/compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt b/compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt index 20615bedb41..9d06ef2a73c 100644 --- a/compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt +++ b/compiler/testData/diagnostics/tests/comparingCallableReferencesWithInstanceOfJavaClass.kt @@ -16,6 +16,9 @@ fun test (j: J, k: K) { j == K::f j == k::f + j === K::f + j === k::f + when (j) { k::f -> "" K::f -> "" diff --git a/compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.fir.kt b/compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.fir.kt new file mode 100644 index 00000000000..eae3326b06d --- /dev/null +++ b/compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.fir.kt @@ -0,0 +1,8 @@ +// ISSUE: KT-47884 + +interface A +class B + +fun foo(a: A<*>, b: B<*>): Boolean = a == b + +fun bar(a: A<*>, b: B<*>): Boolean = a === b diff --git a/compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt b/compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt index 7261d2be82a..9fc13b851d6 100644 --- a/compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt +++ b/compiler/testData/diagnostics/tests/comparisonOfGenericInterfaceWithGenericClass.kt @@ -1,7 +1,8 @@ -// FIR_IDENTICAL // ISSUE: KT-47884 interface A class B fun foo(a: A<*>, b: B<*>): Boolean = a == b + +fun bar(a: A<*>, b: B<*>): Boolean = a === b diff --git a/compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.fir.kt b/compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.fir.kt index 57e3286176d..66d048e4794 100644 --- a/compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.fir.kt +++ b/compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.fir.kt @@ -5,3 +5,9 @@ fun test(x: Any, y: Any) = fun test(x: Float, y: Double) = x == y + +fun fest(x: Any, y: Any) = + x is Float && y is Double && x === y + +fun fest(x: Float, y: Double) = + x === y diff --git a/compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt b/compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt index 409da498788..cfab12dcbf5 100644 --- a/compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt +++ b/compiler/testData/diagnostics/tests/differentNumericTypesFromSmartCast.kt @@ -5,3 +5,9 @@ fun test(x: Any, y: Any) = fun test(x: Float, y: Double) = x == y + +fun fest(x: Any, y: Any) = + x is Float && y is Double && x === y + +fun fest(x: Float, y: Double) = + x === y diff --git a/compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.kt b/compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.kt index 049d7c169d2..d6eced2e7ed 100644 --- a/compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.kt +++ b/compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.kt @@ -16,3 +16,7 @@ enum class KotlinEnumB fun jj(a: JavaEnumA, b: JavaEnumB) = a == b fun jk(a: JavaEnumA, b: KotlinEnumB) = a == b fun kk(a: KotlinEnumA, b: KotlinEnumB) = a == b + +fun jj2(a: JavaEnumA, b: JavaEnumB) = a === b +fun jk2(a: JavaEnumA, b: KotlinEnumB) = a === b +fun kk2(a: KotlinEnumA, b: KotlinEnumB) = a === b diff --git a/compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.txt b/compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.txt index 306501cee79..9ce7ee5813b 100644 --- a/compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.txt +++ b/compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.txt @@ -1,8 +1,11 @@ package public fun jj(/*0*/ a: JavaEnumA, /*1*/ b: JavaEnumB): kotlin.Boolean +public fun jj2(/*0*/ a: JavaEnumA, /*1*/ b: JavaEnumB): kotlin.Boolean public fun jk(/*0*/ a: JavaEnumA, /*1*/ b: KotlinEnumB): kotlin.Boolean +public fun jk2(/*0*/ a: JavaEnumA, /*1*/ b: KotlinEnumB): kotlin.Boolean public fun kk(/*0*/ a: KotlinEnumA, /*1*/ b: KotlinEnumB): kotlin.Boolean +public fun kk2(/*0*/ a: KotlinEnumA, /*1*/ b: KotlinEnumB): kotlin.Boolean public final enum class JavaEnumA : kotlin.Enum { public constructor JavaEnumA() diff --git a/compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.fir.kt b/compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.fir.kt index 1760777bf74..c962352989a 100644 --- a/compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.fir.kt +++ b/compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.fir.kt @@ -26,6 +26,11 @@ fun

processInfo1(info: String, printer: P) where P: Buffered, P: AIPowered { printer == BufferedEnum.A printer == UsualEnum.C printer == CleverEnum.E + + printer === 20 + printer === BufferedEnum.A + printer === UsualEnum.C + printer === CleverEnum.E } fun

processInfo2(info: String, printer: P) where P: AIPowered, P: Buffered { @@ -33,6 +38,11 @@ fun

processInfo2(info: String, printer: P) where P: AIPowered, P: Buffered { printer == BufferedEnum.A printer == UsualEnum.C printer == CleverEnum.E + + printer === 20 + printer === BufferedEnum.A + printer === UsualEnum.C + printer === CleverEnum.E } abstract class Printer { @@ -44,6 +54,11 @@ fun

processInfo3(info: String, printer: P) where P: Buffered, P: Printer { printer == BufferedEnum.A printer == UsualEnum.C printer == CleverEnum.E + + printer === 20 + printer === BufferedEnum.A + printer === UsualEnum.C + printer === CleverEnum.E } fun test(a: Int, b: Any?) { diff --git a/compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt b/compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt index c0ac3ad09aa..420f3f4391d 100644 --- a/compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt +++ b/compiler/testData/diagnostics/tests/enum/equalityOfEnumAndParameter.kt @@ -26,6 +26,11 @@ fun

processInfo1(info: String, printer: P) where P: Buffered, P: AIPowered { printer == BufferedEnum.A printer == UsualEnum.C printer == CleverEnum.E + + printer === 20 + printer === BufferedEnum.A + printer === UsualEnum.C + printer === CleverEnum.E } fun

processInfo2(info: String, printer: P) where P: AIPowered, P: Buffered { @@ -33,6 +38,11 @@ fun

processInfo2(info: String, printer: P) where P: AIPowered, P: Buffered { printer == BufferedEnum.A printer == UsualEnum.C printer == CleverEnum.E + + printer === 20 + printer === BufferedEnum.A + printer === UsualEnum.C + printer === CleverEnum.E } abstract class Printer { @@ -44,6 +54,11 @@ fun

processInfo3(info: String, printer: P) where P: Buffered, P: Printer { printer == BufferedEnum.A printer == UsualEnum.C printer == CleverEnum.E + + printer === 20 + printer === BufferedEnum.A + printer === UsualEnum.C + printer === CleverEnum.E } fun test(a: Int, b: Any?) { diff --git a/compiler/testData/diagnostics/tests/enum/incompatibleEnumEntryClasses.fir.kt b/compiler/testData/diagnostics/tests/enum/incompatibleEnumEntryClasses.fir.kt new file mode 100644 index 00000000000..b9a289accf0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/enum/incompatibleEnumEntryClasses.fir.kt @@ -0,0 +1,92 @@ +// !LANGUAGE: -ProhibitComparisonOfIncompatibleEnums + +interface I { + fun foo() +} + +enum class E1 : I { + A { + override fun foo() { + this == E2.A + + val q = this + when (q) { + this -> {} + E1.A -> {} + E1.B -> {} + E2.A -> {} + 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) { + e1 == e2 + e1 != e2 + + e1 == E2.A + E1.B == e2 + + 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 -> {} + E2.A -> {} + E2.B -> {} + e1 -> {} + e2 -> {} + else -> {} + } +} + +fun foo3(e1: Enum, e2: Enum, e: Enum<*>) { + e1 == e + e1 == e2 + + e1 == E1.A + e1 == E2.A + + when (e1) { + e1 -> {} + e2 -> {} + e -> {} + E1.A -> {} + E2.A -> {} + else -> {} + } + + when (e) { + e -> {} + e2 -> {} + E1.A -> {} + E2.A -> {} + else -> {} + } +} diff --git a/compiler/testData/diagnostics/tests/enum/incompatibleEnumEntryClasses.kt b/compiler/testData/diagnostics/tests/enum/incompatibleEnumEntryClasses.kt index 142407b797a..d206c690a01 100644 --- a/compiler/testData/diagnostics/tests/enum/incompatibleEnumEntryClasses.kt +++ b/compiler/testData/diagnostics/tests/enum/incompatibleEnumEntryClasses.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL // !LANGUAGE: -ProhibitComparisonOfIncompatibleEnums interface I { diff --git a/compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.fir.kt index 77ad8ad0502..76878757e95 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.fir.kt @@ -7,4 +7,7 @@ class B : I fun test(a: A, b: B) { a == b a == b as I + + a === b + a === b as I } diff --git a/compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt b/compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt index abcba613970..1eb51c77320 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/comparingDifferentSubclassesCommonInterface.kt @@ -7,4 +7,7 @@ class B : I fun test(a: A, b: B) { a == b a == b as I + + a === b + a === b as I } diff --git a/compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.fir.kt index 2baf7b005e2..ac456ece8b5 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.fir.kt @@ -11,4 +11,7 @@ class A fun main(args: Array) { (1 to A()) == A() (1 to B()) == B() + + (1 to A()) === A() + (1 to B()) === B() } diff --git a/compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt b/compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt index f8fb90e7df7..b64cf2bd1d0 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/comparingPlatformTypes.kt @@ -11,4 +11,7 @@ class A fun main(args: Array) { (1 to A()) == A() (1 to B()) == B() + + (1 to A()) === A() + (1 to B()) === B() } diff --git a/compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.fir.kt index 2ef82db994e..6ac3d790fda 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.fir.kt @@ -7,4 +7,9 @@ fun test() { 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?") + + Triple(Foo.A, 1, 2) === Pair("a", "b") + Triple(0, 1, 2) === Pair(Foo.A, "a") + Triple(0, 1, 2) === Pair("a", "b") + Triple(Foo.A, 1, 2) === Pair(Foo.A, "a") } diff --git a/compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt b/compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt index cfb6b7cb36e..9ce7dae54ff 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/comparingTripleWithPair.kt @@ -7,4 +7,9 @@ fun test() { 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?") + + Triple(Foo.A, 1, 2) === Pair("a", "b") + Triple(0, 1, 2) === Pair(Foo.A, "a") + Triple(0, 1, 2) === Pair("a", "b") + Triple(Foo.A, 1, 2) === Pair(Foo.A, "a") } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/6.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/6.fir.kt index 2b290de297e..deb9d33e453 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/6.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/6.fir.kt @@ -585,7 +585,7 @@ fun case_29(x: Boolean) { if (false || false || false || false || y !== v) { val t = ?")!>y() - if (z !== t || false) { + if (z !== t || false) { ?")!>t.a ?")!>t.equals(null) ?")!>t.propT