Call completer: safe call with nullable receiver has nullable return type #KT-11007 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
4cd7193047
commit
17593e4ef6
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.Constrain
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.filterConstraintsOut
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.toHandle
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.makeNullableTypeIfSafeReceiver
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
@@ -274,7 +275,10 @@ class CallCompleter(
|
||||
val results = completeCallForArgument(deparenthesized, context)
|
||||
if (results != null && results.isSingleResult) {
|
||||
val resolvedCall = results.resultingCall
|
||||
updatedType = if (resolvedCall.hasInferredReturnType()) resolvedCall.resultingDescriptor?.returnType else null
|
||||
updatedType = if (resolvedCall.hasInferredReturnType()) {
|
||||
resolvedCall.makeNullableTypeIfSafeReceiver(resolvedCall.resultingDescriptor?.returnType, context)
|
||||
}
|
||||
else null
|
||||
}
|
||||
|
||||
// For the cases like 'foo(1)' the type of '1' depends on expected type (it can be Int, Byte, etc.),
|
||||
|
||||
@@ -16,16 +16,22 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.resolvedCallUtil
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
import org.jetbrains.kotlin.psi.KtThisExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getOwnerForEffectiveDispatchReceiverParameter
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
|
||||
// it returns true if call has no dispatch receiver (e.g. resulting descriptor is top-level function or local variable)
|
||||
// or call receiver is effectively `this` instance (explicitly or implicitly) of resulting descriptor
|
||||
@@ -72,4 +78,14 @@ fun ResolvedCall<*>.getImplicitReceiverValue(): ReceiverValue? {
|
||||
}
|
||||
}
|
||||
|
||||
private fun ResolvedCall<*>.hasSafeNullableReceiver(context: CallResolutionContext<*>): Boolean {
|
||||
if (!isSafeCall) return false
|
||||
val receiverValue = getExplicitReceiverValue()?.let { DataFlowValueFactory.createDataFlowValue(it, context) }
|
||||
?: return false
|
||||
return context.dataFlowInfo.getPredictableNullability(receiverValue).canBeNull()
|
||||
}
|
||||
|
||||
fun ResolvedCall<*>.makeNullableTypeIfSafeReceiver(type: KotlinType?, context: CallResolutionContext<*>) =
|
||||
type?.let { TypeUtils.makeNullableIfNeeded(type, hasSafeNullableReceiver(context)) }
|
||||
|
||||
fun ResolvedCall<*>.hasBothReceivers() = dispatchReceiver != null && extensionReceiver != null
|
||||
Reference in New Issue
Block a user