NI: exclude reporting of an unsafe call diagnostic for implicit invoke after safe call in cases when invoke has type parameters (make NI and OI consistent)

^KT-37579 Fixed
This commit is contained in:
Victor Petukhov
2020-03-19 14:55:46 +03:00
parent 8b330193ac
commit 3b892fe31e
7 changed files with 525 additions and 1 deletions
@@ -18790,6 +18790,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/resolve/invoke/implicitInvoke.kt");
}
@TestMetadata("implicitInvokeAfterSafeCall.kt")
public void testImplicitInvokeAfterSafeCall() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/invoke/implicitInvokeAfterSafeCall.kt");
}
@TestMetadata("invokeAndSmartCast.kt")
public void testInvokeAndSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/invoke/invokeAndSmartCast.kt");
@@ -486,7 +486,7 @@ private fun KotlinResolutionCandidate.checkUnsafeImplicitInvokeAfterSafeCall(arg
}
} ?: error("Receiver kind does not match receiver argument")
if (receiverArgument.isSafeCall && receiverArgument.receiver.stableType.isNullable()) {
if (receiverArgument.isSafeCall && receiverArgument.receiver.stableType.isNullable() && resolvedCall.candidateDescriptor.typeParameters.isEmpty()) {
addDiagnostic(UnsafeCallError(argument, isForImplicitInvoke = true))
return ImplicitInvokeCheckStatus.UNSAFE_INVOKE_REPORTED
}
@@ -0,0 +1,140 @@
// !WITH_NEW_INFERENCE
// !DIAGNOSTICS: -UNUSED_PARAMETER
// Test case 1: additional receiver, generic invoke
class Foo1<T>
class Bar1<T>(val value: Foo1<T>)
class Another1 {
operator fun <T> Foo1<T>.invoke(handler: () -> Unit) {}
}
fun Another1.main(x: Bar1<String>?) {
x?.value {}
x?.value.<!INAPPLICABLE_CANDIDATE!>invoke<!>({})
}
// Test case 2: additional receiver, non-generic invoke
class Foo2<T>
class Bar2<T>(val value: Foo2<T>)
class Another2 {
operator fun Foo2<String>.invoke(x: Int) {}
}
fun Another2.main(x: Bar2<String>?) {
x?.value(1)
x?.value.<!INAPPLICABLE_CANDIDATE!>invoke<!>(1)
}
// Test case 3: additional generic receiver, generic invoke
class Foo3<T>
class Bar3<T>(val value: Foo3<T>)
class Another3<T> {
operator fun Foo3<T>.invoke(x: Int) {}
}
fun <K> Another3<K>.main(x: Bar3<K>?) {
x?.value(1)
x?.value.<!INAPPLICABLE_CANDIDATE!>invoke<!>(1)
}
// Test case 4: additional receiver, generic invoke with nullable receiver
class Foo4<T>
class Bar4<T>(val value: Foo4<T>)
class Another4<T> {
operator fun Foo4<T>?.invoke(x: Int) {}
}
fun <K> Another4<K>.main(x: Bar4<K>?) {
x?.value(1)
x?.value.invoke(1)
}
// Test case 5: additional receiver, generic invoke without using a type parameter inside a recevier
class Foo5
class Bar5(val value: Foo5)
class Another5 {
operator fun <T> Foo5.invoke(handler: T) {}
}
fun Another5.main(x: Bar5?) {
x?.value {}
x?.value.<!INAPPLICABLE_CANDIDATE!>invoke<!>({})
}
// Test case 6: top-level generic invoke
class Foo6<T>
class Bar6<T>(val value: Foo6<T>)
operator fun <T> Foo6<T>.invoke(x: Int) {}
fun main(x: Bar6<String>?) {
x?.value(1)
x?.value.<!INAPPLICABLE_CANDIDATE!>invoke<!>(1)
}
// Test case 7: top-level generic invoke and invoke with compatible additional dispatch recevier
class Foo7<T>
class Bar7<T>(val value: Foo7<T>)
class Another7 {
operator fun <T> Foo7<T>.invoke(x: Int) {}
}
operator fun <T> Foo7<T>.invoke(x: Int) {}
fun Another7.main(x: Bar7<String>?) {
x?.value(1)
x?.value.<!INAPPLICABLE_CANDIDATE!>invoke<!>(1)
}
// Test case 8: top-level non-generic invoke
class Foo8<T>
class Bar8<T>(val value: Foo8<T>)
operator fun Foo8<String>.invoke(x: Int) {}
fun main(x: Bar8<String>?) {
x?.value(1)
x?.value.<!INAPPLICABLE_CANDIDATE!>invoke<!>(1)
}
// Test case 9: additional receiver, generic invoke with pure type perameter receiver
class Foo9<T>
class Bar9<T>(val value: Foo9<T>)
class Another9 {
operator fun <T> T.invoke(handler: () -> Unit) {}
}
fun Another9.main(x: Bar9<String>?) {
x?.value {}
x?.value.invoke({})
}
// Test case 10: additional receiver, generic invoke with upper bound
class Foo10<T>
class Bar10<T>(val value: Foo10<T>)
class Another10 {
operator fun <T: Any> Foo10<T>.invoke(handler: () -> Unit) {}
}
fun Another10.main(x: Bar10<String>?) {
x?.value {}
x?.value.<!INAPPLICABLE_CANDIDATE!>invoke<!>({})
}
@@ -0,0 +1,140 @@
// !WITH_NEW_INFERENCE
// !DIAGNOSTICS: -UNUSED_PARAMETER
// Test case 1: additional receiver, generic invoke
class Foo1<T>
class Bar1<T>(val value: Foo1<T>)
class Another1 {
operator fun <T> Foo1<T>.invoke(handler: () -> Unit) {}
}
fun Another1.main(x: Bar1<String>?) {
x?.value {}
x?.value<!UNSAFE_CALL!>.<!>invoke({})
}
// Test case 2: additional receiver, non-generic invoke
class Foo2<T>
class Bar2<T>(val value: Foo2<T>)
class Another2 {
operator fun Foo2<String>.invoke(x: Int) {}
}
fun Another2.main(x: Bar2<String>?) {
x?.<!UNSAFE_IMPLICIT_INVOKE_CALL!>value<!>(1)
x?.value<!UNSAFE_CALL!>.<!>invoke(1)
}
// Test case 3: additional generic receiver, generic invoke
class Foo3<T>
class Bar3<T>(val value: Foo3<T>)
class Another3<T> {
operator fun Foo3<T>.invoke(x: Int) {}
}
fun <K> Another3<K>.main(x: Bar3<K>?) {
x?.<!UNSAFE_IMPLICIT_INVOKE_CALL!>value<!>(1)
x?.value<!UNSAFE_CALL!>.<!>invoke(1)
}
// Test case 4: additional receiver, generic invoke with nullable receiver
class Foo4<T>
class Bar4<T>(val value: Foo4<T>)
class Another4<T> {
operator fun Foo4<T>?.invoke(x: Int) {}
}
fun <K> Another4<K>.main(x: Bar4<K>?) {
x?.<!UNSAFE_IMPLICIT_INVOKE_CALL!>value<!>(1)
x?.value.invoke(1)
}
// Test case 5: additional receiver, generic invoke without using a type parameter inside a recevier
class Foo5
class Bar5(val value: Foo5)
class Another5 {
operator fun <T> Foo5.invoke(handler: T) {}
}
fun Another5.main(x: Bar5?) {
x?.value {}
x?.value<!UNSAFE_CALL!>.<!>invoke({})
}
// Test case 6: top-level generic invoke
class Foo6<T>
class Bar6<T>(val value: Foo6<T>)
operator fun <T> Foo6<T>.invoke(x: Int) {}
fun main(x: Bar6<String>?) {
x?.value(1)
x?.value<!UNSAFE_CALL!>.<!>invoke(1)
}
// Test case 7: top-level generic invoke and invoke with compatible additional dispatch recevier
class Foo7<T>
class Bar7<T>(val value: Foo7<T>)
class Another7 {
operator fun <T> Foo7<T>.invoke(x: Int) {}
}
operator fun <T> Foo7<T>.invoke(x: Int) {}
fun Another7.main(x: Bar7<String>?) {
x?.value(1)
x?.value<!UNSAFE_CALL!>.<!>invoke(1)
}
// Test case 8: top-level non-generic invoke
class Foo8<T>
class Bar8<T>(val value: Foo8<T>)
operator fun Foo8<String>.invoke(x: Int) {}
fun main(x: Bar8<String>?) {
x?.value(1)
x?.value<!UNSAFE_CALL!>.<!>invoke(1)
}
// Test case 9: additional receiver, generic invoke with pure type perameter receiver
class Foo9<T>
class Bar9<T>(val value: Foo9<T>)
class Another9 {
operator fun <T> T.invoke(handler: () -> Unit) {}
}
fun Another9.main(x: Bar9<String>?) {
x?.value {}
x?.value.invoke({})
}
// Test case 10: additional receiver, generic invoke with upper bound
class Foo10<T>
class Bar10<T>(val value: Foo10<T>)
class Another10 {
operator fun <T: Any> Foo10<T>.invoke(handler: () -> Unit) {}
}
fun Another10.main(x: Bar10<String>?) {
x?.value {}
x?.value<!UNSAFE_CALL!>.<!>invoke({})
}
@@ -0,0 +1,229 @@
package
public fun main(/*0*/ x: Bar6<kotlin.String>?): kotlin.Unit
public fun main(/*0*/ x: Bar8<kotlin.String>?): kotlin.Unit
public operator fun </*0*/ T> Foo6<T>.invoke(/*0*/ x: kotlin.Int): kotlin.Unit
public operator fun </*0*/ T> Foo7<T>.invoke(/*0*/ x: kotlin.Int): kotlin.Unit
public operator fun Foo8<kotlin.String>.invoke(/*0*/ x: kotlin.Int): kotlin.Unit
public fun Another1.main(/*0*/ x: Bar1<kotlin.String>?): kotlin.Unit
public fun Another10.main(/*0*/ x: Bar10<kotlin.String>?): kotlin.Unit
public fun Another2.main(/*0*/ x: Bar2<kotlin.String>?): kotlin.Unit
public fun </*0*/ K> Another3<K>.main(/*0*/ x: Bar3<K>?): kotlin.Unit
public fun </*0*/ K> Another4<K>.main(/*0*/ x: Bar4<K>?): kotlin.Unit
public fun Another5.main(/*0*/ x: Bar5?): kotlin.Unit
public fun Another7.main(/*0*/ x: Bar7<kotlin.String>?): kotlin.Unit
public fun Another9.main(/*0*/ x: Bar9<kotlin.String>?): kotlin.Unit
public final class Another1 {
public constructor Another1()
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 operator fun </*0*/ T> Foo1<T>.invoke(/*0*/ handler: () -> kotlin.Unit): kotlin.Unit
}
public final class Another10 {
public constructor Another10()
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 operator fun </*0*/ T : kotlin.Any> Foo10<T>.invoke(/*0*/ handler: () -> kotlin.Unit): kotlin.Unit
}
public final class Another2 {
public constructor Another2()
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 operator fun Foo2<kotlin.String>.invoke(/*0*/ x: kotlin.Int): kotlin.Unit
}
public final class Another3</*0*/ T> {
public constructor Another3</*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 operator fun Foo3<T>.invoke(/*0*/ x: kotlin.Int): kotlin.Unit
}
public final class Another4</*0*/ T> {
public constructor Another4</*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 operator fun Foo4<T>?.invoke(/*0*/ x: kotlin.Int): kotlin.Unit
}
public final class Another5 {
public constructor Another5()
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 operator fun </*0*/ T> Foo5.invoke(/*0*/ handler: T): kotlin.Unit
}
public final class Another7 {
public constructor Another7()
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 operator fun </*0*/ T> Foo7<T>.invoke(/*0*/ x: kotlin.Int): kotlin.Unit
}
public final class Another9 {
public constructor Another9()
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 operator fun </*0*/ T> T.invoke(/*0*/ handler: () -> kotlin.Unit): kotlin.Unit
}
public final class Bar1</*0*/ T> {
public constructor Bar1</*0*/ T>(/*0*/ value: Foo1<T>)
public final val value: Foo1<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 Bar10</*0*/ T> {
public constructor Bar10</*0*/ T>(/*0*/ value: Foo10<T>)
public final val value: Foo10<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 Bar2</*0*/ T> {
public constructor Bar2</*0*/ T>(/*0*/ value: Foo2<T>)
public final val value: Foo2<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 Bar3</*0*/ T> {
public constructor Bar3</*0*/ T>(/*0*/ value: Foo3<T>)
public final val value: Foo3<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 Bar4</*0*/ T> {
public constructor Bar4</*0*/ T>(/*0*/ value: Foo4<T>)
public final val value: Foo4<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 Bar5 {
public constructor Bar5(/*0*/ value: Foo5)
public final val value: Foo5
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 Bar6</*0*/ T> {
public constructor Bar6</*0*/ T>(/*0*/ value: Foo6<T>)
public final val value: Foo6<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 Bar7</*0*/ T> {
public constructor Bar7</*0*/ T>(/*0*/ value: Foo7<T>)
public final val value: Foo7<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 Bar8</*0*/ T> {
public constructor Bar8</*0*/ T>(/*0*/ value: Foo8<T>)
public final val value: Foo8<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 Bar9</*0*/ T> {
public constructor Bar9</*0*/ T>(/*0*/ value: Foo9<T>)
public final val value: Foo9<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 Foo1</*0*/ T> {
public constructor Foo1</*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 Foo10</*0*/ T> {
public constructor Foo10</*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 Foo2</*0*/ T> {
public constructor Foo2</*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 Foo3</*0*/ T> {
public constructor Foo3</*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 Foo4</*0*/ T> {
public constructor Foo4</*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 Foo5 {
public constructor Foo5()
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 Foo6</*0*/ T> {
public constructor Foo6</*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 Foo7</*0*/ T> {
public constructor Foo7</*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 Foo8</*0*/ T> {
public constructor Foo8</*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 Foo9</*0*/ T> {
public constructor Foo9</*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
}
@@ -18802,6 +18802,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
runTest("compiler/testData/diagnostics/tests/resolve/invoke/implicitInvoke.kt");
}
@TestMetadata("implicitInvokeAfterSafeCall.kt")
public void testImplicitInvokeAfterSafeCall() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/invoke/implicitInvokeAfterSafeCall.kt");
}
@TestMetadata("invokeAndSmartCast.kt")
public void testInvokeAndSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/invoke/invokeAndSmartCast.kt");
@@ -18792,6 +18792,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
runTest("compiler/testData/diagnostics/tests/resolve/invoke/implicitInvoke.kt");
}
@TestMetadata("implicitInvokeAfterSafeCall.kt")
public void testImplicitInvokeAfterSafeCall() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/invoke/implicitInvokeAfterSafeCall.kt");
}
@TestMetadata("invokeAndSmartCast.kt")
public void testInvokeAndSmartCast() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/invoke/invokeAndSmartCast.kt");