FIR: add equality call checker

Added checker for FirEqualityOperatorCall. It's surfaced as one of the
following diagnostics depending on the PSI structure and types under
comparison:

* INCOMPATIBLE_TYPES(_WARNING)
* EQUALITY_NOT_APPLICABLE(_WARNING)
* INCOMPATIBLE_ENUM_COMPARISON_ERROR

Comparing with FE1.0, the current implementation is more conservative
and only highlights error if the types are known to follow certain
contracts with `equals` method. Otherwise, the checker reports warnings
instead.

However, the current checker is more strict in the following situations:
1. it now rejects incompatible enum types like `Enum<E1>` and
  `Enum<E2>`, which was previously accepted
2. it now rejects incompatible class types like `Class<String>` and
  `Class<Int>`, which was previously accepted
3. the check now takes smart cast into consideration, so
  `if (x is String) x == 3` is now rejected
This commit is contained in:
Tianyu Geng
2021-04-02 20:49:50 -07:00
committed by teamcityserver
parent 787c743333
commit 7bb81ef157
43 changed files with 1218 additions and 188 deletions
@@ -12,6 +12,6 @@ public enum JavaEnumB {}
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
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<!>
@@ -32,8 +32,8 @@ fun useEn2(x: En2) = x
fun bar(x: Any) {
if (x is En && x is En2) {
when (x) {
En.A -> useEn(x)
En2.D -> useEn2(x)
<!INCOMPATIBLE_TYPES!>En.A<!> -> useEn(x)
<!INCOMPATIBLE_TYPES!>En2.D<!> -> useEn2(x)
else -> {}
}
}
@@ -7,15 +7,15 @@ interface I {
enum class E1 : I {
A {
override fun foo() {
this == E2.A
<!EQUALITY_NOT_APPLICABLE_WARNING!>this == E2.A<!>
val q = this
when (q) {
this -> {}
E1.A -> {}
E1.B -> {}
E2.A -> {}
E2.B -> {}
<!INCOMPATIBLE_TYPES_WARNING!>E2.A<!> -> {}
<!INCOMPATIBLE_TYPES_WARNING!>E2.B<!> -> {}
else -> {}
}
}
@@ -41,13 +41,13 @@ enum class E2 : I {
}
fun foo1(e1: E1, e2: E2) {
e1 == e2
e1 != e2
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == e2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 != e2<!>
e1 == E2.A
E1.B == e2
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == E2.A<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>E1.B == e2<!>
E1.A == E2.B
<!EQUALITY_NOT_APPLICABLE_WARNING!>E1.A == E2.B<!>
e1 == E1.A
E1.A == e1
@@ -58,27 +58,27 @@ fun foo1(e1: E1, e2: E2) {
fun foo2(e1: E1, e2: E2) {
when (e1) {
E1.A -> {}
E2.A -> {}
E2.B -> {}
<!INCOMPATIBLE_TYPES_WARNING!>E2.A<!> -> {}
<!INCOMPATIBLE_TYPES_WARNING!>E2.B<!> -> {}
e1 -> {}
e2 -> {}
<!INCOMPATIBLE_TYPES_WARNING!>e2<!> -> {}
else -> {}
}
}
fun foo3(e1: Enum<E1>, e2: Enum<E2>, e: Enum<*>) {
e1 == e
e1 == e2
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == e2<!>
e1 == E1.A
e1 == E2.A
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == E2.A<!>
when (e1) {
e1 -> {}
e2 -> {}
<!INCOMPATIBLE_TYPES_WARNING!>e2<!> -> {}
e -> {}
E1.A -> {}
E2.A -> {}
<!INCOMPATIBLE_TYPES_WARNING!>E2.A<!> -> {}
else -> {}
}
@@ -9,13 +9,13 @@ enum class E2 {
}
fun foo1(e1: E1, e2: E2) {
e1 == e2
e1 != e2
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == e2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 != e2<!>
e1 == E2.A
E1.B == e2
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == E2.A<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>E1.B == e2<!>
E1.A == E2.B
<!EQUALITY_NOT_APPLICABLE_WARNING!>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 -> {}
E2.A -> {}
E2.B -> {}
<!INCOMPATIBLE_TYPES_WARNING!>E2.A<!> -> {}
<!INCOMPATIBLE_TYPES_WARNING!>E2.B<!> -> {}
e1 -> {}
e2 -> {}
<!INCOMPATIBLE_TYPES_WARNING!>e2<!> -> {}
else -> {}
}
}
fun foo3(e1: Enum<E1>, e2: Enum<E2>, e: Enum<*>) {
e1 == e
e1 == e2
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == e2<!>
e1 == E1.A
e1 == E2.A
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == E2.A<!>
when (e1) {
e1 -> {}
e2 -> {}
<!INCOMPATIBLE_TYPES_WARNING!>e2<!> -> {}
e -> {}
E1.A -> {}
E2.A -> {}
<!INCOMPATIBLE_TYPES_WARNING!>E2.A<!> -> {}
else -> {}
}
@@ -63,15 +63,15 @@ interface MyInterface
open class MyOpenClass
fun foo4(e1: E1, i: MyInterface, c: MyOpenClass) {
e1 == i
i == e1
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == i<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>i == e1<!>
e1 == c
c == e1
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == c<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>c == e1<!>
when (e1) {
i -> {}
c -> {}
<!INCOMPATIBLE_TYPES_WARNING!>i<!> -> {}
<!INCOMPATIBLE_TYPES_WARNING!>c<!> -> {}
else -> {}
}
}
@@ -90,10 +90,10 @@ fun foo6(e1: E1?, e2: E2) {
e1 == null
null == e1
e1 == E2.A
E2.A == e1
e1 == e2
e2 == 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<!>
e2 == null
null == e2
@@ -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 {
e1 == t
t == e1
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == t<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>t == e1<!>
e2 == t
t == e2
<!EQUALITY_NOT_APPLICABLE_WARNING!>e2 == t<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>t == e2<!>
E1.A == t
t == E1.A
<!EQUALITY_NOT_APPLICABLE_WARNING!>E1.A == t<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>t == E1.A<!>
E3.X == t
<!EQUALITY_NOT_APPLICABLE_WARNING!>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>) {
e4 == invString
invString == e4
<!EQUALITY_NOT_APPLICABLE_WARNING!>e4 == invString<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>invString == e4<!>
E4.A == invString
invString == E4.A
}
<!EQUALITY_NOT_APPLICABLE_WARNING!>E4.A == invString<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>invString == E4.A<!>
}
@@ -9,13 +9,13 @@ enum class E2 {
}
fun foo1(e1: E1, e2: E2) {
e1 == e2
e1 != e2
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>e1 == e2<!>
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>e1 != e2<!>
e1 == E2.A
E1.B == e2
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>e1 == E2.A<!>
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>E1.B == e2<!>
E1.A == E2.B
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>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 -> {}
E2.A -> {}
E2.B -> {}
<!INCOMPATIBLE_TYPES!>E2.A<!> -> {}
<!INCOMPATIBLE_TYPES!>E2.B<!> -> {}
e1 -> {}
e2 -> {}
<!INCOMPATIBLE_TYPES!>e2<!> -> {}
else -> {}
}
}
fun foo3(e1: Enum<E1>, e2: Enum<E2>, e: Enum<*>) {
e1 == e
e1 == e2
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>e1 == e2<!>
e1 == E1.A
e1 == E2.A
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>e1 == E2.A<!>
when (e1) {
e1 -> {}
e2 -> {}
<!INCOMPATIBLE_TYPES!>e2<!> -> {}
e -> {}
E1.A -> {}
E2.A -> {}
<!INCOMPATIBLE_TYPES!>E2.A<!> -> {}
else -> {}
}
@@ -63,15 +63,15 @@ interface MyInterface
open class MyOpenClass
fun foo4(e1: E1, i: MyInterface, c: MyOpenClass) {
e1 == i
i == e1
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>e1 == i<!>
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>i == e1<!>
e1 == c
c == e1
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>e1 == c<!>
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>c == e1<!>
when (e1) {
i -> {}
c -> {}
<!INCOMPATIBLE_TYPES!>i<!> -> {}
<!INCOMPATIBLE_TYPES!>c<!> -> {}
else -> {}
}
}
@@ -90,10 +90,10 @@ fun foo6(e1: E1?, e2: E2) {
e1 == null
null == e1
e1 == E2.A
E2.A == e1
e1 == e2
e2 == e1
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>e1 == E2.A<!>
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>E2.A == e1<!>
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>e1 == e2<!>
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>e2 == e1<!>
e2 == null
null == e2
@@ -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 {
e1 == t
t == e1
<!EQUALITY_NOT_APPLICABLE_WARNING!>e1 == t<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>t == e1<!>
e2 == t
t == e2
<!EQUALITY_NOT_APPLICABLE_WARNING!>e2 == t<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>t == e2<!>
E1.A == t
t == E1.A
<!EQUALITY_NOT_APPLICABLE_WARNING!>E1.A == t<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>t == E1.A<!>
E3.X == t
<!EQUALITY_NOT_APPLICABLE_WARNING!>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>) {
e4 == invString
invString == e4
<!EQUALITY_NOT_APPLICABLE_WARNING!>e4 == invString<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>invString == e4<!>
E4.A == invString
invString == E4.A
}
<!EQUALITY_NOT_APPLICABLE_WARNING!>E4.A == invString<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>invString == E4.A<!>
}
@@ -0,0 +1,97 @@
class A<T>
class AIn<in T>
class AOut<out T>
class A2
open class B<T>
open class BIn<in T>
open class BOut<out T>
open class C
open class D
enum class E
interface I
interface T<T>
open class TSub1 : T<String>
open class TSub2 : T<Int>
fun foo(
string: String, int: Int,
strings: List<String>, ints: List<Int>,
aString: A<String>, aInt: A<Int>,
aOutString: A<out String>, aOutInt: A<out Int>,
aOutString2: AOut<String>, aOutInt2: AOut<Int>,
aInString: A<in String>, aInInt: A<in Int>,
aInString2: AIn<String>, aInInt2: AIn<Int>,
bString: B<String>, bInt: B<Int>,
bOutString: B<out String>, bOutInt: B<out Int>,
bOutString2: BOut<String>, bOutInt2: BOut<Int>,
bInString: B<in String>, bInInt: B<in Int>,
bInString2: BIn<String>, bInInt2: BIn<Int>,
a2: A2,
e: E,
i: I,
ac: A<C>, ad: A<D>,
tSub1: TSub1,
tSub2: TSub2,
aListInt: A<List<Int>>,
aSetInt: A<Set<Int>>,
aListString: A<List<String>>,
) {
"a" == "b"
1 == 2
<!EQUALITY_NOT_APPLICABLE!>"" == 2<!>
<!EQUALITY_NOT_APPLICABLE!>string == int<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>strings == ints<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aString == aInt<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>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<!>
aInString2 == aInInt2
<!EQUALITY_NOT_APPLICABLE_WARNING!>aOutString2 == aInInt2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aInString2 == aOutInt2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aString == a2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>bString == bInt<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>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<!>
bInString2 == bInInt2
<!EQUALITY_NOT_APPLICABLE_WARNING!>bOutString2 == bInInt2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>bInString2 == bOutInt2<!>
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>e == i<!>
<!EQUALITY_NOT_APPLICABLE!>"" == i<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>ac == ad<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>tSub1 == tSub2<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aString == bString<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aListInt == aSetInt<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aSetInt == aListString<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aListString == aListInt<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>aString == aListString<!>
<!EQUALITY_NOT_APPLICABLE_WARNING!>bString == aListString<!>
}
@@ -0,0 +1,97 @@
class A<T>
class AIn<in T>
class AOut<out T>
class A2
open class B<T>
open class BIn<in T>
open class BOut<out T>
open class C
open class D
enum class E
interface I
interface T<T>
open class TSub1 : T<String>
open class TSub2 : T<Int>
fun foo(
string: String, int: Int,
strings: List<String>, ints: List<Int>,
aString: A<String>, aInt: A<Int>,
aOutString: A<out String>, aOutInt: A<out Int>,
aOutString2: AOut<String>, aOutInt2: AOut<Int>,
aInString: A<in String>, aInInt: A<in Int>,
aInString2: AIn<String>, aInInt2: AIn<Int>,
bString: B<String>, bInt: B<Int>,
bOutString: B<out String>, bOutInt: B<out Int>,
bOutString2: BOut<String>, bOutInt2: BOut<Int>,
bInString: B<in String>, bInInt: B<in Int>,
bInString2: BIn<String>, bInInt2: BIn<Int>,
a2: A2,
e: E,
i: I,
ac: A<C>, ad: A<D>,
tSub1: TSub1,
tSub2: TSub2,
aListInt: A<List<Int>>,
aSetInt: A<Set<Int>>,
aListString: A<List<String>>,
) {
"a" == "b"
1 == 2
<!EQUALITY_NOT_APPLICABLE!>"" == 2<!>
<!EQUALITY_NOT_APPLICABLE!>string == int<!>
strings == ints
aString == aInt
<!EQUALITY_NOT_APPLICABLE!>aOutString == aOutInt<!>
aInString == aInInt
<!EQUALITY_NOT_APPLICABLE!>aOutString == aInInt<!>
<!EQUALITY_NOT_APPLICABLE!>aInString == aOutInt<!>
<!EQUALITY_NOT_APPLICABLE!>aOutString == aInt<!>
aInString == aInt
<!EQUALITY_NOT_APPLICABLE!>aOutString2 == aOutInt2<!>
aInString2 == aInInt2
<!EQUALITY_NOT_APPLICABLE!>aOutString2 == aInInt2<!>
<!EQUALITY_NOT_APPLICABLE!>aInString2 == aOutInt2<!>
<!EQUALITY_NOT_APPLICABLE!>aString == a2<!>
bString == bInt
bOutString == bOutInt
bInString == bInInt
bOutString == bInInt
bInString == bOutInt
bOutString == bInt
bInString == bInt
bOutString2 == bOutInt2
bInString2 == bInInt2
bOutString2 == bInInt2
bInString2 == bOutInt2
<!INCOMPATIBLE_ENUM_COMPARISON_ERROR!>e == i<!>
<!EQUALITY_NOT_APPLICABLE!>"" == i<!>
ac == ad
tSub1 == tSub2
aString == bString
aListInt == aSetInt
aSetInt == aListString
aListString == aListInt
aString == aListString
bString == aListString
}
@@ -0,0 +1,109 @@
package
public fun foo(/*0*/ string: kotlin.String, /*1*/ int: kotlin.Int, /*2*/ strings: kotlin.collections.List<kotlin.String>, /*3*/ ints: kotlin.collections.List<kotlin.Int>, /*4*/ aString: A<kotlin.String>, /*5*/ aInt: A<kotlin.Int>, /*6*/ aOutString: A<out kotlin.String>, /*7*/ aOutInt: A<out kotlin.Int>, /*8*/ aOutString2: AOut<kotlin.String>, /*9*/ aOutInt2: AOut<kotlin.Int>, /*10*/ aInString: A<in kotlin.String>, /*11*/ aInInt: A<in kotlin.Int>, /*12*/ aInString2: AIn<kotlin.String>, /*13*/ aInInt2: AIn<kotlin.Int>, /*14*/ bString: B<kotlin.String>, /*15*/ bInt: B<kotlin.Int>, /*16*/ bOutString: B<out kotlin.String>, /*17*/ bOutInt: B<out kotlin.Int>, /*18*/ bOutString2: BOut<kotlin.String>, /*19*/ bOutInt2: BOut<kotlin.Int>, /*20*/ bInString: B<in kotlin.String>, /*21*/ bInInt: B<in kotlin.Int>, /*22*/ bInString2: BIn<kotlin.String>, /*23*/ bInInt2: BIn<kotlin.Int>, /*24*/ a2: A2, /*25*/ e: E, /*26*/ i: I, /*27*/ ac: A<C>, /*28*/ ad: A<D>, /*29*/ tSub1: TSub1, /*30*/ tSub2: TSub2, /*31*/ aListInt: A<kotlin.collections.List<kotlin.Int>>, /*32*/ aSetInt: A<kotlin.collections.Set<kotlin.Int>>, /*33*/ aListString: A<kotlin.collections.List<kotlin.String>>, /*34*/ mutableListAny: kotlin.collections.MutableList<kotlin.Any>, /*35*/ listString: kotlin.collections.List<kotlin.String>): kotlin.Unit
public final class A</*0*/ T> {
public constructor A</*0*/ T>()
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 final class A2 {
public constructor A2()
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 final class AIn</*0*/ in T> {
public constructor AIn</*0*/ in T>()
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 final class AOut</*0*/ out T> {
public constructor AOut</*0*/ out T>()
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 B</*0*/ T> {
public constructor B</*0*/ T>()
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 BIn</*0*/ in T> {
public constructor BIn</*0*/ in T>()
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 BOut</*0*/ out T> {
public constructor BOut</*0*/ out T>()
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 C {
public constructor C()
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 D {
public constructor D()
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 final enum class E : kotlin.Enum<E> {
private constructor E()
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: E): 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<E!>!
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): E
public final /*synthesized*/ fun values(): kotlin.Array<E>
}
public interface I {
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 T</*0*/ T> {
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 TSub1 : T<kotlin.String> {
public constructor TSub1()
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 TSub2 : T<kotlin.Int> {
public constructor TSub2()
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
}