Values equality no more provides guarantee for their types equality (for open types or types with overridden equals) #KT-11280 Fixed
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
abstract class Base {
|
||||
override fun equals(other: Any?) = other is Base
|
||||
}
|
||||
|
||||
class Derived1 : Base() {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
class Derived2 : Base()
|
||||
|
||||
fun check(x1: Derived1, x: Base) {
|
||||
if (x1 == x) {
|
||||
// Smart cast here will provoke CCA
|
||||
x.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
}
|
||||
if (x1 === x) {
|
||||
// OK
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.foo()
|
||||
}
|
||||
if (x1 !== x) {} else {
|
||||
// OK
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.foo()
|
||||
}
|
||||
}
|
||||
|
||||
class FinalClass { // <-- 'equals' on instances of this class is useful for smart casts
|
||||
fun use() {}
|
||||
|
||||
fun equals(x: Int): Boolean = x > 42
|
||||
}
|
||||
|
||||
fun foo(x: FinalClass?, y: Any) {
|
||||
if (x == y) {
|
||||
// OK
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.hashCode()
|
||||
// OK
|
||||
<!DEBUG_INFO_SMARTCAST!>y<!>.use()
|
||||
}
|
||||
when (x) {
|
||||
// OK (equals from FinalClass)
|
||||
y -> <!DEBUG_INFO_SMARTCAST!>y<!>.use()
|
||||
}
|
||||
when (y) {
|
||||
// ERROR (equals from Any)
|
||||
x -> y.<!UNRESOLVED_REFERENCE!>use<!>()
|
||||
}
|
||||
}
|
||||
|
||||
open class OpenClass {
|
||||
override fun equals(other: Any?) = other is OpenClass
|
||||
}
|
||||
|
||||
interface Dummy // should not influence anything
|
||||
|
||||
class FinalClass2 : Dummy, OpenClass() { // but here not
|
||||
fun use() {}
|
||||
}
|
||||
|
||||
fun bar(x: FinalClass2?, y: Any) {
|
||||
if (x == y) {
|
||||
// OK
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.hashCode()
|
||||
// ERROR
|
||||
y.<!UNRESOLVED_REFERENCE!>use<!>()
|
||||
}
|
||||
}
|
||||
|
||||
open class OpenClass2 // and here too
|
||||
|
||||
fun bar(x: OpenClass2?, y: Any) {
|
||||
if (x == y) {
|
||||
// OK
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.hashCode()
|
||||
// ERROR
|
||||
y.<!UNRESOLVED_REFERENCE!>use<!>()
|
||||
}
|
||||
}
|
||||
|
||||
sealed class Sealed {
|
||||
override fun equals(other: Any?) = other is Sealed
|
||||
|
||||
class Sealed1 : Sealed() {
|
||||
fun gav() {}
|
||||
}
|
||||
|
||||
object Sealed2 : Sealed()
|
||||
|
||||
fun check(arg: Sealed1) {
|
||||
if (arg == this) {
|
||||
// Smart cast here will provoke CCA
|
||||
this.<!UNRESOLVED_REFERENCE!>gav<!>()
|
||||
<!UNRESOLVED_REFERENCE!>gav<!>()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package
|
||||
|
||||
public fun bar(/*0*/ x: FinalClass2?, /*1*/ y: kotlin.Any): kotlin.Unit
|
||||
public fun bar(/*0*/ x: OpenClass2?, /*1*/ y: kotlin.Any): kotlin.Unit
|
||||
public fun check(/*0*/ x1: Derived1, /*1*/ x: Base): kotlin.Unit
|
||||
public fun foo(/*0*/ x: FinalClass?, /*1*/ y: kotlin.Any): kotlin.Unit
|
||||
|
||||
public abstract class Base {
|
||||
public constructor Base()
|
||||
public open override /*1*/ 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 Derived1 : Base {
|
||||
public constructor Derived1()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class Derived2 : Base {
|
||||
public constructor Derived2()
|
||||
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 Dummy {
|
||||
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 FinalClass {
|
||||
public constructor FinalClass()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun equals(/*0*/ x: kotlin.Int): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
public final fun use(): kotlin.Unit
|
||||
}
|
||||
|
||||
public final class FinalClass2 : Dummy, OpenClass {
|
||||
public constructor FinalClass2()
|
||||
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
public final fun use(): kotlin.Unit
|
||||
}
|
||||
|
||||
public open class OpenClass {
|
||||
public constructor OpenClass()
|
||||
public open override /*1*/ 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 OpenClass2 {
|
||||
public constructor OpenClass2()
|
||||
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 sealed class Sealed {
|
||||
private constructor Sealed()
|
||||
public final fun check(/*0*/ arg: Sealed.Sealed1): kotlin.Unit
|
||||
public open override /*1*/ 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 Sealed1 : Sealed {
|
||||
public constructor Sealed1()
|
||||
public final override /*1*/ /*fake_override*/ fun check(/*0*/ arg: Sealed.Sealed1): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun gav(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public object Sealed2 : Sealed {
|
||||
private constructor Sealed2()
|
||||
public final override /*1*/ /*fake_override*/ fun check(/*0*/ arg: Sealed.Sealed1): kotlin.Unit
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ fun foo(): Int {
|
||||
val x: Any? = null
|
||||
val y = 2
|
||||
if (x == y) {
|
||||
return <!DEBUG_INFO_SMARTCAST!>x<!> + y
|
||||
return x <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>+<!> y
|
||||
}
|
||||
return y
|
||||
}
|
||||
Reference in New Issue
Block a user