[NI] Report unsafe invoke properly for flexible types

`isNullable` check returns `true` for flexible types,
which leads to false positive unsafe invoke error, when
receiver for invoke's property is flexible.
^KT-30695 Fixed
This commit is contained in:
Pavel Kirpichenkov
2020-02-13 17:18:21 +03:00
parent b161839092
commit ba25b0faaf
4 changed files with 48 additions and 1 deletions
@@ -343,7 +343,7 @@ private fun KotlinResolutionCandidate.checkUnsafeImplicitInvokeAfterSafeCall(arg
} }
} ?: error("Receiver kind does not match receiver argument") } ?: error("Receiver kind does not match receiver argument")
if (receiverArgument.receiver.stableType.isNullable()) { if (receiverArgument.isSafeCall && receiverArgument.receiver.stableType.isNullable()) {
addDiagnostic(UnsafeCallError(argument, isForImplicitInvoke = true)) addDiagnostic(UnsafeCallError(argument, isForImplicitInvoke = true))
return ImplicitInvokeCheckStatus.UNSAFE_INVOKE_REPORTED return ImplicitInvokeCheckStatus.UNSAFE_INVOKE_REPORTED
} }
@@ -1,3 +1,13 @@
// FILE: JavaClass.java
public class JavaClass {
public static Cls createFlexible() {
return new Cls();
}
}
// FILE: test.kt
class MemberInvokeOwner { class MemberInvokeOwner {
operator fun invoke() {} operator fun invoke() {}
} }
@@ -23,3 +33,11 @@ fun testNotNullableReceiver(notNullable: Cls) {
notNullable.<!INAPPLICABLE_CANDIDATE!>nullableExtensionProperty<!>() notNullable.<!INAPPLICABLE_CANDIDATE!>nullableExtensionProperty<!>()
notNullable?.extensionProperty() notNullable?.extensionProperty()
} }
fun testFlexibleReceiver() {
val flexible = JavaClass.createFlexible()
flexible.extensionProperty()
flexible?.extensionProperty()
flexible.<!INAPPLICABLE_CANDIDATE!>nullableExtensionProperty<!>()
flexible?.nullableExtensionProperty()
}
@@ -1,3 +1,13 @@
// FILE: JavaClass.java
public class JavaClass {
public static Cls createFlexible() {
return new Cls();
}
}
// FILE: test.kt
class MemberInvokeOwner { class MemberInvokeOwner {
operator fun invoke() {} operator fun invoke() {}
} }
@@ -23,3 +33,11 @@ fun testNotNullableReceiver(notNullable: Cls) {
notNullable.<!UNSAFE_IMPLICIT_INVOKE_CALL!>nullableExtensionProperty<!>() notNullable.<!UNSAFE_IMPLICIT_INVOKE_CALL!>nullableExtensionProperty<!>()
notNullable<!UNNECESSARY_SAFE_CALL!>?.<!>extensionProperty() notNullable<!UNNECESSARY_SAFE_CALL!>?.<!>extensionProperty()
} }
fun testFlexibleReceiver() {
val flexible = JavaClass.createFlexible()
flexible.extensionProperty()
flexible?.<!UNSAFE_IMPLICIT_INVOKE_CALL!>extensionProperty<!>()
flexible.<!UNSAFE_IMPLICIT_INVOKE_CALL!>nullableExtensionProperty<!>()
flexible?.<!UNSAFE_IMPLICIT_INVOKE_CALL!>nullableExtensionProperty<!>()
}
@@ -2,6 +2,7 @@ package
public val Cls.extensionProperty: MemberInvokeOwner public val Cls.extensionProperty: MemberInvokeOwner
public val Cls.nullableExtensionProperty: MemberInvokeOwner? public val Cls.nullableExtensionProperty: MemberInvokeOwner?
public fun testFlexibleReceiver(): kotlin.Unit
public fun testNotNullableReceiver(/*0*/ notNullable: Cls): kotlin.Unit public fun testNotNullableReceiver(/*0*/ notNullable: Cls): kotlin.Unit
public fun testNullableReceiver(/*0*/ nullable: Cls?): kotlin.Unit public fun testNullableReceiver(/*0*/ nullable: Cls?): kotlin.Unit
@@ -13,6 +14,16 @@ public final class Cls {
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
public open class JavaClass {
public constructor JavaClass()
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
// Static members
public open fun createFlexible(): Cls!
}
public final class MemberInvokeOwner { public final class MemberInvokeOwner {
public constructor 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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean