diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index cba774061c4..f4602f1ecab 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -800,6 +800,8 @@ public interface Errors { DiagnosticFactory2 INCOMPATIBLE_ENUM_COMPARISON = DiagnosticFactory2.create(WARNING); + DiagnosticFactory2 INCOMPATIBLE_ENUM_COMPARISON_ERROR = + DiagnosticFactory2.create(ERROR); DiagnosticFactory1 HAS_NEXT_MISSING = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 HAS_NEXT_FUNCTION_AMBIGUITY = DiagnosticFactory1.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 42da0f262c3..0a933eb0ea8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -741,6 +741,7 @@ public class DefaultErrorMessages { }, 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(INCOMPATIBLE_ENUM_COMPARISON_ERROR, "Comparison of incompatible enums ''{0}'' and ''{1}'' is always unsuccessful", RENDER_TYPE, RENDER_TYPE); MAP.put(SENSELESS_COMPARISON, "Condition ''{0}'' is always ''{1}''", ELEMENT_TEXT, TO_STRING); MAP.put(SENSELESS_NULL_IN_WHEN, "Expression under 'when' is never equal to null"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/TypeIntersector.java b/compiler/frontend/src/org/jetbrains/kotlin/types/TypeIntersector.java index af0743daa1b..18616c7901d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/TypeIntersector.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/TypeIntersector.java @@ -28,7 +28,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.CallHandle; import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem; import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl; import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; -import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt; import java.util.*; @@ -41,11 +40,6 @@ public class TypeIntersector { return intersectTypes(new LinkedHashSet<>(Arrays.asList(typeA, typeB))) == null; } - public static boolean isIncompatibleEnums(@NotNull KotlinType typeA, @NotNull KotlinType typeB) { - if (!TypeUtilsKt.isEnum(typeA) || !TypeUtilsKt.isEnum(typeB)) return false; - return !typeA.getConstructor().equals(typeB.getConstructor()); - } - @Nullable public static KotlinType intersectTypes(@NotNull Collection types) { assert !types.isEmpty() : "Attempting to intersect empty collection of types, this case should be dealt with on the call site."; diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/enumCompatibilityChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/enumCompatibilityChecker.kt new file mode 100644 index 00000000000..f66fbaedff2 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/enumCompatibilityChecker.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.types + +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext +import org.jetbrains.kotlin.types.typeUtil.* + +fun checkEnumsForCompatibility(context: ExpressionTypingContext, reportOn: KtElement, typeA: KotlinType, typeB: KotlinType) { + if (isIncompatibleEnums(typeA, typeB)) { + val diagnostic = if (context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitComparisonOfIncompatibleEnums)) { + Errors.INCOMPATIBLE_ENUM_COMPARISON_ERROR + } else { + Errors.INCOMPATIBLE_ENUM_COMPARISON + } + + context.trace.report(diagnostic.on(reportOn, typeA, typeB)) + } +} + +private fun isIncompatibleEnums(typeA: KotlinType, typeB: KotlinType): Boolean { + if (!typeA.isEnum() && !typeB.isEnum()) return false + if (TypeUtils.isNullableType(typeA) && TypeUtils.isNullableType(typeB)) return false + + // TODO: remove this line once KT-30266 will be fixed + // For now, this check is needed as isSubClass contains bug wrt Nothing + if (typeA.isNothingOrNullableNothing() || typeB.isNothingOrNullableNothing()) return false + + val representativeTypeA = typeA.representativeTypeForTypeParameter() + val representativeTypeB = typeB.representativeTypeForTypeParameter() + + val classA = representativeTypeA.constructor.declarationDescriptor as? ClassDescriptor ?: return false + val classB = representativeTypeB.constructor.declarationDescriptor as? ClassDescriptor ?: return false + + return !DescriptorUtils.isSubclass(classA, classB) && !DescriptorUtils.isSubclass(classB, classA) +} + +private fun KotlinType.representativeTypeForTypeParameter(): KotlinType { + val descriptor = constructor.declarationDescriptor + return if (descriptor is TypeParameterDescriptor) descriptor.representativeUpperBound else this +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index 1aa940ff059..084381c0d47 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -1430,10 +1430,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { if (rightType != null) { if (TypeIntersector.isIntersectionEmpty(leftType, rightType)) { context.trace.report(EQUALITY_NOT_APPLICABLE.on(expression, expression.getOperationReference(), leftType, rightType)); + } else { + EnumCompatibilityCheckerKt.checkEnumsForCompatibility(context, expression, leftType, rightType); } - else if (TypeIntersector.isIncompatibleEnums(leftType, rightType)) { - context.trace.report(INCOMPATIBLE_ENUM_COMPARISON.on(expression, leftType, rightType)); - } + SenselessComparisonChecker.checkSenselessComparisonWithNull( expression, left, right, context, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt index 743f4fb4d01..a66225e067a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt @@ -684,9 +684,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping return } - if (TypeIntersector.isIncompatibleEnums(type, subjectType)) { - context.trace.report(INCOMPATIBLE_ENUM_COMPARISON.on(reportErrorOn, subjectType, type)) - } + checkEnumsForCompatibility(context, reportErrorOn, type, subjectType) // check if the pattern is essentially a 'null' expression if (KotlinBuiltIns.isNullableNothing(type) && !TypeUtils.isNullableType(subjectType)) { diff --git a/compiler/testData/diagnostics/tests/enum/incompatibleEnums.kt b/compiler/testData/diagnostics/tests/enum/incompatibleEnums.kt index 7be3faad7b1..784285f7a82 100644 --- a/compiler/testData/diagnostics/tests/enum/incompatibleEnums.kt +++ b/compiler/testData/diagnostics/tests/enum/incompatibleEnums.kt @@ -1,3 +1,5 @@ +// !LANGUAGE: -ProhibitComparisonOfIncompatibleEnums + enum class E1 { A, B } @@ -56,3 +58,88 @@ fun foo3(e1: Enum, e2: Enum, e: Enum<*>) { else -> {} } } + +interface MyInterface +open class MyOpenClass + +fun foo4(e1: E1, i: MyInterface, c: MyOpenClass) { + e1 == i + i == e1 + + e1 == c + c == e1 + + when (e1) { + i -> {} + c -> {} + else -> {} + } +} + +enum class E3 : MyInterface { X, Y } + +fun foo5(i: MyInterface, a: Any) { + E3.X == E3.Y + E3.X == i + E3.X == a +} + +fun foo6(e1: E1?, e2: E2) { + E1.A == null + null == E1.A + e1 == null + null == e1 + + e1 == E2.A + E2.A == e1 + e1 == e2 + e2 == e1 + + e2 == null + null == e2 + E1.A == null + null == E1.A +} + +fun foo7(e1: E1?, e2: E2?) { + e1 == e2 // There should be an IDE-inspection for such cases +} + +fun foo8(e1: E1?, e2: E2, t: T) { + e1 == t + t == e1 + + e2 == t + t == e2 + + E1.A == t + t == E1.A +} + +fun foo9(e1: E1?, e2: E2, t: T, k: K) where T : MyInterface, T : MyOpenClass, K : MyInterface { + e1 == t + t == e1 + + e2 == t + t == e2 + + E1.A == t + t == E1.A + + E3.X == t + + E3.X == k + k == E3.X +} + +interface Inv + +enum class E4 : Inv { A } + +fun foo10(e4: E4, invString: Inv) { + e4 == invString + invString == e4 + + E4.A == invString + invString == E4.A +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/enum/incompatibleEnums.txt b/compiler/testData/diagnostics/tests/enum/incompatibleEnums.txt index 33d652b54a3..5e46d9fc2e5 100644 --- a/compiler/testData/diagnostics/tests/enum/incompatibleEnums.txt +++ b/compiler/testData/diagnostics/tests/enum/incompatibleEnums.txt @@ -1,8 +1,15 @@ package public fun foo1(/*0*/ e1: E1, /*1*/ e2: E2): kotlin.Unit +public fun foo10(/*0*/ e4: E4, /*1*/ invString: Inv): kotlin.Unit public fun foo2(/*0*/ e1: E1, /*1*/ e2: E2): kotlin.Unit public fun foo3(/*0*/ e1: kotlin.Enum, /*1*/ e2: kotlin.Enum, /*2*/ e: kotlin.Enum<*>): kotlin.Unit +public fun foo4(/*0*/ e1: E1, /*1*/ i: MyInterface, /*2*/ c: MyOpenClass): kotlin.Unit +public fun foo5(/*0*/ i: MyInterface, /*1*/ a: kotlin.Any): kotlin.Unit +public fun foo6(/*0*/ e1: E1?, /*1*/ e2: E2): kotlin.Unit +public fun foo7(/*0*/ e1: E1?, /*1*/ e2: E2?): kotlin.Unit +public fun foo8(/*0*/ e1: E1?, /*1*/ e2: E2, /*2*/ t: T): kotlin.Unit +public fun foo9(/*0*/ e1: E1?, /*1*/ e2: E2, /*2*/ t: T, /*3*/ k: K): kotlin.Unit where T : MyOpenClass public final enum class E1 : kotlin.Enum { enum entry A @@ -45,3 +52,62 @@ public final enum class E2 : kotlin.Enum { public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E2 public final /*synthesized*/ fun values(): kotlin.Array } + +public final enum class E3 : kotlin.Enum, MyInterface { + enum entry X + + enum entry Y + + private constructor E3() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E3): kotlin.Int + public final override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + public final override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E3 + public final /*synthesized*/ fun values(): kotlin.Array +} + +public final enum class E4 : kotlin.Enum, Inv { + enum entry A + + private constructor E4() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E4): kotlin.Int + public final override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + public final override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E4 + public final /*synthesized*/ fun values(): kotlin.Array +} + +public interface Inv { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface MyInterface { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public open class MyOpenClass { + public constructor MyOpenClass() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/enum/incompatibleEnums_1_4.kt b/compiler/testData/diagnostics/tests/enum/incompatibleEnums_1_4.kt new file mode 100644 index 00000000000..ad4afd7ec6a --- /dev/null +++ b/compiler/testData/diagnostics/tests/enum/incompatibleEnums_1_4.kt @@ -0,0 +1,145 @@ +// !LANGUAGE: +ProhibitComparisonOfIncompatibleEnums + +enum class E1 { + A, B +} + +enum class E2 { + A, B +} + +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 -> {} + } +} + +interface MyInterface +open class MyOpenClass + +fun foo4(e1: E1, i: MyInterface, c: MyOpenClass) { + e1 == i + i == e1 + + e1 == c + c == e1 + + when (e1) { + i -> {} + c -> {} + else -> {} + } +} + +enum class E3 : MyInterface { X, Y } + +fun foo5(i: MyInterface, a: Any) { + E3.X == E3.Y + E3.X == i + E3.X == a +} + +fun foo6(e1: E1?, e2: E2) { + E1.A == null + null == E1.A + e1 == null + null == e1 + + e1 == E2.A + E2.A == e1 + e1 == e2 + e2 == e1 + + e2 == null + null == e2 + E1.A == null + null == E1.A +} + +fun foo7(e1: E1?, e2: E2?) { + e1 == e2 // There should be an IDE-inspection for such cases +} + +fun foo8(e1: E1?, e2: E2, t: T) { + e1 == t + t == e1 + + e2 == t + t == e2 + + E1.A == t + t == E1.A +} + +fun foo9(e1: E1?, e2: E2, t: T, k: K) where T : MyInterface, T : MyOpenClass, K : MyInterface { + e1 == t + t == e1 + + e2 == t + t == e2 + + E1.A == t + t == E1.A + + E3.X == t + + E3.X == k + k == E3.X +} + +interface Inv + +enum class E4 : Inv { A } + +fun foo10(e4: E4, invString: Inv) { + e4 == invString + invString == e4 + + E4.A == invString + invString == E4.A +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/enum/incompatibleEnums_1_4.txt b/compiler/testData/diagnostics/tests/enum/incompatibleEnums_1_4.txt new file mode 100644 index 00000000000..5e46d9fc2e5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/enum/incompatibleEnums_1_4.txt @@ -0,0 +1,113 @@ +package + +public fun foo1(/*0*/ e1: E1, /*1*/ e2: E2): kotlin.Unit +public fun foo10(/*0*/ e4: E4, /*1*/ invString: Inv): kotlin.Unit +public fun foo2(/*0*/ e1: E1, /*1*/ e2: E2): kotlin.Unit +public fun foo3(/*0*/ e1: kotlin.Enum, /*1*/ e2: kotlin.Enum, /*2*/ e: kotlin.Enum<*>): kotlin.Unit +public fun foo4(/*0*/ e1: E1, /*1*/ i: MyInterface, /*2*/ c: MyOpenClass): kotlin.Unit +public fun foo5(/*0*/ i: MyInterface, /*1*/ a: kotlin.Any): kotlin.Unit +public fun foo6(/*0*/ e1: E1?, /*1*/ e2: E2): kotlin.Unit +public fun foo7(/*0*/ e1: E1?, /*1*/ e2: E2?): kotlin.Unit +public fun foo8(/*0*/ e1: E1?, /*1*/ e2: E2, /*2*/ t: T): kotlin.Unit +public fun foo9(/*0*/ e1: E1?, /*1*/ e2: E2, /*2*/ t: T, /*3*/ k: K): kotlin.Unit where T : MyOpenClass + +public final enum class E1 : kotlin.Enum { + enum entry A + + enum entry B + + private constructor E1() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E1): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E1 + public final /*synthesized*/ fun values(): kotlin.Array +} + +public final enum class E2 : kotlin.Enum { + enum entry A + + enum entry B + + private constructor E2() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E2): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E2 + public final /*synthesized*/ fun values(): kotlin.Array +} + +public final enum class E3 : kotlin.Enum, MyInterface { + enum entry X + + enum entry Y + + private constructor E3() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E3): kotlin.Int + public final override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + public final override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E3 + public final /*synthesized*/ fun values(): kotlin.Array +} + +public final enum class E4 : kotlin.Enum, Inv { + enum entry A + + private constructor E4() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E4): kotlin.Int + public final override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + public final override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E4 + public final /*synthesized*/ fun values(): kotlin.Array +} + +public interface Inv { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface MyInterface { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public open class MyOpenClass { + public constructor MyOpenClass() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 98b7ccd5d6c..7aa173791f7 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -6943,6 +6943,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/enum/incompatibleEnums.kt"); } + @TestMetadata("incompatibleEnums_1_4.kt") + public void testIncompatibleEnums_1_4() throws Exception { + runTest("compiler/testData/diagnostics/tests/enum/incompatibleEnums_1_4.kt"); + } + @TestMetadata("inheritFromEnumEntry.kt") public void testInheritFromEnumEntry() throws Exception { runTest("compiler/testData/diagnostics/tests/enum/inheritFromEnumEntry.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 7d1c2d9e990..96e3b60f822 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -6938,6 +6938,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/enum/incompatibleEnums.kt"); } + @TestMetadata("incompatibleEnums_1_4.kt") + public void testIncompatibleEnums_1_4() throws Exception { + runTest("compiler/testData/diagnostics/tests/enum/incompatibleEnums_1_4.kt"); + } + @TestMetadata("inheritFromEnumEntry.kt") public void testInheritFromEnumEntry() throws Exception { runTest("compiler/testData/diagnostics/tests/enum/inheritFromEnumEntry.kt"); diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index e9b077bd465..d9da258ca42 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -101,6 +101,7 @@ enum class LanguageFeature( ProhibitRepeatedUseSiteTargetAnnotations(KOTLIN_1_4, kind = BUG_FIX), ProhibitUseSiteTargetAnnotationsOnSuperTypes(KOTLIN_1_4, kind = BUG_FIX), ProhibitTypeParametersInClassLiteralsInAnnotationArguments(KOTLIN_1_4, kind = BUG_FIX), + ProhibitComparisonOfIncompatibleEnums(KOTLIN_1_4, kind = BUG_FIX), ProperVisibilityForCompanionObjectInstanceField(sinceVersion = null, kind = BUG_FIX), // Temporarily disabled, see KT-27084/KT-22379 diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt index ac900d95a39..6a648da508e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt @@ -54,6 +54,7 @@ fun KotlinType.supertypes(): Collection = TypeUtils.getAllSupertypes fun KotlinType.isNothing(): Boolean = KotlinBuiltIns.isNothing(this) fun KotlinType.isNullableNothing(): Boolean = KotlinBuiltIns.isNullableNothing(this) +fun KotlinType.isNothingOrNullableNothing(): Boolean = KotlinBuiltIns.isNothingOrNullableNothing(this) fun KotlinType.isUnit(): Boolean = KotlinBuiltIns.isUnit(this) fun KotlinType.isAnyOrNullableAny(): Boolean = KotlinBuiltIns.isAnyOrNullableAny(this) fun KotlinType.isNullableAny(): Boolean = KotlinBuiltIns.isNullableAny(this)