NI: Allow to resolve to functions with SAM conversion and passing array without spread as vararg (with warning)

^KT-35224 Fixed
This commit is contained in:
Victor Petukhov
2019-12-04 20:29:03 +03:00
parent fe875d628d
commit 07269661b4
33 changed files with 573 additions and 27 deletions
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
@@ -45,6 +47,7 @@ class KotlinCallCompleter(
candidate.addExpectedTypeConstraint(returnType, expectedType)
candidate.addExpectedTypeFromCastConstraint(returnType, resolutionCallbacks)
candidate.checkSamWithVararg(diagnosticHolder)
return if (resolutionCallbacks.inferenceSession.shouldRunCompletion(candidate))
candidate.runCompletion(
@@ -56,6 +59,22 @@ class KotlinCallCompleter(
candidate.asCallResolutionResult(ConstraintSystemCompletionMode.PARTIAL, diagnosticHolder)
}
private fun KotlinResolutionCandidate.checkSamWithVararg(diagnosticHolder: KotlinDiagnosticsHolder.SimpleHolder) {
val samConversionPerArgumentWithWarningsForVarargAfterSam =
callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument) &&
!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitVarargAsArrayAfterSamArgument)
if (samConversionPerArgumentWithWarningsForVarargAfterSam && resolvedCall.candidateDescriptor is SyntheticMemberDescriptor<*>) {
val declarationDescriptor = resolvedCall.candidateDescriptor.baseDescriptorForSynthetic as? FunctionDescriptor ?: return
if (declarationDescriptor.valueParameters.lastOrNull()?.isVararg == true) {
diagnosticHolder.addDiagnostic(
ResolvedToSamWithVarargDiagnostic(resolvedCall.atom.argumentsInParenthesis.lastOrNull() ?: return)
)
}
}
}
fun createAllCandidatesResult(
candidates: Collection<KotlinResolutionCandidate>,
expectedType: UnwrappedType?,
@@ -294,7 +294,11 @@ private fun KotlinResolutionCandidate.getExpectedTypeWithSAMConversion(
argument: KotlinCallArgument,
candidateParameter: ParameterDescriptor
): UnwrappedType? {
if (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument)) return null
val generatingAdditionalSamCandidateIsEnabled =
!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument) &&
!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitVarargAsArrayAfterSamArgument)
if (generatingAdditionalSamCandidateIsEnabled) return null
if (!callComponents.samConversionTransformer.shouldRunSamConversionForFunction(resolvedCall.candidateDescriptor)) return null
val argumentIsFunctional = when (argument) {
@@ -202,4 +202,10 @@ class OnlyInputTypesDiagnostic(val typeVariable: NewTypeVariable) : KotlinCallDi
override fun report(reporter: DiagnosticReporter) {
reporter.onCall(this)
}
}
}
class ResolvedToSamWithVarargDiagnostic(val argument: KotlinCallArgument) : KotlinCallDiagnostic(RESOLVED_TO_SAM_WITH_VARARG) {
override fun report(reporter: DiagnosticReporter) {
reporter.onCallArgument(argument, this)
}
}
@@ -83,6 +83,7 @@ enum class ResolutionCandidateApplicability {
INAPPLICABLE_ARGUMENTS_MAPPING_ERROR, // arguments not mapped to parameters (i.e. different size of arguments and parameters)
INAPPLICABLE_WRONG_RECEIVER, // receiver not matched
HIDDEN, // removed from resolve
RESOLVED_TO_SAM_WITH_VARARG, // migration warning up to 1.5 (when resolve to function with SAM conversion and array without spread as vararg)
}
abstract class ResolutionDiagnostic(candidateApplicability: ResolutionCandidateApplicability) :