[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:
Generated
+10
@@ -18652,6 +18652,16 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/invoke/KT-4372.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt30695.kt")
|
||||
public void testKt30695() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/invoke/kt30695.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt30695_2.kt")
|
||||
public void testKt30695_2() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/invoke/kt30695_2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt3772.kt")
|
||||
public void testKt3772() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/invoke/kt3772.kt");
|
||||
|
||||
+8
-3
@@ -104,9 +104,14 @@ class DiagnosticReporterByTrackingStrategy(
|
||||
override fun onCallReceiver(callReceiver: SimpleKotlinCallArgument, diagnostic: KotlinCallDiagnostic) {
|
||||
when (diagnostic.javaClass) {
|
||||
UnsafeCallError::class.java -> {
|
||||
val implicitInvokeCheck = (callReceiver as? ReceiverExpressionKotlinCallArgument)?.isForImplicitInvoke
|
||||
?: callReceiver.receiver.receiverValue.type.isExtensionFunctionType
|
||||
tracingStrategy.unsafeCall(trace, callReceiver.receiver.receiverValue.type, implicitInvokeCheck)
|
||||
val unsafeCallErrorDiagnostic = diagnostic.cast<UnsafeCallError>()
|
||||
val isForImplicitInvoke = when (callReceiver) {
|
||||
is ReceiverExpressionKotlinCallArgument -> callReceiver.isForImplicitInvoke
|
||||
else -> unsafeCallErrorDiagnostic.isForImplicitInvoke
|
||||
|| callReceiver.receiver.receiverValue.type.isExtensionFunctionType
|
||||
}
|
||||
|
||||
tracingStrategy.unsafeCall(trace, callReceiver.receiver.receiverValue.type, isForImplicitInvoke)
|
||||
}
|
||||
|
||||
SuperAsExtensionReceiver::class.java -> {
|
||||
|
||||
+3
-3
@@ -35,11 +35,11 @@ fun resolveKtPrimitive(
|
||||
argument: KotlinCallArgument,
|
||||
expectedType: UnwrappedType?,
|
||||
diagnosticsHolder: KotlinDiagnosticsHolder,
|
||||
isReceiver: Boolean,
|
||||
convertedType: UnwrappedType?
|
||||
receiverInfo: ReceiverInfo,
|
||||
convertedType: UnwrappedType?,
|
||||
): ResolvedAtom = when (argument) {
|
||||
is SimpleKotlinCallArgument ->
|
||||
checkSimpleArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver, convertedType)
|
||||
checkSimpleArgument(csBuilder, argument, expectedType, diagnosticsHolder, receiverInfo, convertedType)
|
||||
|
||||
is LambdaKotlinCallArgument ->
|
||||
preprocessLambdaArgument(csBuilder, argument, expectedType, diagnosticsHolder)
|
||||
|
||||
+1
-1
@@ -132,7 +132,7 @@ class PostponedArgumentsAnalyzer(
|
||||
|
||||
val subResolvedKtPrimitives = returnArgumentsInfo.nonErrorArguments.map {
|
||||
resolveKtPrimitive(
|
||||
c.getBuilder(), it, lambda.returnType.let(::substitute), diagnosticHolder, isReceiver = false, convertedType = null
|
||||
c.getBuilder(), it, lambda.returnType.let(::substitute), diagnosticHolder, ReceiverInfo.notReceiver, convertedType = null
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+54
-11
@@ -288,7 +288,7 @@ internal object CheckExplicitReceiverKindConsistency : ResolutionPart() {
|
||||
private fun KotlinResolutionCandidate.resolveKotlinArgument(
|
||||
argument: KotlinCallArgument,
|
||||
candidateParameter: ParameterDescriptor?,
|
||||
isReceiver: Boolean
|
||||
receiverInfo: ReceiverInfo
|
||||
) {
|
||||
val expectedType = candidateParameter?.let { prepareExpectedType(argument, candidateParameter) }
|
||||
val convertedArgument = if (expectedType != null && shouldRunConversionForConstants(expectedType)) {
|
||||
@@ -306,7 +306,7 @@ private fun KotlinResolutionCandidate.resolveKotlinArgument(
|
||||
argument,
|
||||
expectedType,
|
||||
this,
|
||||
isReceiver,
|
||||
receiverInfo,
|
||||
convertedArgument?.unknownIntegerType?.unwrap()
|
||||
)
|
||||
)
|
||||
@@ -327,6 +327,30 @@ private fun KotlinResolutionCandidate.shouldRunConversionForConstants(expectedTy
|
||||
return false
|
||||
}
|
||||
|
||||
internal enum class ImplicitInvokeCheckStatus {
|
||||
NO_INVOKE, INVOKE_ON_NOT_NULL_VARIABLE, UNSAFE_INVOKE_REPORTED
|
||||
}
|
||||
|
||||
private fun KotlinResolutionCandidate.checkUnsafeImplicitInvokeAfterSafeCall(argument: SimpleKotlinCallArgument): ImplicitInvokeCheckStatus {
|
||||
val variableForInvoke = variableCandidateIfInvoke ?: return ImplicitInvokeCheckStatus.NO_INVOKE
|
||||
|
||||
val receiverArgument = with(variableForInvoke.resolvedCall) {
|
||||
when (explicitReceiverKind) {
|
||||
DISPATCH_RECEIVER -> dispatchReceiverArgument
|
||||
EXTENSION_RECEIVER,
|
||||
BOTH_RECEIVERS -> extensionReceiverArgument
|
||||
NO_EXPLICIT_RECEIVER -> return ImplicitInvokeCheckStatus.INVOKE_ON_NOT_NULL_VARIABLE
|
||||
}
|
||||
} ?: error("Receiver kind does not match receiver argument")
|
||||
|
||||
if (receiverArgument.receiver.stableType.isNullable()) {
|
||||
addDiagnostic(UnsafeCallError(argument, isForImplicitInvoke = true))
|
||||
return ImplicitInvokeCheckStatus.UNSAFE_INVOKE_REPORTED
|
||||
}
|
||||
|
||||
return ImplicitInvokeCheckStatus.INVOKE_ON_NOT_NULL_VARIABLE
|
||||
}
|
||||
|
||||
private fun KotlinResolutionCandidate.prepareExpectedType(
|
||||
argument: KotlinCallArgument,
|
||||
candidateParameter: ParameterDescriptor
|
||||
@@ -388,21 +412,40 @@ private fun KotlinResolutionCandidate.getExpectedTypeWithSAMConversion(
|
||||
internal object CheckReceivers : ResolutionPart() {
|
||||
private fun KotlinResolutionCandidate.checkReceiver(
|
||||
receiverArgument: SimpleKotlinCallArgument?,
|
||||
receiverParameter: ReceiverParameterDescriptor?
|
||||
receiverParameter: ReceiverParameterDescriptor?,
|
||||
shouldCheckImplicitInvoke: Boolean,
|
||||
) {
|
||||
if ((receiverArgument == null) != (receiverParameter == null)) {
|
||||
error("Inconsistency receiver state for call $kotlinCall and candidate descriptor: $candidateDescriptor")
|
||||
}
|
||||
if (receiverArgument == null || receiverParameter == null) return
|
||||
|
||||
resolveKotlinArgument(receiverArgument, receiverParameter, isReceiver = true)
|
||||
val implicitInvokeState = if (shouldCheckImplicitInvoke) {
|
||||
checkUnsafeImplicitInvokeAfterSafeCall(receiverArgument)
|
||||
} else ImplicitInvokeCheckStatus.NO_INVOKE
|
||||
|
||||
val receiverInfo = ReceiverInfo(
|
||||
isReceiver = true,
|
||||
shouldReportUnsafeCall = implicitInvokeState != ImplicitInvokeCheckStatus.UNSAFE_INVOKE_REPORTED,
|
||||
reportUnsafeCallAsUnsafeImplicitInvoke = implicitInvokeState == ImplicitInvokeCheckStatus.INVOKE_ON_NOT_NULL_VARIABLE
|
||||
)
|
||||
|
||||
resolveKotlinArgument(receiverArgument, receiverParameter, receiverInfo)
|
||||
}
|
||||
|
||||
override fun KotlinResolutionCandidate.process(workIndex: Int) {
|
||||
if (workIndex == 0) {
|
||||
checkReceiver(resolvedCall.dispatchReceiverArgument, candidateDescriptor.dispatchReceiverParameter)
|
||||
checkReceiver(
|
||||
resolvedCall.dispatchReceiverArgument,
|
||||
candidateDescriptor.dispatchReceiverParameter,
|
||||
shouldCheckImplicitInvoke = true,
|
||||
)
|
||||
} else {
|
||||
checkReceiver(resolvedCall.extensionReceiverArgument, candidateDescriptor.extensionReceiverParameter)
|
||||
checkReceiver(
|
||||
resolvedCall.extensionReceiverArgument,
|
||||
candidateDescriptor.extensionReceiverParameter,
|
||||
shouldCheckImplicitInvoke = false, // reproduce old inference behaviour
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,7 +455,7 @@ internal object CheckReceivers : ResolutionPart() {
|
||||
internal object CheckArgumentsInParenthesis : ResolutionPart() {
|
||||
override fun KotlinResolutionCandidate.process(workIndex: Int) {
|
||||
val argument = kotlinCall.argumentsInParenthesis[workIndex]
|
||||
resolveKotlinArgument(argument, resolvedCall.argumentToCandidateParameter[argument], isReceiver = false)
|
||||
resolveKotlinArgument(argument, resolvedCall.argumentToCandidateParameter[argument], ReceiverInfo.notReceiver)
|
||||
}
|
||||
|
||||
override fun KotlinResolutionCandidate.workCount() = kotlinCall.argumentsInParenthesis.size
|
||||
@@ -422,7 +465,7 @@ internal object CheckExternalArgument : ResolutionPart() {
|
||||
override fun KotlinResolutionCandidate.process(workIndex: Int) {
|
||||
val argument = kotlinCall.externalArgument ?: return
|
||||
|
||||
resolveKotlinArgument(argument, resolvedCall.argumentToCandidateParameter[argument], isReceiver = false)
|
||||
resolveKotlinArgument(argument, resolvedCall.argumentToCandidateParameter[argument], ReceiverInfo.notReceiver)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,14 +528,14 @@ internal object ErrorDescriptorResolutionPart : ResolutionPart() {
|
||||
resolvedCall.argumentToCandidateParameter = emptyMap()
|
||||
|
||||
kotlinCall.explicitReceiver?.safeAs<SimpleKotlinCallArgument>()?.let {
|
||||
resolveKotlinArgument(it, null, isReceiver = true)
|
||||
resolveKotlinArgument(it, null, ReceiverInfo.notReceiver)
|
||||
}
|
||||
for (argument in kotlinCall.argumentsInParenthesis) {
|
||||
resolveKotlinArgument(argument, null, isReceiver = true)
|
||||
resolveKotlinArgument(argument, null, ReceiverInfo.notReceiver)
|
||||
}
|
||||
|
||||
kotlinCall.externalArgument?.let {
|
||||
resolveKotlinArgument(it, null, isReceiver = true)
|
||||
resolveKotlinArgument(it, null, ReceiverInfo.notReceiver)
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
-8
@@ -31,17 +31,30 @@ import org.jetbrains.kotlin.types.checker.hasSupertypeWithGivenTypeConstructor
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||
|
||||
class ReceiverInfo(
|
||||
val isReceiver: Boolean,
|
||||
val shouldReportUnsafeCall: Boolean, // should not report if unsafe implicit invoke has been reported already
|
||||
val reportUnsafeCallAsUnsafeImplicitInvoke: Boolean,
|
||||
) {
|
||||
init {
|
||||
assert(!reportUnsafeCallAsUnsafeImplicitInvoke || shouldReportUnsafeCall) { "Inconsistent receiver info" }
|
||||
}
|
||||
|
||||
companion object {
|
||||
val notReceiver = ReceiverInfo(isReceiver = false, shouldReportUnsafeCall = true, reportUnsafeCallAsUnsafeImplicitInvoke = false)
|
||||
}
|
||||
}
|
||||
|
||||
fun checkSimpleArgument(
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
argument: SimpleKotlinCallArgument,
|
||||
expectedType: UnwrappedType?,
|
||||
diagnosticsHolder: KotlinDiagnosticsHolder,
|
||||
isReceiver: Boolean,
|
||||
receiverInfo: ReceiverInfo,
|
||||
convertedType: UnwrappedType?
|
||||
): ResolvedAtom = when (argument) {
|
||||
is ExpressionKotlinCallArgument -> checkExpressionArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver, convertedType)
|
||||
is SubKotlinCallArgument -> checkSubCallArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver)
|
||||
is ExpressionKotlinCallArgument -> checkExpressionArgument(csBuilder, argument, expectedType, diagnosticsHolder, receiverInfo.isReceiver, convertedType)
|
||||
is SubKotlinCallArgument -> checkSubCallArgument(csBuilder, argument, expectedType, diagnosticsHolder, receiverInfo)
|
||||
else -> unexpectedArgument(argument)
|
||||
}
|
||||
|
||||
@@ -164,14 +177,14 @@ private fun checkSubCallArgument(
|
||||
subCallArgument: SubKotlinCallArgument,
|
||||
expectedType: UnwrappedType?,
|
||||
diagnosticsHolder: KotlinDiagnosticsHolder,
|
||||
isReceiver: Boolean
|
||||
receiverInfo: ReceiverInfo,
|
||||
): ResolvedAtom {
|
||||
val subCallResult = subCallArgument.callResult
|
||||
|
||||
if (expectedType == null) return subCallResult
|
||||
|
||||
val expectedNullableType = expectedType.makeNullableAsSpecified(true)
|
||||
val position = if (isReceiver) ReceiverConstraintPosition(subCallArgument) else ArgumentConstraintPosition(subCallArgument)
|
||||
val position = if (receiverInfo.isReceiver) ReceiverConstraintPosition(subCallArgument) else ArgumentConstraintPosition(subCallArgument)
|
||||
|
||||
// subArgument cannot has stable smartcast
|
||||
// return type can contains fixed type variables
|
||||
@@ -183,10 +196,15 @@ private fun checkSubCallArgument(
|
||||
return subCallResult
|
||||
}
|
||||
|
||||
if (isReceiver && !csBuilder.addSubtypeConstraintIfCompatible(currentReturnType, expectedType, position) &&
|
||||
csBuilder.addSubtypeConstraintIfCompatible(currentReturnType, expectedNullableType, position)
|
||||
if (receiverInfo.isReceiver
|
||||
&& !csBuilder.addSubtypeConstraintIfCompatible(currentReturnType, expectedType, position)
|
||||
&& csBuilder.addSubtypeConstraintIfCompatible(currentReturnType, expectedNullableType, position)
|
||||
) {
|
||||
diagnosticsHolder.addDiagnostic(UnsafeCallError(subCallArgument))
|
||||
if (receiverInfo.shouldReportUnsafeCall) {
|
||||
diagnosticsHolder.addDiagnostic(
|
||||
UnsafeCallError(subCallArgument, isForImplicitInvoke = receiverInfo.reportUnsafeCallAsUnsafeImplicitInvoke)
|
||||
)
|
||||
}
|
||||
return subCallResult
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -145,7 +145,10 @@ class UnstableSmartCast(
|
||||
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this)
|
||||
}
|
||||
|
||||
class UnsafeCallError(val receiver: SimpleKotlinCallArgument) : KotlinCallDiagnostic(MAY_THROW_RUNTIME_ERROR) {
|
||||
class UnsafeCallError(
|
||||
val receiver: SimpleKotlinCallArgument,
|
||||
val isForImplicitInvoke: Boolean = false
|
||||
) : KotlinCallDiagnostic(MAY_THROW_RUNTIME_ERROR) {
|
||||
override fun report(reporter: DiagnosticReporter) = reporter.onCallReceiver(receiver, this)
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
+14
-14
@@ -370,23 +370,23 @@ fun case_21() {
|
||||
// TESTCASE NUMBER: 22
|
||||
fun case_22(a: (() -> Unit)?) {
|
||||
if (<!EQUALITY_NOT_APPLICABLE!>a != null !is Boolean<!>) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_CALL!>a<!>()<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_CALL!>a<!>()<!>.equals(null)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_CALL!>a<!>()<!>.propT
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_CALL!>a<!>()<!>.propAny
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_CALL!>a<!>()<!>.propNullableT
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_CALL!>a<!>()<!>.propNullableAny
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_CALL!>a<!>()<!>.funT()
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_CALL!>a<!>()<!>.funAny()
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_CALL!>a<!>()<!>.funNullableT()
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_CALL!>a<!>()<!>.funNullableAny()
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>()<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>()<!>.equals(null)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>()<!>.propT
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>()<!>.propAny
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>()<!>.propNullableT
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>()<!>.propNullableAny
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>()<!>.funT()
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>()<!>.funAny()
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>()<!>.funNullableT()
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>()<!>.funNullableAny()
|
||||
}
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 23
|
||||
fun case_23(a: ((Float) -> Int?)?, b: Float?) {
|
||||
if (<!EQUALITY_NOT_APPLICABLE!>a != null !is Boolean<!> && <!EQUALITY_NOT_APPLICABLE!>b !== null is Boolean<!>) {
|
||||
val x = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!><!UNSAFE_CALL!>a<!>(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Float?"), TYPE_MISMATCH!>b<!>)<!>
|
||||
val x = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Float?"), TYPE_MISMATCH!>b<!>)<!>
|
||||
if (x != null) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int & kotlin.Int?")!>x<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int & kotlin.Int?"), DEBUG_INFO_SMARTCAST!>x<!>.equals(null)
|
||||
@@ -405,8 +405,8 @@ fun case_23(a: ((Float) -> Int?)?, b: Float?) {
|
||||
// TESTCASE NUMBER: 24
|
||||
fun case_24(a: ((() -> Unit) -> Unit)?, b: (() -> Unit)?) =
|
||||
if (<!EQUALITY_NOT_APPLICABLE!>a !== null is Boolean<!> && <!EQUALITY_NOT_APPLICABLE!>b !== null !is Boolean<!>) {
|
||||
<!UNSAFE_CALL!>a<!>(<!DEBUG_INFO_EXPRESSION_TYPE("(() -> kotlin.Unit)?"), TYPE_MISMATCH!>b<!>)
|
||||
<!UNSAFE_CALL!>a<!>(<!TYPE_MISMATCH!>b<!>)
|
||||
<!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>(<!DEBUG_INFO_EXPRESSION_TYPE("(() -> kotlin.Unit)?"), TYPE_MISMATCH!>b<!>)
|
||||
<!UNSAFE_IMPLICIT_INVOKE_CALL!>a<!>(<!TYPE_MISMATCH!>b<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(() -> kotlin.Unit)?")!>b<!><!UNSAFE_CALL!>.<!>equals(null)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(() -> kotlin.Unit)?")!>b<!>.propT
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(() -> kotlin.Unit)?")!>b<!><!UNSAFE_CALL!>.<!>propAny
|
||||
@@ -429,7 +429,7 @@ fun case_25(b: Boolean) {
|
||||
val y = if (b) x else null
|
||||
|
||||
if (<!DEPRECATED_IDENTITY_EQUALS!>y !== null === true<!>) {
|
||||
val z = <!DEBUG_INFO_EXPRESSION_TYPE("case_25.<anonymous>.<no name provided>?")!><!UNSAFE_CALL!>y<!>()<!>
|
||||
val z = <!DEBUG_INFO_EXPRESSION_TYPE("case_25.<anonymous>.<no name provided>?")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>y<!>()<!>
|
||||
|
||||
if (<!DEPRECATED_IDENTITY_EQUALS!>z != null !== false<!>) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("case_25.<anonymous>.<no name provided>?")!>z<!><!UNSAFE_CALL!>.<!>a
|
||||
|
||||
@@ -76,7 +76,7 @@ fun case_3(b: Boolean) {
|
||||
val y = if (b) x else null
|
||||
|
||||
if (false || false || false || false || y !== null) {
|
||||
val z = <!DEBUG_INFO_EXPRESSION_TYPE("case_3.<anonymous>.<no name provided>?")!><!UNSAFE_CALL!>y<!>()<!>
|
||||
val z = <!DEBUG_INFO_EXPRESSION_TYPE("case_3.<anonymous>.<no name provided>?")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>y<!>()<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(() -> case_3.<anonymous>.<no name provided>?)?")!>y<!><!UNSAFE_CALL!>.<!>equals(null)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(() -> case_3.<anonymous>.<no name provided>?)?")!>y<!>.propT
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(() -> case_3.<anonymous>.<no name provided>?)?")!>y<!><!UNSAFE_CALL!>.<!>propAny
|
||||
@@ -283,7 +283,7 @@ fun case_11(b: Boolean) {
|
||||
val y = if (b) x else null
|
||||
|
||||
if (y === null && true) else {
|
||||
val z = <!DEBUG_INFO_EXPRESSION_TYPE("case_11.<anonymous>.<no name provided>?")!><!UNSAFE_CALL!>y<!>()<!>
|
||||
val z = <!DEBUG_INFO_EXPRESSION_TYPE("case_11.<anonymous>.<no name provided>?")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>y<!>()<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(() -> case_11.<anonymous>.<no name provided>?)?")!>y<!><!UNSAFE_CALL!>.<!>equals(null)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(() -> case_11.<anonymous>.<no name provided>?)?")!>y<!>.propT
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("(() -> case_11.<anonymous>.<no name provided>?)?")!>y<!><!UNSAFE_CALL!>.<!>propAny
|
||||
|
||||
@@ -583,7 +583,7 @@ fun case_29(x: Boolean) {
|
||||
val y = if (x) z else null
|
||||
|
||||
if (false || false || false || false || y !== <!DEBUG_INFO_CONSTANT!>v<!>) {
|
||||
val t = <!DEBUG_INFO_EXPRESSION_TYPE("case_29.<anonymous>.<no name provided>?")!><!UNSAFE_CALL!>y<!>()<!>
|
||||
val t = <!DEBUG_INFO_EXPRESSION_TYPE("case_29.<anonymous>.<no name provided>?")!><!UNSAFE_IMPLICIT_INVOKE_CALL!>y<!>()<!>
|
||||
|
||||
if (<!EQUALITY_NOT_APPLICABLE!>z !== t<!> || false) {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("case_29.<anonymous>.<no name provided>?")!>t<!><!UNSAFE_CALL!>.<!>a
|
||||
|
||||
@@ -18664,6 +18664,16 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/invoke/KT-4372.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt30695.kt")
|
||||
public void testKt30695() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/invoke/kt30695.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt30695_2.kt")
|
||||
public void testKt30695_2() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/invoke/kt30695_2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt3772.kt")
|
||||
public void testKt3772() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/invoke/kt3772.kt");
|
||||
|
||||
Generated
+10
@@ -18654,6 +18654,16 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/invoke/KT-4372.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt30695.kt")
|
||||
public void testKt30695() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/invoke/kt30695.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt30695_2.kt")
|
||||
public void testKt30695_2() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/invoke/kt30695_2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt3772.kt")
|
||||
public void testKt3772() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/invoke/kt3772.kt");
|
||||
|
||||
Reference in New Issue
Block a user