Add compatibility resolve when SAM conversion was applied partially

#KT-40646 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2020-08-04 11:50:02 +03:00
parent 070848a1c1
commit a45f73867a
9 changed files with 140 additions and 1 deletions
@@ -273,6 +273,28 @@ internal object CompatibilityOfTypeVariableAsIntersectionTypePart : ResolutionPa
}
}
internal object CompatibilityOfPartiallyApplicableSamConversion : ResolutionPart() {
override fun KotlinResolutionCandidate.process(workIndex: Int) {
if (resolvedCall.argumentsWithConversion.isEmpty()) return
if (resolvedCall.argumentsWithConversion.size == candidateDescriptor.valueParameters.size) return
for (argument in kotlinCall.argumentsInParenthesis) {
if (resolvedCall.argumentsWithConversion[argument] != null) continue
val expectedParameterType = argument.getExpectedType(
resolvedCall.argumentToCandidateParameter[argument] ?: continue,
callComponents.languageVersionSettings
)
// argument for the parameter doesn't have a conversion but parameter can be converted => we need a compatibility resolve
if (SamTypeConversions.isJavaParameterCanBeConverted(this, expectedParameterType)) {
markCandidateForCompatibilityResolve()
return
}
}
}
}
internal object CheckExplicitReceiverKindConsistency : ResolutionPart() {
private fun KotlinResolutionCandidate.hasError(): Nothing =
error(
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.incremental.record
import org.jetbrains.kotlin.resolve.calls.inference.model.LowerPriorityToPreserveCompatibility
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.sam.SAM_LOOKUP_NAME
import org.jetbrains.kotlin.resolve.sam.getFunctionTypeForPossibleSamType
@@ -127,4 +126,25 @@ object SamTypeConversions : ParameterTypeConversion {
// now conversions for Kotlin candidates are possible, so we have to perform compatibility resolve
return !candidate.callComponents.samConversionOracle.isJavaApplicableCandidate(candidate.resolvedCall.candidateDescriptor)
}
fun isJavaParameterCanBeConverted(
candidate: KotlinResolutionCandidate,
expectedParameterType: UnwrappedType
): Boolean {
val callComponents = candidate.callComponents
val samConversionOracle = callComponents.samConversionOracle
if (!samConversionOracle.isJavaApplicableCandidate(candidate.resolvedCall.candidateDescriptor)) return false
val declarationDescriptor = expectedParameterType.constructor.declarationDescriptor
if (declarationDescriptor is ClassDescriptor && declarationDescriptor.isDefinitelyNotSamInterface) return false
val convertedType =
callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(
expectedParameterType,
callComponents.samConversionOracle
)
return convertedType != null
}
}
@@ -229,6 +229,7 @@ enum class KotlinCallKind(vararg resolutionPart: ResolutionPart) {
CheckExternalArgument,
EagerResolveOfCallableReferences,
CompatibilityOfTypeVariableAsIntersectionTypePart,
CompatibilityOfPartiallyApplicableSamConversion,
PostponedVariablesInitializerResolutionPart
),
INVOKE(*FUNCTION.resolutionSequence.toTypedArray()),