[NI] Report unsafe implicit invoke accordingly to OI
There are several issues with unsafe desugaring for convention calls. Proper fix is not implemented here (see design proposal KT-30872). This commit only applies the old logic in the new inference. ^KT-30695 Fixed
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
class Rule(val apply:() -> Unit)
|
||||
|
||||
fun bar() {}
|
||||
|
||||
+1
-2
@@ -1,4 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
class Rule(val apply:() -> Unit)
|
||||
|
||||
fun bar() {}
|
||||
@@ -14,7 +13,7 @@ fun foo() {
|
||||
rule?.apply?.invoke()
|
||||
|
||||
// this should be an error
|
||||
rule?.<!OI;UNSAFE_IMPLICIT_INVOKE_CALL!>apply<!>()
|
||||
rule?.<!UNSAFE_IMPLICIT_INVOKE_CALL!>apply<!>()
|
||||
|
||||
// these both also ok (with smart cast / unnecessary safe call)
|
||||
if (rule != null) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
//KT-1875 Safe call should be binded with receiver or this object (but not with both by default)
|
||||
|
||||
package kt1875
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
//KT-1875 Safe call should be binded with receiver or this object (but not with both by default)
|
||||
|
||||
package kt1875
|
||||
@@ -10,13 +9,13 @@ interface T {
|
||||
}
|
||||
|
||||
fun test(t: T) {
|
||||
t<!NI;UNSAFE_CALL!>.<!><!OI;UNSAFE_IMPLICIT_INVOKE_CALL!>f<!>(1) //unsafe call error
|
||||
t.<!UNSAFE_IMPLICIT_INVOKE_CALL!>f<!>(1) //unsafe call error
|
||||
t.f?.invoke(1)
|
||||
}
|
||||
|
||||
fun test1(t: T?) {
|
||||
t<!UNSAFE_CALL!>.<!><!FUNCTION_EXPECTED!>f<!>(1) // todo resolve f as value and report UNSAFE_CALL
|
||||
t<!NI;UNSAFE_CALL!>?.<!><!OI;UNSAFE_IMPLICIT_INVOKE_CALL!>f<!>(1)
|
||||
t?.<!UNSAFE_IMPLICIT_INVOKE_CALL!>f<!>(1)
|
||||
t<!UNSAFE_CALL!>.<!>f?.invoke(1)
|
||||
t?.f?.invoke(1)
|
||||
}
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
fun <E : String?, T : ((CharSequence) -> Unit)?> foo(x: E, y: T) {
|
||||
if (x != null) {
|
||||
y(x)
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
fun <E : String?, T : ((CharSequence) -> Unit)?> foo(x: E, y: T) {
|
||||
if (x != null) {
|
||||
<!NI;UNSAFE_CALL, OI;UNSAFE_IMPLICIT_INVOKE_CALL!>y<!>(<!DEBUG_INFO_SMARTCAST!>x<!>)
|
||||
<!UNSAFE_IMPLICIT_INVOKE_CALL!>y<!>(<!DEBUG_INFO_SMARTCAST!>x<!>)
|
||||
}
|
||||
|
||||
if (y != null) {
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// FILE: J.java
|
||||
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
+1
-2
@@ -1,4 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// FILE: J.java
|
||||
|
||||
import org.jetbrains.annotations.*;
|
||||
@@ -19,6 +18,6 @@ public class J {
|
||||
|
||||
fun test() {
|
||||
J.staticNN()
|
||||
J<!NI;UNSAFE_CALL!>.<!><!OI;UNSAFE_IMPLICIT_INVOKE_CALL!>staticN<!>()
|
||||
J.<!UNSAFE_IMPLICIT_INVOKE_CALL!>staticN<!>()
|
||||
J.staticJ()
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
class A(val x: (String.() -> Unit)?)
|
||||
|
||||
fun test(a: A) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
class A(val x: (String.() -> Unit)?)
|
||||
|
||||
fun test(a: A) {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
class A {
|
||||
val lambda: () -> Unit = TODO()
|
||||
val memberInvoke: B = TODO()
|
||||
val extensionInvoke: C = TODO()
|
||||
}
|
||||
|
||||
class B {
|
||||
operator fun invoke() {}
|
||||
}
|
||||
|
||||
class C
|
||||
operator fun C.invoke() {}
|
||||
|
||||
fun test(a: A?) {
|
||||
a?.lambda()
|
||||
a?.memberInvoke()
|
||||
a?.extensionInvoke()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
class A {
|
||||
val lambda: () -> Unit = TODO()
|
||||
val memberInvoke: B = TODO()
|
||||
val extensionInvoke: C = TODO()
|
||||
}
|
||||
|
||||
class B {
|
||||
operator fun invoke() {}
|
||||
}
|
||||
|
||||
class C
|
||||
operator fun C.invoke() {}
|
||||
|
||||
fun test(a: A?) {
|
||||
a?.<!UNSAFE_IMPLICIT_INVOKE_CALL!>lambda<!>()
|
||||
a?.<!UNSAFE_IMPLICIT_INVOKE_CALL!>memberInvoke<!>()
|
||||
a?.extensionInvoke()
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package
|
||||
|
||||
public fun test(/*0*/ a: A?): kotlin.Unit
|
||||
public operator fun C.invoke(): kotlin.Unit
|
||||
|
||||
public final class A {
|
||||
public constructor A()
|
||||
public final val extensionInvoke: C
|
||||
public final val lambda: () -> kotlin.Unit
|
||||
public final val memberInvoke: B
|
||||
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 B {
|
||||
public constructor B()
|
||||
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 final operator fun invoke(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final 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
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
class MemberInvokeOwner {
|
||||
operator fun invoke() {}
|
||||
}
|
||||
|
||||
class Cls {
|
||||
fun testImplicitReceiver() {
|
||||
<!INAPPLICABLE_CANDIDATE!>nullableExtensionProperty<!>()
|
||||
}
|
||||
}
|
||||
|
||||
val Cls.nullableExtensionProperty: MemberInvokeOwner?
|
||||
get() = null
|
||||
|
||||
val Cls.extensionProperty: MemberInvokeOwner
|
||||
get() = TODO()
|
||||
|
||||
fun testNullableReceiver(nullable: Cls?) {
|
||||
nullable?.extensionProperty()
|
||||
nullable.<!UNRESOLVED_REFERENCE!>extensionProperty<!>()
|
||||
}
|
||||
|
||||
fun testNotNullableReceiver(notNullable: Cls) {
|
||||
notNullable.<!INAPPLICABLE_CANDIDATE!>nullableExtensionProperty<!>()
|
||||
notNullable?.extensionProperty()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
class MemberInvokeOwner {
|
||||
operator fun invoke() {}
|
||||
}
|
||||
|
||||
class Cls {
|
||||
fun testImplicitReceiver() {
|
||||
<!UNSAFE_IMPLICIT_INVOKE_CALL!>nullableExtensionProperty<!>()
|
||||
}
|
||||
}
|
||||
|
||||
val Cls.nullableExtensionProperty: MemberInvokeOwner?
|
||||
get() = null
|
||||
|
||||
val Cls.extensionProperty: MemberInvokeOwner
|
||||
get() = TODO()
|
||||
|
||||
fun testNullableReceiver(nullable: Cls?) {
|
||||
nullable?.<!UNSAFE_IMPLICIT_INVOKE_CALL!>extensionProperty<!>()
|
||||
nullable<!UNSAFE_CALL!>.<!><!FUNCTION_EXPECTED!>extensionProperty<!>()
|
||||
}
|
||||
|
||||
fun testNotNullableReceiver(notNullable: Cls) {
|
||||
notNullable.<!UNSAFE_IMPLICIT_INVOKE_CALL!>nullableExtensionProperty<!>()
|
||||
notNullable<!UNNECESSARY_SAFE_CALL!>?.<!>extensionProperty()
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package
|
||||
|
||||
public val Cls.extensionProperty: MemberInvokeOwner
|
||||
public val Cls.nullableExtensionProperty: MemberInvokeOwner?
|
||||
public fun testNotNullableReceiver(/*0*/ notNullable: Cls): kotlin.Unit
|
||||
public fun testNullableReceiver(/*0*/ nullable: Cls?): kotlin.Unit
|
||||
|
||||
public final class Cls {
|
||||
public constructor Cls()
|
||||
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 final fun testImplicitReceiver(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class MemberInvokeOwner {
|
||||
public constructor MemberInvokeOwner()
|
||||
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 final operator fun invoke(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// !LANGUAGE: -SafeCastCheckBoundSmartCasts -BooleanElvisBoundSmartCasts
|
||||
// A set of examples for
|
||||
// "If the result of a safe call is not null, understand that its receiver is not null"
|
||||
|
||||
+1
-2
@@ -1,4 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// !LANGUAGE: -SafeCastCheckBoundSmartCasts -BooleanElvisBoundSmartCasts
|
||||
// A set of examples for
|
||||
// "If the result of a safe call is not null, understand that its receiver is not null"
|
||||
@@ -130,7 +129,7 @@ class Invokable(val x: String) {
|
||||
class InvokableProperty(val i: Invokable)
|
||||
|
||||
fun checkInvokable(ip: InvokableProperty?) {
|
||||
if (ip?.<!OI;UNSAFE_IMPLICIT_INVOKE_CALL!>i<!>() == "Hello") {
|
||||
if (ip?.<!UNSAFE_IMPLICIT_INVOKE_CALL!>i<!>() == "Hello") {
|
||||
<!DEBUG_INFO_SMARTCAST!>ip<!>.hashCode()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user