[FIR] Prefer the non-smartcasted receiver in resolution if it's visible

Previously, we would ignore the candidate with the non-smartcasted
receiver if they have the same symbol.
Now we prefer them when they're visible or when the smart cast changes
the nullability.
This commit is contained in:
Kirill Rakhman
2023-12-18 17:32:28 +01:00
committed by Space Team
parent 5186ba80e2
commit ad2689ecbf
15 changed files with 105 additions and 251 deletions
@@ -29,12 +29,10 @@ FILE fqName:<root> fileName:/propertyInitializationAfterSmartCast.kt
TYPE_OP type=<root>.Derived_1 origin=CAST typeOperand=<root>.Derived_1
GET_VAR '<this>: <root>.Base_1 declared in <root>.Base_1' type=<root>.Base_1 origin=null
SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:x type:kotlin.Any? visibility:private [final]' type=kotlin.Unit origin=null
receiver: TYPE_OP type=<root>.Derived_1 origin=IMPLICIT_CAST typeOperand=<root>.Derived_1
GET_VAR '<this>: <root>.Base_1 declared in <root>.Base_1' type=<root>.Base_1 origin=null
receiver: GET_VAR '<this>: <root>.Base_1 declared in <root>.Base_1' type=<root>.Base_1 origin=null
value: CONST String type=kotlin.String value="O"
SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:y type:kotlin.Any? visibility:private [final]' type=kotlin.Unit origin=null
receiver: TYPE_OP type=<root>.Derived_1 origin=IMPLICIT_CAST typeOperand=<root>.Derived_1
GET_VAR '<this>: <root>.Base_1 declared in <root>.Base_1' type=<root>.Base_1 origin=null
receiver: GET_VAR '<this>: <root>.Base_1 declared in <root>.Base_1' type=<root>.Base_1 origin=null
value: CONST String type=kotlin.String value="O"
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
@@ -114,12 +112,10 @@ FILE fqName:<root> fileName:/propertyInitializationAfterSmartCast.kt
TYPE_OP type=<root>.Impl_2 origin=CAST typeOperand=<root>.Impl_2
GET_VAR '<this>: <root>.Base_2 declared in <root>.Base_2' type=<root>.Base_2 origin=null
SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:x type:kotlin.Any? visibility:private [final]' type=kotlin.Unit origin=null
receiver: TYPE_OP type=<root>.Impl_2 origin=IMPLICIT_CAST typeOperand=<root>.Impl_2
GET_VAR '<this>: <root>.Base_2 declared in <root>.Base_2' type=<root>.Base_2 origin=null
receiver: GET_VAR '<this>: <root>.Base_2 declared in <root>.Base_2' type=<root>.Base_2 origin=null
value: CONST String type=kotlin.String value="K"
SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:y type:kotlin.Any? visibility:private [final]' type=kotlin.Unit origin=null
receiver: TYPE_OP type=<root>.Impl_2 origin=IMPLICIT_CAST typeOperand=<root>.Impl_2
GET_VAR '<this>: <root>.Base_2 declared in <root>.Base_2' type=<root>.Base_2 origin=null
receiver: GET_VAR '<this>: <root>.Base_2 declared in <root>.Base_2' type=<root>.Base_2 origin=null
value: CONST String type=kotlin.String value="K"
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
@@ -1,5 +1,3 @@
// IGNORE_BACKEND_K2: JVM_IR
open class SuperFoo {
public fun bar() {
if (this is Foo) {
@@ -27,4 +27,21 @@ class Derived : Base() {
x.y = x.y + 1
}
}
protected fun baz2(x: Base?) {
x.<!INVISIBLE_REFERENCE!>foo<!>()
x.<!INVISIBLE_REFERENCE!>bar<!>()
x.<!INVISIBLE_REFERENCE!>x<!> = x.<!INVISIBLE_REFERENCE!>x<!> + 1
x.<!INVISIBLE_SETTER!>y<!> = x<!UNSAFE_CALL!>.<!>y + 1
if (x is Derived) {
x.foo()
x.bar()
x.baz(x)
x.x = x.x + 1
x.y = x.y + 1
}
}
}
@@ -27,4 +27,21 @@ class Derived : Base() {
<!INVISIBLE_SETTER!>x.y<!> = x.y + 1
}
}
protected fun baz2(x: Base?) {
x<!UNSAFE_CALL!>.<!><!INVISIBLE_MEMBER!>foo<!>()
x<!UNSAFE_CALL!>.<!><!INVISIBLE_MEMBER!>bar<!>()
x<!UNSAFE_CALL!>.<!><!INVISIBLE_MEMBER!>x<!> = x<!UNSAFE_CALL!>.<!><!INVISIBLE_MEMBER!>x<!> + 1
<!INVISIBLE_SETTER!>x<!UNSAFE_CALL!>.<!>y<!> = x<!UNSAFE_CALL!>.<!>y + 1
if (x is Derived) {
<!DEBUG_INFO_SMARTCAST!>x<!>.foo()
<!DEBUG_INFO_SMARTCAST!>x<!>.bar()
<!DEBUG_INFO_SMARTCAST!>x<!>.baz(<!DEBUG_INFO_SMARTCAST!>x<!>)
<!DEBUG_INFO_SMARTCAST!>x<!>.x = <!DEBUG_INFO_SMARTCAST!>x<!>.x + 1
<!DEBUG_INFO_SMARTCAST!>x<!>.y = <!DEBUG_INFO_SMARTCAST!>x<!>.y + 1
}
}
}
@@ -1,24 +0,0 @@
package
public open class Base {
public constructor Base()
protected open var x: kotlin.Int
public open var y: kotlin.Int
protected open fun bar(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected open 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 Derived : Base {
public constructor Derived()
protected open override /*1*/ /*fake_override*/ var x: kotlin.Int
public open override /*1*/ /*fake_override*/ var y: kotlin.Int
protected open override /*1*/ fun bar(): kotlin.Unit
protected final fun baz(/*0*/ x: Base): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected open override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -41,10 +41,10 @@ fun testWithSubject_ok(x: Boolean, y: Boolean?, any: Any, z: Boolean) {
x !in x -> {}
x is String -> {}
x !is String -> {}
x <!OVERLOAD_RESOLUTION_AMBIGUITY!><<!> x -> {}
x <!OVERLOAD_RESOLUTION_AMBIGUITY!>><!> x -> {}
x <!OVERLOAD_RESOLUTION_AMBIGUITY!><=<!> x -> {}
x <!OVERLOAD_RESOLUTION_AMBIGUITY!>>=<!> x -> {}
x < x -> {}
x > x -> {}
x <= x -> {}
x >= x -> {}
x == x -> {}
x != x -> {}
<!DEPRECATED_IDENTITY_EQUALS!>x === x<!> -> {}
@@ -1,65 +0,0 @@
FILE fqName:<root> fileName:/smartCastInValInitialization.kt
CLASS CLASS name:RootBus modality:FINAL visibility:public superTypes:[<root>.MessageBusImpl]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.RootBus
CONSTRUCTOR visibility:public <> () returnType:<root>.RootBus [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () declared in <root>.MessageBusImpl'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:RootBus modality:FINAL visibility:public superTypes:[<root>.MessageBusImpl]'
PROPERTY FAKE_OVERRIDE name:parentBus visibility:public modality:FINAL [fake_override,val]
overridden:
public final parentBus: kotlin.Any?
FUN FAKE_OVERRIDE name:<get-parentBus> visibility:public modality:FINAL <> ($this:<root>.MessageBusImpl) returnType:kotlin.Any? [fake_override]
correspondingProperty: PROPERTY FAKE_OVERRIDE name:parentBus visibility:public modality:FINAL [fake_override,val]
overridden:
public final fun <get-parentBus> (): kotlin.Any? declared in <root>.MessageBusImpl
$this: VALUE_PARAMETER name:<this> type:<root>.MessageBusImpl
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in <root>.MessageBusImpl
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in <root>.MessageBusImpl
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in <root>.MessageBusImpl
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
CLASS CLASS name:MessageBusImpl modality:OPEN visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.MessageBusImpl
CONSTRUCTOR visibility:public <> () returnType:<root>.MessageBusImpl [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:MessageBusImpl modality:OPEN visibility:public superTypes:[kotlin.Any]'
PROPERTY name:parentBus visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:parentBus type:kotlin.Any? visibility:private [final]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-parentBus> visibility:public modality:FINAL <> ($this:<root>.MessageBusImpl) returnType:kotlin.Any?
correspondingProperty: PROPERTY name:parentBus visibility:public modality:FINAL [val]
$this: VALUE_PARAMETER name:<this> type:<root>.MessageBusImpl
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-parentBus> (): kotlin.Any? declared in <root>.MessageBusImpl'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:parentBus type:kotlin.Any? visibility:private [final]' type=kotlin.Any? origin=null
receiver: GET_VAR '<this>: <root>.MessageBusImpl declared in <root>.MessageBusImpl.<get-parentBus>' type=<root>.MessageBusImpl origin=null
ANONYMOUS_INITIALIZER isStatic=false
BLOCK_BODY
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
TYPE_OP type=<root>.RootBus origin=CAST typeOperand=<root>.RootBus
GET_VAR '<this>: <root>.MessageBusImpl declared in <root>.MessageBusImpl' type=<root>.MessageBusImpl origin=null
SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:parentBus type:kotlin.Any? visibility:private [final]' type=kotlin.Unit origin=null
receiver: TYPE_OP type=<root>.RootBus origin=IMPLICIT_CAST typeOperand=<root>.RootBus
GET_VAR '<this>: <root>.MessageBusImpl declared in <root>.MessageBusImpl' type=<root>.MessageBusImpl origin=null
value: CONST Null type=kotlin.Nothing? value=null
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
@@ -1,25 +0,0 @@
class RootBus : MessageBusImpl {
constructor() /* primary */ {
super/*MessageBusImpl*/()
/* <init>() */
}
}
open class MessageBusImpl {
constructor() /* primary */ {
super/*Any*/()
/* <init>() */
}
val parentBus: Any?
get
init {
<this> as RootBus /*~> Unit */
<this> /*as RootBus */.#parentBus = null
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
class RootBus: MessageBusImpl()
open class MessageBusImpl {
@@ -1,76 +0,0 @@
FILE fqName:<root> fileName:/smartCastAside.kt
CLASS INTERFACE name:A modality:ABSTRACT visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.A
FUN name:foo visibility:public modality:ABSTRACT <> ($this:<root>.A) returnType:kotlin.Unit
$this: VALUE_PARAMETER name:<this> type:<root>.A
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
CLASS INTERFACE name:B modality:ABSTRACT visibility:public superTypes:[<root>.A]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.B
FUN name:bar visibility:public modality:ABSTRACT <> ($this:<root>.B) returnType:kotlin.Unit
$this: VALUE_PARAMETER name:<this> type:<root>.B
FUN FAKE_OVERRIDE name:foo visibility:public modality:ABSTRACT <> ($this:<root>.A) returnType:kotlin.Unit [fake_override]
overridden:
public abstract fun foo (): kotlin.Unit declared in <root>.A
$this: VALUE_PARAMETER name:<this> type:<root>.A
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in <root>.A
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in <root>.A
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in <root>.A
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
CLASS INTERFACE name:C modality:ABSTRACT visibility:public superTypes:[<root>.A]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.C
FUN name:baz visibility:public modality:ABSTRACT <> ($this:<root>.C) returnType:kotlin.Unit
$this: VALUE_PARAMETER name:<this> type:<root>.C
FUN FAKE_OVERRIDE name:foo visibility:public modality:ABSTRACT <> ($this:<root>.A) returnType:kotlin.Unit [fake_override]
overridden:
public abstract fun foo (): kotlin.Unit declared in <root>.A
$this: VALUE_PARAMETER name:<this> type:<root>.A
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in <root>.A
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in <root>.A
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in <root>.A
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN name:test visibility:public modality:FINAL <> (param:<root>.B) returnType:kotlin.Unit
VALUE_PARAMETER name:param index:0 type:<root>.B
BLOCK_BODY
WHEN type=kotlin.Unit origin=IF
BRANCH
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=<root>.C
GET_VAR 'param: <root>.B declared in <root>.test' type=<root>.B origin=null
then: BLOCK type=kotlin.Unit origin=null
CALL 'public abstract fun foo (): kotlin.Unit declared in <root>.A' type=kotlin.Unit origin=null
$this: TYPE_OP type=<root>.C origin=IMPLICIT_CAST typeOperand=<root>.C
GET_VAR 'param: <root>.B declared in <root>.test' type=<root>.B origin=null
CALL 'public abstract fun bar (): kotlin.Unit declared in <root>.B' type=kotlin.Unit origin=null
$this: GET_VAR 'param: <root>.B declared in <root>.test' type=<root>.B origin=null
CALL 'public abstract fun baz (): kotlin.Unit declared in <root>.C' type=kotlin.Unit origin=null
$this: TYPE_OP type=<root>.C origin=IMPLICIT_CAST typeOperand=<root>.C
GET_VAR 'param: <root>.B declared in <root>.test' type=<root>.B origin=null
@@ -1,24 +0,0 @@
interface A {
abstract fun foo()
}
interface B : A {
abstract fun bar()
}
interface C : A {
abstract fun baz()
}
fun test(param: B) {
when {
param is C -> { // BLOCK
param /*as C */.foo()
param.bar()
param /*as C */.baz()
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
interface A {
fun foo()
}