Use the new type inference for top-level callable reference resolution

^KT-47797 Fixed
^KT-47987 Fixed
^KT-45034 Fixed
^KT-48446 Fixed
^KT-13934 Fixed
This commit is contained in:
Victor Petukhov
2021-09-20 17:13:17 +03:00
parent ca13aea26a
commit ee728b6902
115 changed files with 1239 additions and 1325 deletions
@@ -7,12 +7,12 @@ package org.jetbrains.kotlin.resolve.calls
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceResolver
import org.jetbrains.kotlin.resolve.calls.components.KotlinCallCompleter
import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks
import org.jetbrains.kotlin.resolve.calls.components.NewOverloadingConflictResolver
import org.jetbrains.kotlin.resolve.calls.components.*
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.components.candidate.SimpleResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.resolve.descriptorUtil.OVERLOAD_RESOLUTION_BY_LAMBDA_ANNOTATION_FQ_NAME
@@ -24,24 +24,116 @@ class KotlinCallResolver(
private val towerResolver: TowerResolver,
private val kotlinCallCompleter: KotlinCallCompleter,
private val overloadingConflictResolver: NewOverloadingConflictResolver,
private val callableReferenceResolver: CallableReferenceResolver,
private val callableReferenceArgumentResolver: CallableReferenceArgumentResolver,
private val callComponents: KotlinCallComponents
) {
fun resolveCall(
fun resolveAndCompleteCall(
scopeTower: ImplicitScopeTower,
resolutionCallbacks: KotlinResolutionCallbacks,
kotlinCall: KotlinCall,
expectedType: UnwrappedType?,
collectAllCandidates: Boolean,
createFactoryProviderForInvoke: () -> CandidateFactoryProviderForInvoke<ResolutionCandidate>
): CallResolutionResult {
val candidateFactory = createFactory(scopeTower, kotlinCall, resolutionCallbacks, expectedType)
val candidates = resolveCall(scopeTower, resolutionCallbacks, kotlinCall, collectAllCandidates, candidateFactory)
if (collectAllCandidates) {
return kotlinCallCompleter.createAllCandidatesResult(candidates, expectedType, resolutionCallbacks)
}
return kotlinCallCompleter.runCompletion(candidateFactory, candidates, expectedType, resolutionCallbacks)
}
fun resolveAndCompleteGivenCandidates(
scopeTower: ImplicitScopeTower,
resolutionCallbacks: KotlinResolutionCallbacks,
kotlinCall: KotlinCall,
expectedType: UnwrappedType?,
givenCandidates: Collection<GivenCandidate>,
collectAllCandidates: Boolean
): CallResolutionResult {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
kotlinCall.checkCallInvariants()
val candidateFactory = SimpleCandidateFactory(
callComponents, scopeTower, kotlinCall, resolutionCallbacks, callableReferenceResolver
val candidateFactory = SimpleCandidateFactory(callComponents, scopeTower, kotlinCall, resolutionCallbacks)
val resolutionCandidates = givenCandidates.map { candidateFactory.createCandidate(it).forceResolution() }
if (collectAllCandidates) {
val allCandidates = towerResolver.runWithEmptyTowerData(
KnownResultProcessor(resolutionCandidates),
TowerResolver.AllCandidatesCollector(),
useOrder = false
)
return kotlinCallCompleter.createAllCandidatesResult(allCandidates, expectedType, resolutionCallbacks)
}
val candidates = towerResolver.runWithEmptyTowerData(
KnownResultProcessor(resolutionCandidates),
TowerResolver.SuccessfulResultCollector(),
useOrder = true
)
val mostSpecificCandidates = choseMostSpecific(kotlinCall, resolutionCallbacks, candidates)
return kotlinCallCompleter.runCompletion(candidateFactory, mostSpecificCandidates, expectedType, resolutionCallbacks)
}
fun resolveCallableReferenceArgument(
argument: CallableReferenceKotlinCallArgument,
expectedType: UnwrappedType?,
baseSystem: ConstraintStorage,
resolutionCallbacks: KotlinResolutionCallbacks
): Collection<CallableReferenceResolutionCandidate> {
val scopeTower = callComponents.statelessCallbacks.getScopeTowerForCallableReferenceArgument(argument)
val factory = createCallableReferenceCallFactory(scopeTower, argument.call, resolutionCallbacks, expectedType, argument, baseSystem)
return resolveCall(scopeTower, resolutionCallbacks, argument.call, collectAllCandidates = false, factory)
}
private fun createCallableReferenceCallFactory(
scopeTower: ImplicitScopeTower,
kotlinCall: KotlinCall,
resolutionCallbacks: KotlinResolutionCallbacks,
expectedType: UnwrappedType?,
argument: CallableReferenceKotlinCallArgument? = null,
baseSystem: ConstraintStorage? = null
): CandidateFactory<CallableReferenceResolutionCandidate> {
val resolutionAtom = argument
?: CallableReferenceKotlinCall(kotlinCall, resolutionCallbacks.getLhsResult(kotlinCall), kotlinCall.name)
return CallableReferencesCandidateFactory(resolutionAtom, callComponents, scopeTower, expectedType, baseSystem, resolutionCallbacks)
}
private fun createSimpleCallFactory(
scopeTower: ImplicitScopeTower,
kotlinCall: KotlinCall,
resolutionCallbacks: KotlinResolutionCallbacks,
): CandidateFactory<ResolutionCandidate> = SimpleCandidateFactory(callComponents, scopeTower, kotlinCall, resolutionCallbacks)
private fun createFactory(
scopeTower: ImplicitScopeTower,
kotlinCall: KotlinCall,
resolutionCallbacks: KotlinResolutionCallbacks,
expectedType: UnwrappedType?
): CandidateFactory<ResolutionCandidate> =
when (kotlinCall.callKind) {
KotlinCallKind.CALLABLE_REFERENCE -> createCallableReferenceCallFactory(scopeTower, kotlinCall, resolutionCallbacks, expectedType)
else -> createSimpleCallFactory(scopeTower, kotlinCall, resolutionCallbacks)
}
private fun <C : ResolutionCandidate> resolveCall(
scopeTower: ImplicitScopeTower,
resolutionCallbacks: KotlinResolutionCallbacks,
kotlinCall: KotlinCall,
collectAllCandidates: Boolean,
candidateFactory: CandidateFactory<C>,
): Collection<C> {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
kotlinCall.checkCallInvariants()
@Suppress("UNCHECKED_CAST")
val processor = when (kotlinCall.callKind) {
KotlinCallKind.VARIABLE -> {
createVariableAndObjectProcessor(scopeTower, kotlinCall.name, candidateFactory, kotlinCall.explicitReceiver?.receiver)
@@ -51,9 +143,12 @@ class KotlinCallResolver(
scopeTower,
kotlinCall.name,
candidateFactory,
createFactoryProviderForInvoke(),
resolutionCallbacks.getCandidateFactoryForInvoke(scopeTower, kotlinCall),
kotlinCall.explicitReceiver?.receiver
)
) as ScopeTowerProcessor<C>
}
KotlinCallKind.CALLABLE_REFERENCE -> {
createCallableReferenceProcessor(candidateFactory as CallableReferencesCandidateFactory) as ScopeTowerProcessor<C>
}
KotlinCallKind.INVOKE -> {
createProcessorWithReceiverValueOrEmpty(kotlinCall.explicitReceiver?.receiver) {
@@ -69,8 +164,7 @@ class KotlinCallResolver(
}
if (collectAllCandidates) {
val allCandidates = towerResolver.collectAllCandidates(scopeTower, processor, kotlinCall.name)
return kotlinCallCompleter.createAllCandidatesResult(allCandidates, expectedType, resolutionCallbacks)
return towerResolver.collectAllCandidates(scopeTower, processor, kotlinCall.name)
}
val candidates = towerResolver.runResolve(
@@ -80,73 +174,55 @@ class KotlinCallResolver(
name = kotlinCall.name
)
return choseMostSpecific(candidateFactory, resolutionCallbacks, expectedType, candidates)
}
fun resolveGivenCandidates(
scopeTower: ImplicitScopeTower,
resolutionCallbacks: KotlinResolutionCallbacks,
kotlinCall: KotlinCall,
expectedType: UnwrappedType?,
givenCandidates: Collection<GivenCandidate>,
collectAllCandidates: Boolean
): CallResolutionResult {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
kotlinCall.checkCallInvariants()
val candidateFactory = SimpleCandidateFactory(
callComponents, scopeTower, kotlinCall, resolutionCallbacks, callableReferenceResolver
)
val resolutionCandidates = givenCandidates.map { candidateFactory.createCandidate(it).forceResolution() }
if (collectAllCandidates) {
val allCandidates = towerResolver.runWithEmptyTowerData(
KnownResultProcessor(resolutionCandidates),
TowerResolver.AllCandidatesCollector(),
useOrder = false
)
return kotlinCallCompleter.createAllCandidatesResult(allCandidates, expectedType, resolutionCallbacks)
}
val candidates = towerResolver.runWithEmptyTowerData(
KnownResultProcessor(resolutionCandidates),
TowerResolver.SuccessfulResultCollector(),
useOrder = true
)
return choseMostSpecific(candidateFactory, resolutionCallbacks, expectedType, candidates)
@Suppress("UNCHECKED_CAST")
return choseMostSpecific(kotlinCall, resolutionCallbacks, candidates) as Set<C>
}
private fun choseMostSpecific(
candidateFactory: SimpleCandidateFactory,
kotlinCall: KotlinCall,
resolutionCallbacks: KotlinResolutionCallbacks,
expectedType: UnwrappedType?,
candidates: Collection<ResolutionCandidate>
): CallResolutionResult {
): Set<ResolutionCandidate> {
var refinedCandidates = candidates
if (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.RefinedSamAdaptersPriority)) {
if (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.RefinedSamAdaptersPriority) && kotlinCall.callKind != KotlinCallKind.CALLABLE_REFERENCE) {
val nonSynthesized = candidates.filter { !it.resolvedCall.candidateDescriptor.isSynthesized }
if (!nonSynthesized.isEmpty()) {
if (nonSynthesized.isNotEmpty()) {
refinedCandidates = nonSynthesized
}
}
var maximallySpecificCandidates = overloadingConflictResolver.chooseMaximallySpecificCandidates(
refinedCandidates,
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
discriminateGenerics = true // todo
)
var maximallySpecificCandidates = if (kotlinCall.callKind == KotlinCallKind.CALLABLE_REFERENCE) {
@Suppress("UNCHECKED_CAST")
callableReferenceArgumentResolver.callableReferenceOverloadConflictResolver.chooseMaximallySpecificCandidates(
refinedCandidates as Collection<CallableReferenceResolutionCandidate>,
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
discriminateGenerics = true
)
} else {
overloadingConflictResolver.chooseMaximallySpecificCandidates(
refinedCandidates,
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
discriminateGenerics = true // todo
)
}
if (
maximallySpecificCandidates.size > 1 &&
callComponents.languageVersionSettings.supportsFeature(LanguageFeature.OverloadResolutionByLambdaReturnType) &&
candidates.all { resolutionCallbacks.inferenceSession.shouldRunCompletion(it) }
candidates.all { resolutionCallbacks.inferenceSession.shouldRunCompletion(it) } &&
kotlinCall.callKind != KotlinCallKind.CALLABLE_REFERENCE
) {
val candidatesWithAnnotation =
candidates.filter { it.resolvedCall.candidateDescriptor.annotations.hasAnnotation(OVERLOAD_RESOLUTION_BY_LAMBDA_ANNOTATION_FQ_NAME) }
val candidatesWithAnnotation = candidates.filter {
it.resolvedCall.candidateDescriptor.annotations.hasAnnotation(OVERLOAD_RESOLUTION_BY_LAMBDA_ANNOTATION_FQ_NAME)
}.toSet()
val candidatesWithoutAnnotation = candidates - candidatesWithAnnotation
if (candidatesWithAnnotation.isNotEmpty()) {
val newCandidates = kotlinCallCompleter.chooseCandidateRegardingOverloadResolutionByLambdaReturnType(maximallySpecificCandidates, resolutionCallbacks)
@Suppress("UNCHECKED_CAST")
val newCandidates = kotlinCallCompleter.chooseCandidateRegardingOverloadResolutionByLambdaReturnType(
maximallySpecificCandidates as Set<SimpleResolutionCandidate>,
resolutionCallbacks
)
maximallySpecificCandidates = overloadingConflictResolver.chooseMaximallySpecificCandidates(
newCandidates,
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
@@ -160,7 +236,6 @@ class KotlinCallResolver(
}
}
return kotlinCallCompleter.runCompletion(candidateFactory, maximallySpecificCandidates, expectedType, resolutionCallbacks)
return maximallySpecificCandidates
}
}
@@ -0,0 +1,74 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.isInapplicable
class CallableReferenceArgumentResolver(val callableReferenceOverloadConflictResolver: CallableReferenceOverloadConflictResolver) {
fun processCallableReferenceArgument(
csBuilder: ConstraintSystemBuilder,
resolvedAtom: ResolvedCallableReferenceArgumentAtom,
diagnosticsHolder: KotlinDiagnosticsHolder,
resolutionCallbacks: KotlinResolutionCallbacks
) {
val argument = resolvedAtom.atom
val expectedType = resolvedAtom.expectedType?.let { (csBuilder.buildCurrentSubstitutor() as NewTypeSubstitutor).safeSubstitute(it) }
val candidates = resolutionCallbacks.resolveCallableReferenceArgument(resolvedAtom.atom, expectedType, csBuilder.currentStorage())
if (candidates.size > 1 && resolvedAtom is EagerCallableReferenceAtom) {
if (candidates.all { it.resultingApplicability.isInapplicable }) {
diagnosticsHolder.addDiagnostic(CallableReferenceCallCandidatesAmbiguity(argument, candidates))
}
resolvedAtom.setAnalyzedResults(
candidate = null,
subResolvedAtoms = listOf(resolvedAtom.transformToPostponed())
)
return
}
val chosenCandidate = candidates.singleOrNull()
if (chosenCandidate != null) {
val toFreshSubstitutor = CreateFreshVariablesSubstitutor.createToFreshVariableSubstitutorAndAddInitialConstraints(
chosenCandidate.candidate,
csBuilder
)
chosenCandidate.addConstraints(csBuilder, toFreshSubstitutor, callableReference = argument)
chosenCandidate.diagnostics.forEach {
val transformedDiagnostic = when (it) {
is CompatibilityWarning -> CompatibilityWarningOnArgument(argument, it.candidate)
else -> it
}
diagnosticsHolder.addDiagnostic(transformedDiagnostic)
}
chosenCandidate.freshVariablesSubstitutor = toFreshSubstitutor
} else {
if (candidates.isEmpty()) {
diagnosticsHolder.addDiagnostic(NoneCallableReferenceCallCandidates(argument))
} else {
diagnosticsHolder.addDiagnostic(CallableReferenceCallCandidatesAmbiguity(argument, candidates))
}
}
// todo -- create this inside CallableReferencesCandidateFactory
val subKtArguments = listOfNotNull(buildResolvedKtArgument(argument.lhsResult))
resolvedAtom.setAnalyzedResults(chosenCandidate, subKtArguments)
}
private fun buildResolvedKtArgument(lhsResult: LHSResult): ResolvedAtom? {
if (lhsResult !is LHSResult.Expression) return null
return when (val lshCallArgument = lhsResult.lshCallArgument) {
is SubKotlinCallArgument -> lshCallArgument.callResult
is ExpressionKotlinCallArgument -> ResolvedExpressionAtom(lshCallArgument)
else -> unexpectedArgument(lshCallArgument)
}
}
}
@@ -0,0 +1,46 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
import org.jetbrains.kotlin.resolve.calls.results.*
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
import org.jetbrains.kotlin.util.CancellationChecker
class CallableReferenceOverloadConflictResolver(
builtIns: KotlinBuiltIns,
module: ModuleDescriptor,
specificityComparator: TypeSpecificityComparator,
platformOverloadsSpecificityComparator: PlatformOverloadsSpecificityComparator,
cancellationChecker: CancellationChecker,
statelessCallbacks: KotlinResolutionStatelessCallbacks,
constraintInjector: ConstraintInjector,
kotlinTypeRefiner: KotlinTypeRefiner,
) : OverloadingConflictResolver<CallableReferenceResolutionCandidate>(
builtIns,
module,
specificityComparator,
platformOverloadsSpecificityComparator,
cancellationChecker,
{ it.candidate },
{ statelessCallbacks.createConstraintSystemForOverloadResolution(constraintInjector, builtIns) },
Companion::createFlatSignature,
{ null },
{ statelessCallbacks.isDescriptorFromSource(it) },
null,
kotlinTypeRefiner,
) {
companion object {
private fun createFlatSignature(candidate: CallableReferenceResolutionCandidate) =
FlatSignature.createFromReflectionType(
candidate, candidate.candidate, candidate.numDefaults, hasBoundExtensionReceiver = candidate.extensionReceiver != null,
candidate.reflectionCandidateType
)
}
}
@@ -6,32 +6,19 @@
package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.builtins.*
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.calls.components.CreateFreshVariablesSubstitutor.createToFreshVariableSubstitutorAndAddInitialConstraints
import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPositionImpl
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.DISPATCH_RECEIVER
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.EXTENSION_RECEIVER
import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject
import org.jetbrains.kotlin.resolve.scopes.receivers.DetailedReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.captureFromExpression
import org.jetbrains.kotlin.types.expressions.CoercionStrategy
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addIfNotNull
sealed class CallableReceiver(val receiver: ReceiverValueWithSmartCastInfo) {
class UnboundReference(receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver(receiver)
@@ -40,10 +27,6 @@ sealed class CallableReceiver(val receiver: ReceiverValueWithSmartCastInfo) {
class ExplicitValueReceiver(receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver(receiver)
}
// todo investigate similar code in CheckVisibility
private val CallableReceiver.asReceiverValueForVisibilityChecks: ReceiverValue
get() = receiver.receiverValue
class CallableReferenceAdaptation(
val argumentTypes: Array<KotlinType>,
val coercionStrategy: CoercionStrategy,
@@ -90,41 +73,31 @@ fun createCallableReferenceProcessor(factory: CallableReferencesCandidateFactory
}
}
fun ConstraintSystemOperation.checkCallableReference(
argument: CallableReferenceKotlinCallArgument,
dispatchReceiver: CallableReceiver?,
extensionReceiver: CallableReceiver?,
candidateDescriptor: CallableDescriptor,
reflectionCandidateType: UnwrappedType,
expectedType: UnwrappedType?,
ownerDescriptor: DeclarationDescriptor
): Pair<FreshVariableNewTypeSubstitutor, KotlinCallDiagnostic?> {
val position = ArgumentConstraintPositionImpl(argument)
val toFreshSubstitutor = createToFreshVariableSubstitutorAndAddInitialConstraints(candidateDescriptor, this)
if (!ErrorUtils.isError(candidateDescriptor)) {
addReceiverConstraint(toFreshSubstitutor, dispatchReceiver, candidateDescriptor.dispatchReceiverParameter, position)
addReceiverConstraint(toFreshSubstitutor, extensionReceiver, candidateDescriptor.extensionReceiverParameter, position)
fun CallableReferenceResolutionCandidate.addConstraints(
constraintSystem: ConstraintSystemOperation,
substitutor: FreshVariableNewTypeSubstitutor,
callableReference: CallableReferenceResolutionAtom
) {
val position = when (callableReference) {
is CallableReferenceKotlinCallArgument -> ArgumentConstraintPositionImpl(callableReference)
is CallableReferenceKotlinCall -> CallableReferenceConstraintPositionImpl(callableReference)
}
if (expectedType != null && !hasContradiction) {
addSubtypeConstraint(toFreshSubstitutor.safeSubstitute(reflectionCandidateType), expectedType, position)
if (!ErrorUtils.isError(candidate)) {
constraintSystem.addReceiverConstraint(substitutor, dispatchReceiver, candidate.dispatchReceiverParameter, position)
constraintSystem.addReceiverConstraint(substitutor, extensionReceiver, candidate.extensionReceiverParameter, position)
}
val invisibleMember = DescriptorVisibilities.findInvisibleMember(
dispatchReceiver?.asReceiverValueForVisibilityChecks,
candidateDescriptor, ownerDescriptor
)
return toFreshSubstitutor to invisibleMember?.let(::VisibilityError)
if (expectedType != null && !TypeUtils.noExpectedType(expectedType) && !constraintSystem.hasContradiction) {
constraintSystem.addSubtypeConstraint(substitutor.safeSubstitute(reflectionCandidateType), expectedType, position)
}
}
private fun ConstraintSystemOperation.addReceiverConstraint(
toFreshSubstitutor: FreshVariableNewTypeSubstitutor,
receiverArgument: CallableReceiver?,
receiverParameter: ReceiverParameterDescriptor?,
position: ArgumentConstraintPositionImpl
position: ConstraintPosition
) {
if (receiverArgument == null || receiverParameter == null) {
assert(receiverArgument == null) { "Receiver argument should be null if parameter is: $receiverArgument" }
@@ -1,162 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.results.*
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower
import org.jetbrains.kotlin.resolve.calls.tower.TowerResolver
import org.jetbrains.kotlin.resolve.calls.tower.isInapplicable
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
import org.jetbrains.kotlin.util.CancellationChecker
class CallableReferenceOverloadConflictResolver(
builtIns: KotlinBuiltIns,
module: ModuleDescriptor,
specificityComparator: TypeSpecificityComparator,
platformOverloadsSpecificityComparator: PlatformOverloadsSpecificityComparator,
cancellationChecker: CancellationChecker,
statelessCallbacks: KotlinResolutionStatelessCallbacks,
constraintInjector: ConstraintInjector,
kotlinTypeRefiner: KotlinTypeRefiner,
) : OverloadingConflictResolver<CallableReferenceCandidate>(
builtIns,
module,
specificityComparator,
platformOverloadsSpecificityComparator,
cancellationChecker,
{ it.candidate },
{ statelessCallbacks.createConstraintSystemForOverloadResolution(constraintInjector, builtIns) },
Companion::createFlatSignature,
{ null },
{ statelessCallbacks.isDescriptorFromSource(it) },
null,
kotlinTypeRefiner,
) {
companion object {
private fun createFlatSignature(candidate: CallableReferenceCandidate) =
FlatSignature.createFromReflectionType(
candidate, candidate.candidate, candidate.numDefaults, hasBoundExtensionReceiver = candidate.extensionReceiver != null,
candidate.reflectionCandidateType
)
}
}
class CallableReferenceResolver(
private val towerResolver: TowerResolver,
private val callableReferenceOverloadConflictResolver: CallableReferenceOverloadConflictResolver,
private val callComponents: KotlinCallComponents
) {
fun processCallableReferenceArgument(
csBuilder: ConstraintSystemBuilder,
resolvedAtom: ResolvedCallableReferenceAtom,
diagnosticsHolder: KotlinDiagnosticsHolder,
resolutionCallbacks: KotlinResolutionCallbacks
) {
val argument = resolvedAtom.atom
val expectedType = resolvedAtom.expectedType?.let { (csBuilder.buildCurrentSubstitutor() as NewTypeSubstitutor).safeSubstitute(it) }
val scopeTower = callComponents.statelessCallbacks.getScopeTowerForCallableReferenceArgument(argument)
val candidates = runRHSResolution(scopeTower, argument, expectedType, csBuilder, resolutionCallbacks) { checkCallableReference ->
csBuilder.runTransaction { checkCallableReference(this); false }
}
if (candidates.size > 1 && resolvedAtom is EagerCallableReferenceAtom) {
if (candidates.all { it.resultingApplicability.isInapplicable }) {
diagnosticsHolder.addDiagnostic(CallableReferenceCandidatesAmbiguity(argument, candidates))
}
resolvedAtom.setAnalyzedResults(
candidate = null,
subResolvedAtoms = listOf(resolvedAtom.transformToPostponed())
)
return
}
val chosenCandidate = candidates.singleOrNull()
if (chosenCandidate != null) {
val (toFreshSubstitutor, diagnostic) = with(chosenCandidate) {
csBuilder.checkCallableReference(
argument, dispatchReceiver, extensionReceiver, candidate,
reflectionCandidateType, expectedType, scopeTower.lexicalScope.ownerDescriptor
)
}
diagnosticsHolder.addDiagnosticIfNotNull(diagnostic)
chosenCandidate.diagnostics.forEach {
val transformedDiagnostic = when (it) {
is CompatibilityWarning -> CompatibilityWarningOnArgument(argument, it.candidate)
else -> it
}
diagnosticsHolder.addDiagnostic(transformedDiagnostic)
}
chosenCandidate.freshSubstitutor = toFreshSubstitutor
} else {
if (candidates.isEmpty()) {
diagnosticsHolder.addDiagnostic(NoneCallableReferenceCandidates(argument))
} else {
diagnosticsHolder.addDiagnostic(CallableReferenceCandidatesAmbiguity(argument, candidates))
}
}
// todo -- create this inside CallableReferencesCandidateFactory
val subKtArguments = listOfNotNull(buildResolvedKtArgument(argument.lhsResult))
resolvedAtom.setAnalyzedResults(chosenCandidate, subKtArguments)
}
private fun buildResolvedKtArgument(lhsResult: LHSResult): ResolvedAtom? {
if (lhsResult !is LHSResult.Expression) return null
val lshCallArgument = lhsResult.lshCallArgument
return when (lshCallArgument) {
is SubKotlinCallArgument -> lshCallArgument.callResult
is ExpressionKotlinCallArgument -> ResolvedExpressionAtom(lshCallArgument)
else -> unexpectedArgument(lshCallArgument)
}
}
private fun runRHSResolution(
scopeTower: ImplicitScopeTower,
callableReference: CallableReferenceKotlinCallArgument,
expectedType: UnwrappedType?, // this type can have not fixed type variable inside
csBuilder: ConstraintSystemBuilder,
resolutionCallbacks: KotlinResolutionCallbacks,
compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit // you can run anything throw this operation and all this operation will be rolled back
): Set<CallableReferenceCandidate> {
val factory = CallableReferencesCandidateFactory(
callableReference, callComponents, scopeTower, compatibilityChecker, expectedType, csBuilder, resolutionCallbacks
)
val processor = createCallableReferenceProcessor(factory)
val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = true, name = callableReference.rhsName)
return callableReferenceOverloadConflictResolver.chooseMaximallySpecificCandidates(
candidates,
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
discriminateGenerics = false // we can't specify generics explicitly for callable references
)
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionContext
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
@@ -42,7 +43,7 @@ class CompletionModeCalculator {
if (returnType == null) return ConstraintSystemCompletionMode.PARTIAL
// Full if return type for call has no type variables
if (csBuilder.isProperType(returnType)) return ConstraintSystemCompletionMode.FULL
if (getSystem().getBuilder().isProperType(returnType)) return ConstraintSystemCompletionMode.FULL
// For nested call with variables in return type check possibility of full completion
return CalculatorForNestedCall(
@@ -11,10 +11,15 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.components.candidate.SimpleResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
import org.jetbrains.kotlin.resolve.calls.tower.CandidateFactoryProviderForInvoke
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
import org.jetbrains.kotlin.types.KotlinType
@@ -37,7 +42,7 @@ interface KotlinResolutionStatelessCallbacks {
fun isSuperExpression(receiver: SimpleKotlinCallArgument?): Boolean
fun getScopeTowerForCallableReferenceArgument(argument: CallableReferenceKotlinCallArgument): ImplicitScopeTower
fun getVariableCandidateIfInvoke(functionCall: KotlinCall): KotlinResolutionCandidate?
fun getVariableCandidateIfInvoke(functionCall: KotlinCall): ResolutionCandidate?
fun isBuilderInferenceCall(argument: KotlinCallArgument, parameter: ValueParameterDescriptor): Boolean
fun isApplicableCallForBuilderInference(descriptor: CallableDescriptor, languageVersionSettings: LanguageVersionSettings): Boolean
@@ -77,6 +82,17 @@ interface KotlinResolutionCallbacks {
stubsForPostponedVariables: Map<NewTypeVariable, StubTypeForBuilderInference>,
): ReturnArgumentsAnalysisResult
fun getCandidateFactoryForInvoke(
scopeTower: ImplicitScopeTower,
kotlinCall: KotlinCall,
): CandidateFactoryProviderForInvoke<ResolutionCandidate>
fun resolveCallableReferenceArgument(
argument: CallableReferenceKotlinCallArgument,
expectedType: UnwrappedType?,
baseSystem: ConstraintStorage,
): Collection<CallableReferenceResolutionCandidate>
fun bindStubResolvedCallForCandidate(candidate: ResolvedCallAtom)
fun isCompileTimeConstant(resolvedAtom: ResolvedCallAtom, expectedType: UnwrappedType): Boolean
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.TrivialConstraint
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage.Empty.hasContradiction
import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPositionImpl
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.CandidateFactory
import org.jetbrains.kotlin.resolve.calls.tower.forceResolution
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.TypeUtils
@@ -40,22 +41,27 @@ class KotlinCallCompleter(
resolutionCallbacks: KotlinResolutionCallbacks
): CallResolutionResult {
val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder()
when {
candidates.isEmpty() -> diagnosticHolder.addDiagnostic(NoneCandidatesCallDiagnostic(factory.kotlinCall))
candidates.size > 1 -> diagnosticHolder.addDiagnostic(ManyCandidatesCallDiagnostic(factory.kotlinCall, candidates))
candidates.isEmpty() -> diagnosticHolder.addDiagnostic(NoneCandidatesCallDiagnostic())
candidates.size > 1 -> diagnosticHolder.addDiagnostic(ManyCandidatesCallDiagnostic(candidates))
}
val candidate = prepareCandidateForCompletion(factory, candidates, resolutionCallbacks)
val returnType = candidate.substitutedReturnType()
val resultType = when (candidate) {
is SimpleResolutionCandidate -> {
candidate.checkSamWithVararg(diagnosticHolder)
candidate.substitutedReturnType().also {
candidate.addExpectedTypeConstraint(it, expectedType)
candidate.addExpectedTypeFromCastConstraint(it, resolutionCallbacks)
}
}
is CallableReferenceResolutionCandidate -> candidate.substitutedReflectionType()
}
candidate.addExpectedTypeConstraint(returnType, expectedType)
candidate.addExpectedTypeFromCastConstraint(returnType, resolutionCallbacks)
candidate.checkSamWithVararg(diagnosticHolder)
val completionMode =
CompletionModeCalculator.computeCompletionMode(
candidate, expectedType, returnType, trivialConstraintTypeInferenceOracle, resolutionCallbacks.inferenceSession
)
val completionMode = CompletionModeCalculator.computeCompletionMode(
candidate, expectedType, resultType, trivialConstraintTypeInferenceOracle, resolutionCallbacks.inferenceSession
)
return when (completionMode) {
ConstraintSystemCompletionMode.FULL -> {
@@ -151,7 +157,7 @@ class KotlinCallCompleter(
private fun SimpleResolutionCandidate.getInputTypesOfLambdaAtom(atom: ResolvedLambdaAtom): List<UnwrappedType> {
val result = mutableListOf<UnwrappedType>()
val substitutor = csBuilder.buildCurrentSubstitutor()
val substitutor = getSystem().getBuilder().buildCurrentSubstitutor()
val ctx = getSystem().asConstraintSystemCompleterContext()
for (inputType in atom.inputTypes) {
result += substitutor.safeSubstitute(ctx, inputType) as UnwrappedType
@@ -198,7 +204,7 @@ class KotlinCallCompleter(
collectAllCandidatesMode = true
)
CandidateWithDiagnostics(candidate, diagnosticsHolder.getDiagnostics() + candidate.diagnosticsFromResolutionParts)
CandidateWithDiagnostics(candidate, diagnosticsHolder.getDiagnostics() + candidate.diagnostics)
}
return AllCandidatesResolutionResult(completedCandidates)
}
@@ -264,6 +270,10 @@ class KotlinCallCompleter(
return candidate ?: factory.createErrorCandidate().forceResolution()
}
private fun CallableReferenceResolutionCandidate.substitutedReflectionType(): UnwrappedType {
return resolvedCall.freshVariablesSubstitutor.safeSubstitute(this.reflectionCandidateType)
}
private fun ResolutionCandidate.substitutedReturnType(): UnwrappedType? {
val returnType = resolvedCall.candidateDescriptor.returnType?.unwrap() ?: return null
return resolvedCall.freshVariablesSubstitutor.safeSubstitute(returnType)
@@ -276,6 +286,8 @@ class KotlinCallCompleter(
if (returnType == null) return
if (expectedType == null || (TypeUtils.noExpectedType(expectedType) && expectedType !== TypeUtils.UNIT_EXPECTED_TYPE)) return
val csBuilder = getSystem().getBuilder()
when {
csBuilder.currentStorage().notFixedTypeVariables.isEmpty() -> {
// This is needed to avoid multiple mismatch errors as we type check resulting type against expected one later
@@ -304,7 +316,10 @@ class KotlinCallCompleter(
) {
if (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ExpectedTypeFromCast)) return
if (returnType == null) return
val expectedType = resolutionCallbacks.getExpectedTypeFromAsExpressionAndRecordItInTrace(resolvedCall) ?: return
val csBuilder = getSystem().getBuilder()
csBuilder.addSubtypeConstraint(returnType, expectedType, ExpectedTypeConstraintPositionImpl(resolvedCall.atom))
}
@@ -314,7 +329,7 @@ class KotlinCallCompleter(
forwardToInferenceSession: Boolean = false
): CallResolutionResult {
val systemStorage = getSystem().asReadOnlyStorage()
val allDiagnostics = diagnosticsHolder.getDiagnostics() + diagnosticsFromResolutionParts
val allDiagnostics = diagnosticsHolder.getDiagnostics() + diagnostics
if (isErrorCandidate()) {
return ErrorCallResolutionResult(resolvedCall, allDiagnostics, systemStorage)
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.utils.addToStdlib.cast
class PostponedArgumentsAnalyzer(
private val callableReferenceResolver: CallableReferenceResolver,
private val callableReferenceArgumentResolver: CallableReferenceArgumentResolver,
private val languageVersionSettings: LanguageVersionSettings
) {
@@ -49,8 +49,10 @@ class PostponedArgumentsAnalyzer(
diagnosticsHolder
)
is ResolvedCallableReferenceAtom ->
callableReferenceResolver.processCallableReferenceArgument(c.getBuilder(), argument, diagnosticsHolder, resolutionCallbacks)
is ResolvedCallableReferenceArgumentAtom ->
callableReferenceArgumentResolver.processCallableReferenceArgument(
c.getBuilder(), argument, diagnosticsHolder, resolutionCallbacks
)
is ResolvedCollectionLiteralAtom -> TODO("Not supported")
@@ -119,6 +119,7 @@ internal object NoArguments : ResolutionPart() {
internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
override fun ResolutionCandidate.process(workIndex: Int) {
val csBuilder = getSystem().getBuilder()
val toFreshVariables =
if (candidateDescriptor.typeParameters.isEmpty())
FreshVariableNewTypeSubstitutor.Empty
@@ -126,7 +127,7 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
createToFreshVariableSubstitutorAndAddInitialConstraints(candidateDescriptor, csBuilder)
val knownTypeParametersSubstitutor = knownTypeParametersResultingSubstitutor?.let {
createKnownParametersFromFreshVariablesSubstitutor(toFreshVariables, knownTypeParametersResultingSubstitutor)
createKnownParametersFromFreshVariablesSubstitutor(toFreshVariables, it)
} ?: EmptySubstitutor
resolvedCall.freshVariablesSubstitutor = toFreshVariables
@@ -275,6 +276,7 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
internal object PostponedVariablesInitializerResolutionPart : ResolutionPart() {
override fun ResolutionCandidate.process(workIndex: Int) {
val csBuilder = getSystem().getBuilder()
for ((argument, parameter) in resolvedCall.argumentToCandidateParameter) {
if (!callComponents.statelessCallbacks.isBuilderInferenceCall(argument, parameter)) continue
val receiverType = parameter.type.getReceiverTypeFromFunctionType() ?: continue
@@ -302,6 +304,7 @@ internal object PostponedVariablesInitializerResolutionPart : ResolutionPart() {
internal object CompatibilityOfTypeVariableAsIntersectionTypePart : ResolutionPart() {
override fun ResolutionCandidate.process(workIndex: Int) {
val csBuilder = getSystem().getBuilder()
for ((_, variableWithConstraints) in csBuilder.currentStorage().notFixedTypeVariables) {
val constraints = variableWithConstraints.constraints.filter { csBuilder.isProperType(it.type) }
@@ -487,13 +490,14 @@ internal object CollectionTypeVariableUsagesInfo : ResolutionPart() {
override fun ResolutionCandidate.process(workIndex: Int) {
for (variable in resolvedCall.freshVariablesSubstitutor.freshVariables) {
if (resolvedCall.candidateDescriptor is ClassConstructorDescriptor) {
val typeParameters = resolvedCall.candidateDescriptor.containingDeclaration.declaredTypeParameters
val candidateDescriptor = resolvedCall.candidateDescriptor
if (candidateDescriptor is ClassConstructorDescriptor) {
val typeParameters = candidateDescriptor.containingDeclaration.declaredTypeParameters
if (isContainedInInvariantOrContravariantPositionsAmongTypeParameters(variable, typeParameters)) {
variable.recordInfoAboutTypeVariableUsagesAsInvariantOrContravariantParameter()
}
} else if (getSystem().isContainedInInvariantOrContravariantPositionsWithDependencies(variable, candidateDescriptor)) {
} else if (getSystem().isContainedInInvariantOrContravariantPositionsWithDependencies(variable, this.candidateDescriptor)) {
variable.recordInfoAboutTypeVariableUsagesAsInvariantOrContravariantParameter()
}
}
@@ -505,6 +509,7 @@ private fun ResolutionCandidate.resolveKotlinArgument(
candidateParameter: ParameterDescriptor?,
receiverInfo: ReceiverInfo
) {
val csBuilder = getSystem().getBuilder()
val candidateExpectedType = candidateParameter?.let { argument.getExpectedType(it, callComponents.languageVersionSettings) }
val isReceiver = receiverInfo.isReceiver
@@ -602,6 +607,7 @@ private fun ResolutionCandidate.resolveKotlinArgument(
private fun ResolutionCandidate.shouldRunConversionForConstants(expectedType: UnwrappedType): Boolean {
if (UnsignedTypes.isUnsignedType(expectedType)) return true
val csBuilder = getSystem().getBuilder()
if (csBuilder.isTypeVariable(expectedType)) {
val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[expectedType.constructor] ?: return false
return variableWithConstraints.constraints.any {
@@ -650,7 +656,7 @@ internal object CheckReceivers : ResolutionPart() {
receiverParameter: ReceiverParameterDescriptor?,
shouldCheckImplicitInvoke: Boolean,
) {
if ((receiverArgument == null) != (receiverParameter == null)) {
if (this !is CallableReferenceResolutionCandidate && (receiverArgument == null) != (receiverParameter == null)) {
error("Inconsistency receiver state for call $kotlinCall and candidate descriptor: $candidateDescriptor")
}
if (receiverArgument == null || receiverParameter == null) return
@@ -709,11 +715,25 @@ internal object EagerResolveOfCallableReferences : ResolutionPart() {
getSubResolvedAtoms()
.filterIsInstance<EagerCallableReferenceAtom>()
.forEach {
callableReferenceResolver.processCallableReferenceArgument(csBuilder, it, this, resolutionCallbacks)
callComponents.callableReferenceArgumentResolver.processCallableReferenceArgument(
getSystem().getBuilder(), it, this, resolutionCallbacks
)
}
}
}
internal object CheckCallableReference : ResolutionPart() {
override fun ResolutionCandidate.process(workIndex: Int) {
if (this !is CallableReferenceResolutionCandidate) {
error("`CheckCallableReferences` resolution part is applicable only to callable reference calls")
}
val constraintSystem = getSystem().takeIf { !it.hasContradiction } ?: return
addConstraints(constraintSystem.getBuilder(), resolvedCall.freshVariablesSubstitutor, kotlinCall)
}
}
internal object CheckInfixResolutionPart : ResolutionPart() {
override fun ResolutionCandidate.process(workIndex: Int) {
val candidateDescriptor = resolvedCall.candidateDescriptor
@@ -28,8 +28,10 @@ object UnitTypeConversions : ParameterTypeConversion {
if (argument !is SimpleKotlinCallArgument) return true
val receiver = argument.receiver
if (receiver.receiverValue.type.hasUnitOrSubtypeReturnType(candidate.csBuilder)) return true
if (receiver.typesFromSmartCasts.any { it.hasUnitOrSubtypeReturnType(candidate.csBuilder) }) return true
val csBuilder = candidate.getSystem().getBuilder()
if (receiver.receiverValue.type.hasUnitOrSubtypeReturnType(csBuilder)) return true
if (receiver.typesFromSmartCasts.any { it.hasUnitOrSubtypeReturnType(csBuilder) }) return true
if (
!expectedParameterType.isBuiltinFunctionalType ||
@@ -33,10 +33,10 @@ class CallableReferenceResolutionCandidate(
val reflectionCandidateType: UnwrappedType,
val callableReferenceAdaptation: CallableReferenceAdaptation?,
val kotlinCall: CallableReferenceResolutionAtom,
val expectedType: UnwrappedType?,
override val callComponents: KotlinCallComponents,
override val scopeTower: ImplicitScopeTower,
override val resolutionCallbacks: KotlinResolutionCallbacks,
val expectedType: UnwrappedType?,
override val baseSystem: ConstraintStorage?
) : ResolutionCandidate() {
override val variableCandidateIfInvoke: ResolutionCandidate? = null
@@ -20,30 +20,61 @@ import java.util.ArrayList
sealed class ResolutionCandidate : Candidate, KotlinDiagnosticsHolder {
abstract val resolvedCall: MutableResolvedCallAtom
abstract val callComponents: KotlinCallComponents
abstract fun getSubResolvedAtoms(): List<ResolvedAtom>
abstract fun addResolvedKtPrimitive(resolvedAtom: ResolvedAtom)
abstract val variableCandidateIfInvoke: ResolutionCandidate?
abstract val scopeTower: ImplicitScopeTower
abstract val knownTypeParametersResultingSubstitutor: TypeSubstitutor?
abstract val resolutionCallbacks: KotlinResolutionCallbacks
override val isSuccessful: Boolean
get() {
processParts(stopOnFirstError = true)
return resultingApplicabilities.minOrNull()!!.isSuccess && !getSystem().hasContradiction
}
override val resultingApplicability: CandidateApplicability
get() {
processParts(stopOnFirstError = false)
return resultingApplicabilities.minOrNull() ?: CandidateApplicability.RESOLVED
}
open val resolutionSequence: List<ResolutionPart> get() = resolvedCall.atom.callKind.resolutionSequence
protected abstract val baseSystem: ConstraintStorage?
protected val mutableDiagnostics: ArrayList<KotlinCallDiagnostic> = arrayListOf()
val descriptor: CallableDescriptor get() = resolvedCall.candidateDescriptor
val diagnostics: List<KotlinCallDiagnostic> = mutableDiagnostics
val resultingApplicabilities: Array<CandidateApplicability>
get() = arrayOf(currentApplicability, getResultApplicability(getSystem().errors), variableApplicability)
private val variableApplicability
get() = variableCandidateIfInvoke?.resultingApplicability ?: CandidateApplicability.RESOLVED
private val stepCount get() = resolutionSequence.sumOf { it.run { workCount() } }
private var step = 0
private var newSystem: NewConstraintSystemImpl? = null
private var currentApplicability: CandidateApplicability = CandidateApplicability.RESOLVED
abstract fun getSubResolvedAtoms(): List<ResolvedAtom>
abstract fun addResolvedKtPrimitive(resolvedAtom: ResolvedAtom)
override fun addDiagnostic(diagnostic: KotlinCallDiagnostic) {
mutableDiagnostics.add(diagnostic)
currentApplicability = minOf(diagnostic.candidateApplicability, currentApplicability)
}
private val variableApplicability
get() = variableCandidateIfInvoke?.resultingApplicability ?: CandidateApplicability.RESOLVED
override fun addCompatibilityWarning(other: Candidate) {
if (other is ResolutionCandidate && this !== other && this::class == other::class) {
addDiagnostic(CompatibilityWarning(other.descriptor))
}
}
val descriptor: CallableDescriptor get() = resolvedCall.candidateDescriptor
protected val mutableDiagnostics: ArrayList<KotlinCallDiagnostic> = arrayListOf()
open val resolutionSequence: List<ResolutionPart> get() = resolvedCall.atom.callKind.resolutionSequence
private var newSystem: NewConstraintSystemImpl? = null
val diagnostics: List<KotlinCallDiagnostic> = mutableDiagnostics
override fun toString(): String {
val descriptor = DescriptorRenderer.COMPACT.render(resolvedCall.candidateDescriptor)
val okOrFail = if (resultingApplicabilities.minOrNull()?.isSuccess != false) "OK" else "FAIL"
val step = "$step/$stepCount"
return "$okOrFail($step): $descriptor"
}
fun getSystem(): NewConstraintSystem {
if (newSystem == null) {
@@ -57,9 +88,6 @@ sealed class ResolutionCandidate : Candidate, KotlinDiagnosticsHolder {
return newSystem!!
}
private val stepCount get() = resolutionSequence.sumOf { it.run { workCount() } }
private var step = 0
private fun processParts(stopOnFirstError: Boolean) {
if (stopOnFirstError && step > 0) return // error already happened
if (step == stepCount) return
@@ -99,34 +127,4 @@ sealed class ResolutionCandidate : Candidate, KotlinDiagnosticsHolder {
}
return false
}
protected var currentApplicability: CandidateApplicability = CandidateApplicability.RESOLVED
override val isSuccessful: Boolean
get() {
processParts(stopOnFirstError = true)
return resultingApplicabilities.minOrNull()!!.isSuccess && !getSystem().hasContradiction
}
val resultingApplicabilities: Array<CandidateApplicability>
get() = arrayOf(currentApplicability, getResultApplicability(getSystem().errors), variableApplicability)
override val resultingApplicability: CandidateApplicability
get() {
processParts(stopOnFirstError = false)
return resultingApplicabilities.minOrNull()!!
}
override fun addCompatibilityWarning(other: Candidate) {
if (other is ResolutionCandidate && this !== other && this::class == other::class) {
addDiagnostic(CompatibilityWarning(other.descriptor))
}
}
override fun toString(): String {
val descriptor = DescriptorRenderer.COMPACT.render(resolvedCall.candidateDescriptor)
val okOrFail = if (resultingApplicabilities.minOrNull()!!.isSuccess) "OK" else "FAIL"
val step = "$step/$stepCount"
return "$okOrFail($step): $descriptor"
}
}
}
@@ -25,8 +25,6 @@ open class SimpleResolutionCandidate(
override val resolvedCall: MutableResolvedCallAtom,
override val knownTypeParametersResultingSubstitutor: TypeSubstitutor? = null,
) : ResolutionCandidate() {
private var subResolvedAtoms: MutableList<ResolvedAtom> = arrayListOf()
override val variableCandidateIfInvoke: ResolutionCandidate?
get() = callComponents.statelessCallbacks.getVariableCandidateIfInvoke(resolvedCall.atom)
@@ -35,4 +33,6 @@ open class SimpleResolutionCandidate(
override fun addResolvedKtPrimitive(resolvedAtom: ResolvedAtom) {
subResolvedAtoms.add(resolvedAtom)
}
private var subResolvedAtoms: MutableList<ResolvedAtom> = arrayListOf()
}
@@ -35,6 +35,8 @@ val CallableDescriptor.returnTypeOrNothing: UnwrappedType
fun TypeSubstitutor.substitute(type: UnwrappedType): UnwrappedType = safeSubstitute(type, Variance.INVARIANT).unwrap()
fun CallableDescriptor.substitute(substitutor: NewTypeSubstitutor): CallableDescriptor {
if (substitutor.isEmpty) return this
val wrappedSubstitution = object : TypeSubstitution() {
override fun get(key: KotlinType): TypeProjection? = null
override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) = substitutor.safeSubstitute(topLevelType.unwrap())
@@ -44,16 +46,20 @@ fun CallableDescriptor.substitute(substitutor: NewTypeSubstitutor): CallableDesc
fun CallableDescriptor.substituteAndApproximateTypes(
substitutor: NewTypeSubstitutor,
typeApproximator: TypeApproximator?
typeApproximator: TypeApproximator?,
positionDependentApproximation: Boolean = false
): CallableDescriptor {
if (substitutor.isEmpty) return this
val wrappedSubstitution = object : TypeSubstitution() {
override fun get(key: KotlinType): TypeProjection? = null
override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) =
substitutor.safeSubstitute(topLevelType.unwrap()).let { substitutedType ->
typeApproximator?.approximateToSuperType(
typeApproximator?.approximateTo(
substitutedType,
TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference,
position != Variance.IN_VARIANCE || !positionDependentApproximation
) ?: substitutedType
}
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.resolve.calls.components.candidate.SimpleResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.components.transformToResolvedLambda
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.model.*
@@ -286,7 +287,7 @@ class KotlinConstraintSystemCompleter(
diagnosticsHolder: KotlinDiagnosticsHolder,
): ResolvedLambdaAtom {
val returnVariable = TypeVariableForLambdaReturnType(candidate.callComponents.builtIns, "_R")
val csBuilder = candidate.csBuilder
val csBuilder = candidate.getSystem().getBuilder()
csBuilder.registerVariable(returnVariable)
val functionalType: KotlinType = csBuilder.buildCurrentSubstitutor().safeSubstitute(candidate.getSystem().asConstraintSystemCompleterContext(), atom.expectedType!!) as KotlinType
val expectedType = KotlinTypeFactory.simpleType(
@@ -34,6 +34,9 @@ class DeclaredUpperBoundConstraintPositionImpl(
class ArgumentConstraintPositionImpl(argument: KotlinCallArgument) : ArgumentConstraintPosition<KotlinCallArgument>(argument)
class CallableReferenceConstraintPositionImpl(val callableReferenceCall: CallableReferenceKotlinCall) :
CallableReferenceConstraintPosition<CallableReferenceResolutionAtom>(callableReferenceCall)
class ReceiverConstraintPositionImpl(argument: KotlinCallArgument) : ReceiverConstraintPosition<KotlinCallArgument>(argument)
class FixVariableConstraintPositionImpl(
@@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.resolve.calls.components
package org.jetbrains.kotlin.resolve.calls.model
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.ReflectionTypes
@@ -13,35 +13,53 @@ import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.components.*
import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject
import org.jetbrains.kotlin.resolve.scopes.receivers.DetailedReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.expressions.CoercionStrategy
import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addIfNotNull
class CallableReferencesCandidateFactory(
val argument: CallableReferenceKotlinCallArgument,
val kotlinCall: CallableReferenceResolutionAtom,
val callComponents: KotlinCallComponents,
val scopeTower: ImplicitScopeTower,
val compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit,
val expectedType: UnwrappedType?,
private val csBuilder: ConstraintSystemOperation,
private val baseSystem: ConstraintStorage?,
private val resolutionCallbacks: KotlinResolutionCallbacks
) : CandidateFactory<CallableReferenceResolutionCandidate> {
// todo investigate similar code in CheckVisibility
private val CallableReceiver.asReceiverValueForVisibilityChecks: ReceiverValue
get() = receiver.receiverValue
fun createCallableProcessor(explicitReceiver: DetailedReceiver?) =
createCallableReferenceProcessor(scopeTower, argument.rhsName, this, explicitReceiver)
override fun createErrorCandidate(): CallableReferenceResolutionCandidate {
val errorScope = ErrorUtils.createErrorScope("Error resolution candidate for call $kotlinCall")
val errorDescriptor = errorScope.getContributedFunctions(kotlinCall.rhsName, scopeTower.location).first()
val (reflectionCandidateType, callableReferenceAdaptation) = buildReflectionType(
errorDescriptor,
dispatchReceiver = null,
extensionReceiver = null,
expectedType,
callComponents.builtIns,
buildTypeWithConversions = kotlinCall is CallableReferenceKotlinCallArgument
)
return CallableReferenceResolutionCandidate(
errorDescriptor, dispatchReceiver = null, extensionReceiver = null,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, reflectionCandidateType, callableReferenceAdaptation,
kotlinCall, expectedType, callComponents, scopeTower, resolutionCallbacks, baseSystem
)
}
override fun createCandidate(
towerCandidate: CandidateWithBoundDispatchReceiver,
@@ -59,18 +77,20 @@ class CallableReferencesCandidateFactory(
dispatchCallableReceiver,
extensionCallableReceiver,
expectedType,
callComponents.builtIns
callComponents.builtIns,
// conversions aren't needed for top-level callable references
buildTypeWithConversions = kotlinCall is CallableReferenceKotlinCallArgument
)
fun createReferenceCandidate(): CallableReferenceResolutionCandidate =
CallableReferenceResolutionCandidate(
candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver,
explicitReceiverKind, reflectionCandidateType, callableReferenceAdaptation, diagnostics
)
fun createCallableReferenceCallCandidate(diagnostics: List<KotlinCallDiagnostic>) = CallableReferenceResolutionCandidate(
candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver,
explicitReceiverKind, reflectionCandidateType, callableReferenceAdaptation,
kotlinCall, expectedType, callComponents, scopeTower, resolutionCallbacks, baseSystem
).also { diagnostics.forEach(it::addDiagnostic) }
if (callComponents.statelessCallbacks.isHiddenInResolution(candidateDescriptor, argument, resolutionCallbacks)) {
if (callComponents.statelessCallbacks.isHiddenInResolution(candidateDescriptor, kotlinCall.call, resolutionCallbacks)) {
diagnostics.add(HiddenDescriptor)
return createReferenceCandidate()
return createCallableReferenceCallCandidate(diagnostics)
}
if (needCompatibilityResolveForCallableReference(callableReferenceAdaptation, candidateDescriptor)) {
@@ -79,7 +99,7 @@ class CallableReferencesCandidateFactory(
if (callableReferenceAdaptation != null && expectedType != null && hasNonTrivialAdaptation(callableReferenceAdaptation)) {
if (!expectedType.isFunctionType && !expectedType.isSuspendFunctionType) { // expectedType has some reflection type
diagnostics.add(AdaptedCallableReferenceIsUsedWithReflection(argument))
diagnostics.add(AdaptedCallableReferenceIsUsedWithReflection(kotlinCall))
}
}
@@ -87,49 +107,28 @@ class CallableReferencesCandidateFactory(
callableReferenceAdaptation.defaults != 0 &&
!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.FunctionReferenceWithDefaultValueAsOtherType)
) {
diagnostics.add(CallableReferencesDefaultArgumentUsed(argument, candidateDescriptor, callableReferenceAdaptation.defaults))
diagnostics.add(CallableReferencesDefaultArgumentUsed(kotlinCall, candidateDescriptor, callableReferenceAdaptation.defaults))
}
if (candidateDescriptor !is CallableMemberDescriptor) {
return CallableReferenceResolutionCandidate(
candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver,
explicitReceiverKind, reflectionCandidateType, callableReferenceAdaptation,
listOf(NotCallableMemberReference(argument, candidateDescriptor))
)
return createCallableReferenceCallCandidate(listOf(NotCallableMemberReference(kotlinCall, candidateDescriptor)))
}
diagnostics.addAll(towerCandidate.diagnostics)
// todo smartcast on receiver diagnostic and CheckInstantiationOfAbstractClass
compatibilityChecker {
if (it.hasContradiction) return@compatibilityChecker
val (_, visibilityError) = it.checkCallableReference(
argument, dispatchCallableReceiver, extensionCallableReceiver, candidateDescriptor,
reflectionCandidateType, expectedType, scopeTower.lexicalScope.ownerDescriptor
)
diagnostics.addIfNotNull(visibilityError)
if (it.hasContradiction) diagnostics.add(
CallableReferenceNotCompatible(
argument,
candidateDescriptor,
expectedType,
reflectionCandidateType
)
)
}
return createReferenceCandidate()
return createCallableReferenceCallCandidate(diagnostics)
}
fun createCallableProcessor(explicitReceiver: DetailedReceiver?) =
createCallableReferenceProcessor(scopeTower, kotlinCall.rhsName, this, explicitReceiver)
private fun needCompatibilityResolveForCallableReference(
callableReferenceAdaptation: CallableReferenceAdaptation?,
candidate: CallableDescriptor
): Boolean {
// KT-13934: reference to companion object member via class name
if (candidate.containingDeclaration.isCompanionObject() && argument.lhsResult is LHSResult.Type) return true
if (candidate.containingDeclaration.isCompanionObject() && kotlinCall.lhsResult is LHSResult.Type) return true
if (callableReferenceAdaptation == null) return false
@@ -142,19 +141,13 @@ class CallableReferencesCandidateFactory(
callableReferenceAdaptation.coercionStrategy != CoercionStrategy.NO_COERCION ||
callableReferenceAdaptation.mappedArguments.values.any { it is ResolvedCallArgument.VarargArgument }
private enum class VarargMappingState {
UNMAPPED, MAPPED_WITH_PLAIN_ARGS, MAPPED_WITH_ARRAY
}
private fun getCallableReferenceAdaptation(
descriptor: FunctionDescriptor,
expectedType: UnwrappedType?,
unboundReceiverCount: Int,
builtins: KotlinBuiltIns
): CallableReferenceAdaptation? {
if (callComponents.languageVersionSettings.apiVersion < ApiVersion.KOTLIN_1_4) return null
if (expectedType == null) return null
if (expectedType == null || TypeUtils.noExpectedType(expectedType)) return null
// Do not adapt references against KCallable type as it's impossible to map defaults/vararg to absent parameters of KCallable
if (ReflectionTypes.hasKCallableTypeFqName(expectedType)) return null
@@ -302,7 +295,7 @@ class CallableReferencesCandidateFactory(
return when (varargMappingState) {
VarargMappingState.UNMAPPED -> {
if (KotlinBuiltIns.isArrayOrPrimitiveArray(expectedParameterType) ||
csBuilder.isTypeVariable(expectedParameterType)
expectedParameterType.constructor is TypeVariableTypeConstructor
) {
val arrayType = builtins.getPrimitiveArrayKotlinTypeByPrimitiveKotlinType(elementType)
?: builtins.getArrayType(Variance.OUT_VARIANCE, elementType)
@@ -327,7 +320,8 @@ class CallableReferencesCandidateFactory(
dispatchReceiver: CallableReceiver?,
extensionReceiver: CallableReceiver?,
expectedType: UnwrappedType?,
builtins: KotlinBuiltIns
builtins: KotlinBuiltIns,
buildTypeWithConversions: Boolean = true
): Pair<UnwrappedType, CallableReferenceAdaptation?> {
val argumentsAndReceivers = ArrayList<KotlinType>(descriptor.valueParameters.size + 2)
@@ -365,7 +359,7 @@ class CallableReferencesCandidateFactory(
builtins = builtins
)
val returnType = if (callableReferenceAdaptation == null) {
val returnType = if (callableReferenceAdaptation == null || !buildTypeWithConversions) {
descriptor.valueParameters.mapTo(argumentsAndReceivers) { it.type }
descriptorReturnType
} else {
@@ -380,7 +374,8 @@ class CallableReferencesCandidateFactory(
}
val suspendConversionStrategy = callableReferenceAdaptation?.suspendConversionStrategy
val isSuspend = descriptor.isSuspend || suspendConversionStrategy == SuspendConversionStrategy.SUSPEND_CONVERSION
val isSuspend = descriptor.isSuspend ||
(suspendConversionStrategy == SuspendConversionStrategy.SUSPEND_CONVERSION && buildTypeWithConversions)
callComponents.reflectionTypes.getKFunctionType(
Annotations.EMPTY, null, argumentsAndReceivers, null,
@@ -397,7 +392,7 @@ class CallableReferencesCandidateFactory(
private fun toCallableReceiver(receiver: ReceiverValueWithSmartCastInfo, isExplicit: Boolean): CallableReceiver {
if (!isExplicit) return CallableReceiver.ScopeReceiver(receiver)
return when (val lhsResult = argument.lhsResult) {
return when (val lhsResult = kotlinCall.lhsResult) {
is LHSResult.Expression -> CallableReceiver.ExplicitValueReceiver(receiver)
is LHSResult.Type -> {
if (lhsResult.qualifier?.classValueReceiver?.type == receiver.receiverValue.type) {
@@ -410,4 +405,8 @@ class CallableReferencesCandidateFactory(
else -> throw IllegalStateException("Unsupported kind of lhsResult: $lhsResult")
}
}
}
private enum class VarargMappingState {
UNMAPPED, MAPPED_WITH_PLAIN_ARGS, MAPPED_WITH_ARRAY
}
}
@@ -71,6 +71,18 @@ fun KotlinCall.checkCallInvariants() {
}
KotlinCallKind.CALLABLE_REFERENCE -> {
assert(argumentsInParenthesis.isEmpty()) {
"Callable references can't have value arguments"
}
assert(typeArguments.isEmpty()) {
"Callable references can't have explicit type arguments"
}
assert(externalArgument == null) {
"External argument is not allowed not for function call: $externalArgument."
}
}
KotlinCallKind.UNSUPPORTED -> error("Call with UNSUPPORTED kind")
}
}
@@ -34,6 +34,18 @@ abstract class InapplicableArgumentDiagnostic : KotlinCallDiagnostic(INAPPLICABL
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this)
}
abstract class CallableReferenceInapplicableDiagnostic(
private val argument: CallableReferenceResolutionAtom,
applicability: CandidateApplicability = INAPPLICABLE
) : KotlinCallDiagnostic(applicability) {
override fun report(reporter: DiagnosticReporter) {
when (argument) {
is CallableReferenceKotlinCall -> reporter.onCall(this)
is CallableReferenceKotlinCallArgument -> reporter.onCallArgument(argument, this)
}
}
}
// ArgumentsToParameterMapper
class TooManyArguments(val argument: KotlinCallArgument, val descriptor: CallableDescriptor) :
KotlinCallDiagnostic(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR) {
@@ -99,38 +111,40 @@ class WrongCountOfTypeArguments(
// Callable reference resolution
class CallableReferenceNotCompatible(
override val argument: CallableReferenceKotlinCallArgument,
argument: CallableReferenceResolutionAtom,
val candidate: CallableMemberDescriptor,
val expectedType: UnwrappedType?,
val callableReverenceType: UnwrappedType
) : InapplicableArgumentDiagnostic()
) : CallableReferenceInapplicableDiagnostic(argument)
// supported by FE but not supported by BE now
class CallableReferencesDefaultArgumentUsed(
val argument: CallableReferenceKotlinCallArgument,
val argument: CallableReferenceResolutionAtom,
val candidate: CallableDescriptor,
val defaultsCount: Int
) : KotlinCallDiagnostic(IMPOSSIBLE_TO_GENERATE) {
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this)
}
) : CallableReferenceInapplicableDiagnostic(argument)
class NotCallableMemberReference(
override val argument: CallableReferenceKotlinCallArgument,
val argument: CallableReferenceResolutionAtom,
val candidate: CallableDescriptor
) : InapplicableArgumentDiagnostic()
) : CallableReferenceInapplicableDiagnostic(argument)
class NoneCallableReferenceCandidates(override val argument: CallableReferenceKotlinCallArgument) : InapplicableArgumentDiagnostic()
class NoneCallableReferenceCallCandidates(val argument: CallableReferenceKotlinCallArgument) :
CallableReferenceInapplicableDiagnostic(argument)
class CallableReferenceCandidatesAmbiguity(
override val argument: CallableReferenceKotlinCallArgument,
val candidates: Collection<CallableReferenceCandidate>
) : InapplicableArgumentDiagnostic()
class CallableReferenceCallCandidatesAmbiguity(
val argument: CallableReferenceKotlinCallArgument,
val candidates: Collection<CallableReferenceResolutionCandidate>
) : CallableReferenceInapplicableDiagnostic(argument)
class NotCallableExpectedType(
override val argument: CallableReferenceKotlinCallArgument,
val argument: CallableReferenceKotlinCallArgument,
val expectedType: UnwrappedType,
val notCallableTypeConstructor: TypeConstructor
) : InapplicableArgumentDiagnostic()
) : CallableReferenceInapplicableDiagnostic(argument)
class AdaptedCallableReferenceIsUsedWithReflection(val argument: CallableReferenceResolutionAtom) :
CallableReferenceInapplicableDiagnostic(argument, RESOLVED_WITH_ERROR)
// SmartCasts
class SmartCastDiagnostic(
@@ -258,15 +272,6 @@ class CompatibilityWarningOnArgument(
}
}
class AdaptedCallableReferenceIsUsedWithReflection(
val argument: CallableReferenceKotlinCallArgument,
) : KotlinCallDiagnostic(RESOLVED_WITH_ERROR) {
override fun report(reporter: DiagnosticReporter) {
reporter.onCallArgument(argument, this)
}
}
class KotlinConstraintSystemDiagnostic(
val error: ConstraintSystemError
) : KotlinCallDiagnostic(error.applicability) {
@@ -58,6 +58,16 @@ enum class KotlinCallKind(vararg resolutionPart: ResolutionPart) {
PostponedVariablesInitializerResolutionPart
),
INVOKE(*FUNCTION.resolutionSequence.toTypedArray()),
CALLABLE_REFERENCE(
CheckVisibility,
NoTypeArguments,
NoArguments,
CreateFreshVariablesSubstitutor,
CollectionTypeVariableUsagesInfo,
CheckReceivers,
CheckCallableReference,
CompatibilityOfTypeVariableAsIntersectionTypePart
),
UNSUPPORTED();
val resolutionSequence = resolutionPart.asList()
@@ -81,7 +81,9 @@ open class MutableResolvedCallAtom(
override val candidateDescriptor: CallableDescriptor, // original candidate descriptor
override val explicitReceiverKind: ExplicitReceiverKind,
override val dispatchReceiverArgument: SimpleKotlinCallArgument?,
override val extensionReceiverArgument: SimpleKotlinCallArgument?
override val extensionReceiverArgument: SimpleKotlinCallArgument?,
open val reflectionCandidateType: UnwrappedType? = null,
open val candidate: CallableReferenceResolutionCandidate? = null
) : ResolvedCallAtom() {
override lateinit var typeArgumentMappingByOriginal: TypeArgumentsToParametersMapper.TypeArgumentsMapping
override lateinit var argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
@@ -45,4 +45,7 @@ class TypeApproximator(
// resultType <: type
fun approximateToSubType(type: UnwrappedType, conf: TypeApproximatorConfiguration): UnwrappedType? =
super.approximateToSubType(type, conf) as UnwrappedType?
fun approximateTo(type: UnwrappedType, conf: TypeApproximatorConfiguration, toSuperType: Boolean): UnwrappedType? =
if (toSuperType) approximateToSuperType(type, conf) else approximateToSubType(type, conf)
}