Make TypeConstructor.isFinal return false for enums
The reason is that beforedc02b2e3aband8a0dcca957, TypeConstructor.isFinal for some class descriptors (DeserializedClassDescriptor, LazyJavaClassDescriptor, MutableClassDescriptor) were implemented as `isFinalClass` (which is `modality == FINAL && kind != ENUM_CLASS`), and all others as `modality == FINAL` or simply true/false. This led to differences in behavior depending on the exact instance of the class descriptor. Now that TypeConstructor.isFinal is always `modality == FINAL`, some tests (PseudoValueTestGenerated) fail because the finality of some type constructors changed and these tests render final vs non-final type constructors differently. In this commit, TypeConstructor.isFinal is now made to behave safer, i.e. considering enum class type constructor to be non-final (as was the case earlier for some ClassDescriptor instances). Some diagnostics might disappear (e.g. FINAL_UPPER_BOUND) but it doesn't look like a big deal
This commit is contained in:
@@ -3,10 +3,10 @@ enum class Direction {
|
||||
NORTH, SOUTH, WEST, EAST
|
||||
}
|
||||
---------------------
|
||||
<v0>: Direction NEW: magic[FAKE_INITIALIZER](NORTH,) -> <v0>
|
||||
<v1>: Direction NEW: magic[FAKE_INITIALIZER](SOUTH,) -> <v1>
|
||||
<v2>: Direction NEW: magic[FAKE_INITIALIZER](WEST,) -> <v2>
|
||||
<v3>: Direction NEW: magic[FAKE_INITIALIZER](EAST) -> <v3>
|
||||
<v0>: {<: Direction} NEW: magic[FAKE_INITIALIZER](NORTH,) -> <v0>
|
||||
<v1>: {<: Direction} NEW: magic[FAKE_INITIALIZER](SOUTH,) -> <v1>
|
||||
<v2>: {<: Direction} NEW: magic[FAKE_INITIALIZER](WEST,) -> <v2>
|
||||
<v3>: {<: Direction} NEW: magic[FAKE_INITIALIZER](EAST) -> <v3>
|
||||
=====================
|
||||
== foo ==
|
||||
fun foo(dir: Direction): Int {
|
||||
@@ -20,31 +20,31 @@ fun foo(dir: Direction): Int {
|
||||
return res
|
||||
}
|
||||
---------------------
|
||||
<v0>: Direction NEW: magic[FAKE_INITIALIZER](dir: Direction) -> <v0>
|
||||
<v14>: * NEW: magic[EXHAUSTIVE_WHEN_ELSE](when (dir) { Direction.NORTH -> res = 1 Direction.SOUTH -> res = 2 Direction.WEST -> res = 3 Direction.EAST -> res = 4 }) -> <v14>
|
||||
dir <v1>: * NEW: r(dir) -> <v1>
|
||||
NORTH <v2>: * NEW: r(NORTH) -> <v2>
|
||||
Direction.NORTH <v2>: * COPY
|
||||
Direction.NORTH <v3>: * NEW: magic[EQUALS_IN_WHEN_CONDITION](Direction.NORTH|<v1>, <v2>) -> <v3>
|
||||
1 <v4>: Int NEW: r(1) -> <v4>
|
||||
<v0>: {<: Direction} NEW: magic[FAKE_INITIALIZER](dir: Direction) -> <v0>
|
||||
<v14>: * NEW: magic[EXHAUSTIVE_WHEN_ELSE](when (dir) { Direction.NORTH -> res = 1 Direction.SOUTH -> res = 2 Direction.WEST -> res = 3 Direction.EAST -> res = 4 }) -> <v14>
|
||||
dir <v1>: * NEW: r(dir) -> <v1>
|
||||
NORTH <v2>: * NEW: r(NORTH) -> <v2>
|
||||
Direction.NORTH <v2>: * COPY
|
||||
Direction.NORTH <v3>: * NEW: magic[EQUALS_IN_WHEN_CONDITION](Direction.NORTH|<v1>, <v2>) -> <v3>
|
||||
1 <v4>: Int NEW: r(1) -> <v4>
|
||||
res = 1 !<v15>: *
|
||||
SOUTH <v5>: * NEW: r(SOUTH) -> <v5>
|
||||
Direction.SOUTH <v5>: * COPY
|
||||
Direction.SOUTH <v6>: * NEW: magic[EQUALS_IN_WHEN_CONDITION](Direction.SOUTH|<v1>, <v5>) -> <v6>
|
||||
2 <v7>: Int NEW: r(2) -> <v7>
|
||||
SOUTH <v5>: * NEW: r(SOUTH) -> <v5>
|
||||
Direction.SOUTH <v5>: * COPY
|
||||
Direction.SOUTH <v6>: * NEW: magic[EQUALS_IN_WHEN_CONDITION](Direction.SOUTH|<v1>, <v5>) -> <v6>
|
||||
2 <v7>: Int NEW: r(2) -> <v7>
|
||||
res = 2 !<v16>: *
|
||||
WEST <v8>: * NEW: r(WEST) -> <v8>
|
||||
Direction.WEST <v8>: * COPY
|
||||
Direction.WEST <v9>: * NEW: magic[EQUALS_IN_WHEN_CONDITION](Direction.WEST|<v1>, <v8>) -> <v9>
|
||||
3 <v10>: Int NEW: r(3) -> <v10>
|
||||
WEST <v8>: * NEW: r(WEST) -> <v8>
|
||||
Direction.WEST <v8>: * COPY
|
||||
Direction.WEST <v9>: * NEW: magic[EQUALS_IN_WHEN_CONDITION](Direction.WEST|<v1>, <v8>) -> <v9>
|
||||
3 <v10>: Int NEW: r(3) -> <v10>
|
||||
res = 3 !<v17>: *
|
||||
EAST <v11>: * NEW: r(EAST) -> <v11>
|
||||
Direction.EAST <v11>: * COPY
|
||||
Direction.EAST <v12>: * NEW: magic[EQUALS_IN_WHEN_CONDITION](Direction.EAST|<v1>, <v11>) -> <v12>
|
||||
4 <v13>: Int NEW: r(4) -> <v13>
|
||||
EAST <v11>: * NEW: r(EAST) -> <v11>
|
||||
Direction.EAST <v11>: * COPY
|
||||
Direction.EAST <v12>: * NEW: magic[EQUALS_IN_WHEN_CONDITION](Direction.EAST|<v1>, <v11>) -> <v12>
|
||||
4 <v13>: Int NEW: r(4) -> <v13>
|
||||
res = 4 !<v18>: *
|
||||
when (dir) { Direction.NORTH -> res = 1 Direction.SOUTH -> res = 2 Direction.WEST -> res = 3 Direction.EAST -> res = 4 } <v19>: * NEW: merge(when (dir) { Direction.NORTH -> res = 1 Direction.SOUTH -> res = 2 Direction.WEST -> res = 3 Direction.EAST -> res = 4 }|!<v15>, !<v16>, !<v17>, !<v18>) -> <v19>
|
||||
res <v20>: Int NEW: r(res) -> <v20>
|
||||
when (dir) { Direction.NORTH -> res = 1 Direction.SOUTH -> res = 2 Direction.WEST -> res = 3 Direction.EAST -> res = 4 } <v19>: * NEW: merge(when (dir) { Direction.NORTH -> res = 1 Direction.SOUTH -> res = 2 Direction.WEST -> res = 3 Direction.EAST -> res = 4 }|!<v15>, !<v16>, !<v17>, !<v18>) -> <v19>
|
||||
res <v20>: Int NEW: r(res) -> <v20>
|
||||
return res !<v21>: *
|
||||
{ val res: Int when (dir) { Direction.NORTH -> res = 1 Direction.SOUTH -> res = 2 Direction.WEST -> res = 3 Direction.EAST -> res = 4 } return res } !<v21>: * COPY
|
||||
{ val res: Int when (dir) { Direction.NORTH -> res = 1 Direction.SOUTH -> res = 2 Direction.WEST -> res = 3 Direction.EAST -> res = 4 } return res } !<v21>: * COPY
|
||||
=====================
|
||||
|
||||
+2
-2
@@ -10,8 +10,8 @@ enum class EE(val x: Int) {
|
||||
---------------------
|
||||
<v0>: Int NEW: magic[FAKE_INITIALIZER](val x: Int) -> <v0>
|
||||
<v10>: EE.Companion NEW: magic[FAKE_INITIALIZER](companion object { fun foo() = 42 }) -> <v10>
|
||||
<v1>: EE NEW: magic[FAKE_INITIALIZER](INSTANCE(Companion.foo()),) -> <v1>
|
||||
<v5>: EE NEW: magic[FAKE_INITIALIZER](ANOTHER(foo());) -> <v5>
|
||||
<v1>: {<: EE} NEW: magic[FAKE_INITIALIZER](INSTANCE(Companion.foo()),) -> <v1>
|
||||
<v5>: {<: EE} NEW: magic[FAKE_INITIALIZER](ANOTHER(foo());) -> <v5>
|
||||
<v7>: EE.Companion NEW: magic[IMPLICIT_RECEIVER](foo()) -> <v7>
|
||||
Companion <v2>: EE.Companion NEW: r(Companion) -> <v2>
|
||||
foo() <v3>: Int NEW: call(foo(), foo|<v2>) -> <v3>
|
||||
|
||||
+5
-5
@@ -10,10 +10,10 @@ enum class E(val x: Int) {
|
||||
E1(0)
|
||||
}
|
||||
---------------------
|
||||
<v0>: Int NEW: magic[FAKE_INITIALIZER](val x: Int) -> <v0>
|
||||
<v1>: E NEW: magic[FAKE_INITIALIZER](E1(0)) -> <v1>
|
||||
0 <v2>: Int NEW: r(0) -> <v2>
|
||||
(0) <v3>: * NEW: call((0), <init>|<v2>) -> <v3>
|
||||
<v0>: Int NEW: magic[FAKE_INITIALIZER](val x: Int) -> <v0>
|
||||
<v1>: {<: E} NEW: magic[FAKE_INITIALIZER](E1(0)) -> <v1>
|
||||
0 <v2>: Int NEW: r(0) -> <v2>
|
||||
(0) <v3>: * NEW: call((0), <init>|<v2>) -> <v3>
|
||||
=====================
|
||||
== C ==
|
||||
class C {
|
||||
@@ -26,7 +26,7 @@ class C {
|
||||
== foo ==
|
||||
fun foo() = E1.x + O.y + C.z
|
||||
---------------------
|
||||
E1 <v0>: E NEW: r(E1) -> <v0>
|
||||
E1 <v0>: {<: E} NEW: r(E1) -> <v0>
|
||||
x <v1>: Int NEW: r(x|<v0>) -> <v1>
|
||||
E1.x <v1>: Int COPY
|
||||
O <v2>: O NEW: r(O) -> <v2>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// 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) = a == b
|
||||
fun jk(a: JavaEnumA, b: KotlinEnumB) = a == b
|
||||
fun kk(a: KotlinEnumA, b: KotlinEnumB) = a == b
|
||||
@@ -0,0 +1,73 @@
|
||||
package
|
||||
|
||||
public fun jj(/*0*/ a: JavaEnumA, /*1*/ b: JavaEnumB): kotlin.Boolean
|
||||
public fun jk(/*0*/ a: JavaEnumA, /*1*/ b: KotlinEnumB): kotlin.Boolean
|
||||
public fun kk(/*0*/ a: KotlinEnumA, /*1*/ b: KotlinEnumB): kotlin.Boolean
|
||||
|
||||
public final enum class JavaEnumA : kotlin.Enum<JavaEnumA!> {
|
||||
public constructor JavaEnumA()
|
||||
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: JavaEnumA!): 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<JavaEnumA!>!
|
||||
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): JavaEnumA
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<JavaEnumA>
|
||||
}
|
||||
|
||||
public final enum class JavaEnumB : kotlin.Enum<JavaEnumB!> {
|
||||
public constructor JavaEnumB()
|
||||
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: JavaEnumB!): 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<JavaEnumB!>!
|
||||
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): JavaEnumB
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<JavaEnumB>
|
||||
}
|
||||
|
||||
public final enum class KotlinEnumA : kotlin.Enum<KotlinEnumA> {
|
||||
private constructor KotlinEnumA()
|
||||
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: KotlinEnumA): 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<KotlinEnumA!>!
|
||||
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): KotlinEnumA
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<KotlinEnumA>
|
||||
}
|
||||
|
||||
public final enum class KotlinEnumB : kotlin.Enum<KotlinEnumB> {
|
||||
private constructor KotlinEnumB()
|
||||
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: KotlinEnumB): 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<KotlinEnumB!>!
|
||||
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): KotlinEnumB
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<KotlinEnumB>
|
||||
}
|
||||
+1
-1
@@ -12,7 +12,7 @@ fun <T> f2() where T : C2, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>C3<!> {}
|
||||
fun <T> f3() where T : C3, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>C2<!> {}
|
||||
|
||||
enum class E1
|
||||
class A5<<!CONFLICTING_UPPER_BOUNDS!>T<!>> where T : C1, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED, FINAL_UPPER_BOUND!>E1<!>
|
||||
class A5<T> where T : C1, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>E1<!>
|
||||
|
||||
object O1
|
||||
class A6<<!CONFLICTING_UPPER_BOUNDS!>T<!>> where T : <!FINAL_UPPER_BOUND!>O1<!>, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>C2<!>
|
||||
|
||||
@@ -7411,6 +7411,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compareTwoDifferentEnums.kt")
|
||||
public void testCompareTwoDifferentEnums() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ConstructorCallFromOutside.kt")
|
||||
public void testConstructorCallFromOutside() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/enum/ConstructorCallFromOutside.kt");
|
||||
|
||||
+6
@@ -7411,6 +7411,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compareTwoDifferentEnums.kt")
|
||||
public void testCompareTwoDifferentEnums() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/enum/compareTwoDifferentEnums.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ConstructorCallFromOutside.kt")
|
||||
public void testConstructorCallFromOutside() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/enum/ConstructorCallFromOutside.kt");
|
||||
|
||||
@@ -56,7 +56,7 @@ public abstract class AbstractClassTypeConstructor extends AbstractTypeConstruct
|
||||
@Override
|
||||
public final boolean isFinal() {
|
||||
ClassDescriptor descriptor = getDeclarationDescriptor();
|
||||
return descriptor.getModality() == Modality.FINAL && !descriptor.isExpect();
|
||||
return ModalityKt.isFinalClass(descriptor) && !descriptor.isExpect();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
Reference in New Issue
Block a user