Add compatibility warning for SAM conversions on Kotlin functions

This commit is contained in:
Mikhail Zarechenskiy
2020-05-29 14:15:35 +03:00
parent 080d8fa127
commit 01de789c76
15 changed files with 467 additions and 2 deletions
@@ -11,6 +11,7 @@ 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
@@ -86,6 +87,10 @@ object SamTypeConversions : ParameterTypeConversion {
SamConversionDescription(convertedTypeByOriginal, convertedTypeByCandidate!!)
)
if (needCompatibilityResolve(candidate, expectedParameterType)) {
candidate.addDiagnostic(LowerPriorityToPreserveCompatibility)
}
val samDescriptor = originalExpectedType.constructor.declarationDescriptor
if (samDescriptor is ClassDescriptor) {
callComponents.lookupTracker.record(candidate.scopeTower.location, samDescriptor, SAM_LOOKUP_NAME)
@@ -93,4 +98,13 @@ object SamTypeConversions : ParameterTypeConversion {
return convertedTypeByCandidate
}
private fun needCompatibilityResolve(candidate: KotlinResolutionCandidate, typeToConvert: UnwrappedType): Boolean {
// fun interfaces is a new feature with a new modifier, so no compatibility resolve is needed
val descriptor = typeToConvert.constructor.declarationDescriptor
if (descriptor is ClassDescriptor && descriptor.isFun) return false
// now conversions for Kotlin candidates are possible, so we have to perform compatibility resolve
return !candidate.callComponents.samConversionOracle.isJavaApplicableCandidate(candidate.resolvedCall.candidateDescriptor)
}
}
@@ -19,8 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.inference.model
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.INAPPLICABLE
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.*
import org.jetbrains.kotlin.resolve.scopes.receivers.DetailedReceiver
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
@@ -123,3 +122,5 @@ class ConstrainingTypeIsError(
val constraintType: KotlinTypeMarker,
val position: IncorporationConstraintPosition
) : ConstraintSystemCallDiagnostic(INAPPLICABLE)
object LowerPriorityToPreserveCompatibility : ConstraintSystemCallDiagnostic(RESOLVED_NEED_PRESERVE_COMPATIBILITY)
@@ -86,6 +86,7 @@ fun getResultApplicability(diagnostics: Collection<KotlinCallDiagnostic>) =
enum class ResolutionCandidateApplicability {
RESOLVED, // call success or has uncompleted inference or in other words possible successful candidate
RESOLVED_WITH_ERROR, // call has error, but it is still successful from resolution perspective
RESOLVED_NEED_PRESERVE_COMPATIBILITY, // call resolved successfully, but using new features that changes resolve
RESOLVED_LOW_PRIORITY,
CONVENTION_ERROR, // missing infix, operator etc
MAY_THROW_RUNTIME_ERROR, // unsafe call or unstable smart cast
@@ -120,6 +121,7 @@ class UsedSmartCastForDispatchReceiver(val smartCastType: KotlinType) : Resoluti
object ErrorDescriptorDiagnostic : ResolutionDiagnostic(RESOLVED) // todo discuss and change to INAPPLICABLE
object LowPriorityDescriptorDiagnostic : ResolutionDiagnostic(RESOLVED_LOW_PRIORITY)
object DynamicDescriptorDiagnostic : ResolutionDiagnostic(RESOLVED_LOW_PRIORITY)
object ResolvedUsingNewFeatures : ResolutionDiagnostic(RESOLVED_NEED_PRESERVE_COMPATIBILITY)
object UnstableSmartCastDiagnostic : ResolutionDiagnostic(RESOLVED_WITH_ERROR)
object HiddenExtensionRelatedToDynamicTypes : ResolutionDiagnostic(HIDDEN)
object HiddenDescriptor : ResolutionDiagnostic(HIDDEN)