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:
-6
@@ -2813,12 +2813,6 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/referenceAdaptationCompatibility.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("referenceAdaptationHasDependencyOnApi14.kt")
|
||||
public void testReferenceAdaptationHasDependencyOnApi14() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/referenceAdaptationHasDependencyOnApi14.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("referenceToCompanionObjectMemberViaClassName.kt")
|
||||
public void testReferenceToCompanionObjectMemberViaClassName() throws Exception {
|
||||
|
||||
-6
@@ -2813,12 +2813,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/referenceAdaptationCompatibility.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("referenceAdaptationHasDependencyOnApi14.kt")
|
||||
public void testReferenceAdaptationHasDependencyOnApi14() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/referenceAdaptationHasDependencyOnApi14.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("referenceToCompanionObjectMemberViaClassName.kt")
|
||||
public void testReferenceToCompanionObjectMemberViaClassName() throws Exception {
|
||||
|
||||
-6
@@ -2813,12 +2813,6 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/referenceAdaptationCompatibility.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("referenceAdaptationHasDependencyOnApi14.kt")
|
||||
public void testReferenceAdaptationHasDependencyOnApi14() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/referenceAdaptationHasDependencyOnApi14.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("referenceToCompanionObjectMemberViaClassName.kt")
|
||||
public void testReferenceToCompanionObjectMemberViaClassName() throws Exception {
|
||||
|
||||
+9
-2
@@ -20,16 +20,23 @@ import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.CALLABLE_REFERENCE_TO_JAVA_SYNTHETIC_PROPERTY
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED
|
||||
import org.jetbrains.kotlin.resolve.calls.util.isCallableReference
|
||||
import org.jetbrains.kotlin.psi.KtPropertyDelegate
|
||||
import org.jetbrains.kotlin.psi.psiUtil.unwrapParenthesesLabelsAndAnnotationsDeeply
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.util.extractCallableReferenceExpression
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||
|
||||
class UnsupportedSyntheticCallableReferenceChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
// TODO: support references to synthetic Java extension properties (KT-8575)
|
||||
if (resolvedCall.call.isCallableReference() && resolvedCall.resultingDescriptor is SyntheticJavaPropertyDescriptor) {
|
||||
val callableReferenceExpression = resolvedCall.call.extractCallableReferenceExpression() ?: return
|
||||
|
||||
// We allow resolve of top-level callable reference to synthetic Java extension properties in delegate position
|
||||
if (callableReferenceExpression.unwrapParenthesesLabelsAndAnnotationsDeeply() is KtPropertyDelegate) return
|
||||
|
||||
if (resolvedCall.resultingDescriptor is SyntheticJavaPropertyDescriptor) {
|
||||
val diagnostic = if (
|
||||
context.languageVersionSettings.supportsFeature(LanguageFeature.NewInference) &&
|
||||
context.languageVersionSettings.supportsFeature(LanguageFeature.ReferencesToSyntheticJavaProperties)
|
||||
|
||||
+32
-10
@@ -156,16 +156,16 @@ class DiagnosticReporterByTrackingStrategy(
|
||||
MixingNamedAndPositionArguments::class.java ->
|
||||
trace.report(MIXING_NAMED_AND_POSITIONED_ARGUMENTS.on(callArgument.psiCallArgument.valueArgument.asElement()))
|
||||
|
||||
NoneCallableReferenceCandidates::class.java -> {
|
||||
val expression = diagnostic.cast<NoneCallableReferenceCandidates>()
|
||||
NoneCallableReferenceCallCandidates::class.java -> {
|
||||
val expression = diagnostic.cast<NoneCallableReferenceCallCandidates>()
|
||||
.argument.safeAs<CallableReferenceKotlinCallArgumentImpl>()?.ktCallableReferenceExpression
|
||||
if (expression != null) {
|
||||
trace.report(UNRESOLVED_REFERENCE.on(expression.callableReference, expression.callableReference))
|
||||
}
|
||||
}
|
||||
|
||||
CallableReferenceCandidatesAmbiguity::class.java -> {
|
||||
val ambiguityDiagnostic = diagnostic as CallableReferenceCandidatesAmbiguity
|
||||
CallableReferenceCallCandidatesAmbiguity::class.java -> {
|
||||
val ambiguityDiagnostic = diagnostic as CallableReferenceCallCandidatesAmbiguity
|
||||
val expression = when (val psiExpression = ambiguityDiagnostic.argument.psiExpression) {
|
||||
is KtPsiUtil.KtExpressionWrapper -> psiExpression.baseExpression
|
||||
else -> psiExpression
|
||||
@@ -197,14 +197,18 @@ class DiagnosticReporterByTrackingStrategy(
|
||||
"diagnostic ($diagnostic) should have type CallableReferencesDefaultArgumentUsed"
|
||||
}
|
||||
|
||||
diagnostic.argument.psiExpression?.let {
|
||||
trace.report(
|
||||
UNSUPPORTED_FEATURE.on(
|
||||
it, LanguageFeature.FunctionReferenceWithDefaultValueAsOtherType to context.languageVersionSettings
|
||||
)
|
||||
)
|
||||
val callableReferenceExpression = diagnostic.argument.call.extractCallableReferenceExpression()
|
||||
|
||||
require(callableReferenceExpression != null) {
|
||||
"A call element must be callable reference for `CallableReferencesDefaultArgumentUsed`"
|
||||
}
|
||||
|
||||
trace.report(
|
||||
UNSUPPORTED_FEATURE.on(
|
||||
callableReferenceExpression,
|
||||
LanguageFeature.FunctionReferenceWithDefaultValueAsOtherType to context.languageVersionSettings
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
ResolvedToSamWithVarargDiagnostic::class.java -> {
|
||||
@@ -342,7 +346,25 @@ class DiagnosticReporterByTrackingStrategy(
|
||||
)
|
||||
}
|
||||
|
||||
private fun reportCallableReferenceConstraintError(
|
||||
error: NewConstraintMismatch,
|
||||
rhsExpression: KtSimpleNameExpression
|
||||
) {
|
||||
trace.report(TYPE_MISMATCH.on(rhsExpression, error.lowerKotlinType, error.upperKotlinType))
|
||||
}
|
||||
|
||||
private fun reportConstraintErrorByPosition(error: NewConstraintMismatch, position: ConstraintPosition) {
|
||||
if (position is CallableReferenceConstraintPositionImpl) {
|
||||
val callableReferenceExpression = position.callableReferenceCall.call.extractCallableReferenceExpression()
|
||||
|
||||
require(callableReferenceExpression != null) {
|
||||
"There should be the corresponding callable reference expression for `CallableReferenceConstraintPositionImpl`"
|
||||
}
|
||||
|
||||
reportCallableReferenceConstraintError(error, callableReferenceExpression.callableReference)
|
||||
return
|
||||
}
|
||||
|
||||
val argument =
|
||||
when (position) {
|
||||
is ArgumentConstraintPositionImpl -> position.argument
|
||||
|
||||
+30
-9
@@ -20,15 +20,21 @@ import org.jetbrains.kotlin.psi.psiUtil.getBinaryWithTypeParent
|
||||
import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.KotlinCallResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.util.extractCallableReferenceExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.components.*
|
||||
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.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
|
||||
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.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategyImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
|
||||
@@ -71,7 +77,8 @@ class KotlinResolutionCallbacksImpl(
|
||||
private val deprecationResolver: DeprecationResolver,
|
||||
private val moduleDescriptor: ModuleDescriptor,
|
||||
private val topLevelCallContext: BasicCallResolutionContext,
|
||||
private val missingSupertypesResolver: MissingSupertypesResolver
|
||||
private val missingSupertypesResolver: MissingSupertypesResolver,
|
||||
private val kotlinCallResolver: KotlinCallResolver,
|
||||
) : KotlinResolutionCallbacks {
|
||||
class LambdaInfo(val expectedType: UnwrappedType, val contextDependency: ContextDependency) {
|
||||
val returnStatements = ArrayList<Pair<KtReturnExpression, LambdaContextInfo?>>()
|
||||
@@ -82,6 +89,19 @@ class KotlinResolutionCallbacksImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun resolveCallableReferenceArgument(
|
||||
argument: CallableReferenceKotlinCallArgument,
|
||||
expectedType: UnwrappedType?,
|
||||
baseSystem: ConstraintStorage,
|
||||
): Collection<CallableReferenceResolutionCandidate> =
|
||||
kotlinCallResolver.resolveCallableReferenceArgument(argument, expectedType, baseSystem, this)
|
||||
|
||||
override fun getCandidateFactoryForInvoke(
|
||||
scopeTower: ImplicitScopeTower,
|
||||
kotlinCall: KotlinCall
|
||||
): PSICallResolver.FactoryProviderForInvoke =
|
||||
psiCallResolver.FactoryProviderForInvoke(topLevelCallContext, scopeTower, kotlinCall as PSIKotlinCallImpl)
|
||||
|
||||
override fun analyzeAndGetLambdaReturnArguments(
|
||||
lambdaArgument: LambdaKotlinCallArgument,
|
||||
isSuspend: Boolean,
|
||||
@@ -113,21 +133,22 @@ class KotlinResolutionCallbacksImpl(
|
||||
}
|
||||
|
||||
val deparenthesizedExpression = KtPsiUtil.deparenthesize(ktExpression) ?: ktExpression
|
||||
if (deparenthesizedExpression is KtCallableReferenceExpression) {
|
||||
return psiCallResolver.createCallableReferenceKotlinCallArgument(
|
||||
|
||||
return if (deparenthesizedExpression is KtCallableReferenceExpression) {
|
||||
psiCallResolver.createCallableReferenceKotlinCallArgument(
|
||||
newContext, deparenthesizedExpression, DataFlowInfo.EMPTY,
|
||||
CallMaker.makeExternalValueArgument(deparenthesizedExpression),
|
||||
argumentName = null,
|
||||
outerCallContext,
|
||||
tracingStrategy = TracingStrategyImpl.create(deparenthesizedExpression.callableReference, newContext.call)
|
||||
)
|
||||
} else {
|
||||
createSimplePSICallArgument(
|
||||
trace.bindingContext, outerCallContext.statementFilter, outerCallContext.scope.ownerDescriptor,
|
||||
CallMaker.makeExternalValueArgument(ktExpression), DataFlowInfo.EMPTY, typeInfo, languageVersionSettings,
|
||||
dataFlowValueFactory, outerCallContext.call
|
||||
)
|
||||
}
|
||||
|
||||
return createSimplePSICallArgument(
|
||||
trace.bindingContext, outerCallContext.statementFilter, outerCallContext.scope.ownerDescriptor,
|
||||
CallMaker.makeExternalValueArgument(ktExpression), DataFlowInfo.EMPTY, typeInfo, languageVersionSettings,
|
||||
dataFlowValueFactory, outerCallContext.call
|
||||
)
|
||||
}
|
||||
|
||||
val lambdaInfo = LambdaInfo(
|
||||
|
||||
+6
-3
@@ -213,7 +213,10 @@ class KotlinToResolvedCallTransformer(
|
||||
|
||||
return if (completedSimpleAtom.atom.callKind == KotlinCallKind.CALLABLE_REFERENCE) {
|
||||
NewCallableReferenceResolvedCall(
|
||||
completedSimpleAtom as ResolvedCallableReferenceCallAtom, typeApproximator, resultSubstitutor
|
||||
completedSimpleAtom as ResolvedCallableReferenceCallAtom,
|
||||
typeApproximator,
|
||||
expressionTypingServices.languageVersionSettings,
|
||||
resultSubstitutor
|
||||
)
|
||||
} else {
|
||||
NewResolvedCallImpl(
|
||||
@@ -384,7 +387,7 @@ class KotlinToResolvedCallTransformer(
|
||||
)
|
||||
}
|
||||
|
||||
private fun getResolvedCallForArgumentExpression(expression: KtExpression, context: BasicCallResolutionContext) =
|
||||
fun getResolvedCallForArgumentExpression(expression: KtExpression, context: BasicCallResolutionContext) =
|
||||
if (!ExpressionTypingUtils.dependsOnExpectedType(expression))
|
||||
null
|
||||
else
|
||||
@@ -486,7 +489,7 @@ class KotlinToResolvedCallTransformer(
|
||||
|
||||
outerTracingStrategy.bindReference(trace, variableCall)
|
||||
outerTracingStrategy.bindResolvedCall(trace, variableAsFunction)
|
||||
functionCall.kotlinCall.psiKotlinCall.tracingStrategy.bindReference(trace, functionCall)
|
||||
functionCall.psiKotlinCall.tracingStrategy.bindReference(trace, functionCall)
|
||||
}
|
||||
|
||||
fun reportCallDiagnostic(
|
||||
|
||||
+125
-26
@@ -7,54 +7,68 @@ package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
|
||||
import org.jetbrains.kotlin.psi.Call
|
||||
import org.jetbrains.kotlin.psi.ValueArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.substitute
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.substituteAndApproximateTypes
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.util.isNotSimpleCall
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeApproximator
|
||||
import org.jetbrains.kotlin.types.isFlexible
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.compactIfPossible
|
||||
|
||||
sealed class NewAbstractResolvedCall<D : CallableDescriptor> : ResolvedCall<D> {
|
||||
abstract val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
|
||||
abstract val kotlinCall: KotlinCall
|
||||
abstract val kotlinCall: KotlinCall?
|
||||
abstract val languageVersionSettings: LanguageVersionSettings
|
||||
abstract val resolvedCallAtom: ResolvedCallAtom?
|
||||
abstract val psiKotlinCall: PSIKotlinCall
|
||||
abstract val isCompleted: Boolean
|
||||
abstract val typeApproximator: TypeApproximator
|
||||
abstract val freshSubstitutor: FreshVariableNewTypeSubstitutor?
|
||||
|
||||
protected var argumentToParameterMap: Map<ValueArgument, ArgumentMatchImpl>? = null
|
||||
protected var _valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>? = null
|
||||
protected open val positionDependentApproximation = false
|
||||
|
||||
private var argumentToParameterMap: Map<ValueArgument, ArgumentMatchImpl>? = null
|
||||
private var valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>? = null
|
||||
private var nonTrivialUpdatedResultInfo: DataFlowInfo? = null
|
||||
private var isCompleted: Boolean = false
|
||||
|
||||
abstract fun updateDispatchReceiverType(newType: KotlinType)
|
||||
abstract fun updateExtensionReceiverType(newType: KotlinType)
|
||||
abstract fun containsOnlyOnlyInputTypesErrors(): Boolean
|
||||
abstract fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?)
|
||||
abstract fun argumentToParameterMap(
|
||||
resultingDescriptor: CallableDescriptor,
|
||||
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>,
|
||||
): Map<ValueArgument, ArgumentMatchImpl>
|
||||
|
||||
override fun getCall(): Call = kotlinCall.psiKotlinCall.psiCall
|
||||
override fun getCall(): Call = psiKotlinCall.psiCall
|
||||
|
||||
override fun getValueArguments(): Map<ValueParameterDescriptor, ResolvedValueArgument> {
|
||||
if (_valueArguments == null) {
|
||||
_valueArguments = createValueArguments()
|
||||
if (valueArguments == null) {
|
||||
valueArguments = createValueArguments()
|
||||
}
|
||||
return _valueArguments!!
|
||||
return valueArguments!!
|
||||
}
|
||||
|
||||
fun setValueArguments(m: Map<ValueParameterDescriptor, ResolvedValueArgument>) {
|
||||
_valueArguments = m
|
||||
}
|
||||
|
||||
open fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?) {}
|
||||
|
||||
override fun getValueArgumentsByIndex(): List<ResolvedValueArgument>? {
|
||||
val arguments = ArrayList<ResolvedValueArgument?>(candidateDescriptor.valueParameters.size)
|
||||
for (i in 0 until candidateDescriptor.valueParameters.size) {
|
||||
arguments.add(null)
|
||||
}
|
||||
|
||||
for ((parameterDescriptor, value) in valueArguments) {
|
||||
for ((parameterDescriptor, value) in getValueArguments()) {
|
||||
val oldValue = arguments.set(parameterDescriptor.index, value)
|
||||
if (oldValue != null) {
|
||||
return null
|
||||
@@ -69,36 +83,121 @@ sealed class NewAbstractResolvedCall<D : CallableDescriptor> : ResolvedCall<D> {
|
||||
|
||||
override fun getArgumentMapping(valueArgument: ValueArgument): ArgumentMapping {
|
||||
if (argumentToParameterMap == null) {
|
||||
argumentToParameterMap = argumentToParameterMap(resultingDescriptor, valueArguments)
|
||||
updateArgumentsMapping(argumentToParameterMap(resultingDescriptor, getValueArguments()))
|
||||
}
|
||||
return argumentToParameterMap!![valueArgument] ?: ArgumentUnmapped
|
||||
}
|
||||
|
||||
override fun getDataFlowInfoForArguments() = object : DataFlowInfoForArguments {
|
||||
override fun getResultInfo(): DataFlowInfo = nonTrivialUpdatedResultInfo ?: kotlinCall.psiKotlinCall.resultDataFlowInfo
|
||||
override fun getResultInfo(): DataFlowInfo = nonTrivialUpdatedResultInfo ?: psiKotlinCall.resultDataFlowInfo
|
||||
|
||||
override fun getInfo(valueArgument: ValueArgument): DataFlowInfo {
|
||||
val externalPsiCallArgument = kotlinCall.externalArgument?.psiCallArgument
|
||||
val externalPsiCallArgument = kotlinCall?.externalArgument?.psiCallArgument
|
||||
if (externalPsiCallArgument?.valueArgument == valueArgument) {
|
||||
return externalPsiCallArgument.dataFlowInfoAfterThisArgument
|
||||
}
|
||||
return kotlinCall.psiKotlinCall.dataFlowInfoForArguments.getInfo(valueArgument)
|
||||
return psiKotlinCall.dataFlowInfoForArguments.getInfo(valueArgument)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateValueArguments(newValueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>?) {
|
||||
valueArguments = newValueArguments
|
||||
}
|
||||
|
||||
fun substituteReceivers(substitutor: NewTypeSubstitutor?) {
|
||||
if (substitutor != null) {
|
||||
// todo: add asset that we do not complete call many times
|
||||
isCompleted = true
|
||||
|
||||
dispatchReceiver?.type?.let {
|
||||
val newType = substitutor.safeSubstitute(it.unwrap())
|
||||
updateDispatchReceiverType(newType)
|
||||
}
|
||||
|
||||
extensionReceiver?.type?.let {
|
||||
val newType = substitutor.safeSubstitute(it.unwrap())
|
||||
updateExtensionReceiverType(newType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isCompleted() = isCompleted
|
||||
|
||||
// Currently, updated only with info from effect system
|
||||
internal fun updateResultingDataFlowInfo(dataFlowInfo: DataFlowInfo) {
|
||||
if (dataFlowInfo == DataFlowInfo.EMPTY) return
|
||||
assert(nonTrivialUpdatedResultInfo == null) {
|
||||
"Attempt to rewrite resulting dataFlowInfo enhancement for call: $kotlinCall"
|
||||
}
|
||||
nonTrivialUpdatedResultInfo = dataFlowInfo.and(kotlinCall.psiKotlinCall.resultDataFlowInfo)
|
||||
nonTrivialUpdatedResultInfo = dataFlowInfo.and(psiKotlinCall.resultDataFlowInfo)
|
||||
}
|
||||
|
||||
abstract fun argumentToParameterMap(
|
||||
resultingDescriptor: CallableDescriptor,
|
||||
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>,
|
||||
): Map<ValueArgument, ArgumentMatchImpl>
|
||||
protected fun updateArgumentsMapping(newMapping: Map<ValueArgument, ArgumentMatchImpl>?) {
|
||||
argumentToParameterMap = newMapping
|
||||
}
|
||||
|
||||
protected fun substitutedResultingDescriptor(substitutor: NewTypeSubstitutor?) =
|
||||
when (val candidateDescriptor = candidateDescriptor) {
|
||||
is ClassConstructorDescriptor, is SyntheticMemberDescriptor<*> -> {
|
||||
val explicitTypeArguments = resolvedCallAtom?.atom?.typeArguments?.filterIsInstance<SimpleTypeArgument>() ?: emptyList()
|
||||
|
||||
candidateDescriptor.substituteInferredVariablesAndApproximate(
|
||||
getSubstitutorWithoutFlexibleTypes(substitutor, explicitTypeArguments),
|
||||
)
|
||||
}
|
||||
is FunctionDescriptor -> {
|
||||
candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor, candidateDescriptor.isNotSimpleCall())
|
||||
}
|
||||
is PropertyDescriptor -> {
|
||||
if (candidateDescriptor.isNotSimpleCall()) {
|
||||
candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor)
|
||||
} else {
|
||||
candidateDescriptor
|
||||
}
|
||||
}
|
||||
else -> candidateDescriptor
|
||||
}
|
||||
|
||||
private fun CallableDescriptor.substituteInferredVariablesAndApproximate(
|
||||
substitutor: NewTypeSubstitutor?,
|
||||
shouldApproximate: Boolean = true
|
||||
): CallableDescriptor {
|
||||
val inferredTypeVariablesSubstitutor = substitutor ?: FreshVariableNewTypeSubstitutor.Empty
|
||||
|
||||
val freshVariablesSubstituted = freshSubstitutor?.let(::substitute) ?: this
|
||||
val knownTypeParameterSubstituted = resolvedCallAtom?.knownParametersSubstitutor?.let(freshVariablesSubstituted::substitute)
|
||||
?: freshVariablesSubstituted
|
||||
|
||||
return knownTypeParameterSubstituted.substituteAndApproximateTypes(
|
||||
inferredTypeVariablesSubstitutor,
|
||||
typeApproximator = if (shouldApproximate) typeApproximator else null,
|
||||
positionDependentApproximation
|
||||
)
|
||||
}
|
||||
|
||||
private fun getSubstitutorWithoutFlexibleTypes(
|
||||
currentSubstitutor: NewTypeSubstitutor?,
|
||||
explicitTypeArguments: List<SimpleTypeArgument>,
|
||||
): NewTypeSubstitutor? {
|
||||
if (currentSubstitutor !is NewTypeSubstitutorByConstructorMap || explicitTypeArguments.isEmpty()) return currentSubstitutor
|
||||
if (!currentSubstitutor.map.any { (_, value) -> value.isFlexible() }) return currentSubstitutor
|
||||
|
||||
val typeVariables = freshSubstitutor?.freshVariables ?: return null
|
||||
val newSubstitutorMap = currentSubstitutor.map.toMutableMap()
|
||||
|
||||
explicitTypeArguments.forEachIndexed { index, typeArgument ->
|
||||
val typeVariableConstructor = typeVariables.getOrNull(index)?.freshTypeConstructor ?: return@forEachIndexed
|
||||
|
||||
newSubstitutorMap[typeVariableConstructor] =
|
||||
newSubstitutorMap[typeVariableConstructor]?.withNullabilityFromExplicitTypeArgument(typeArgument)
|
||||
?: return@forEachIndexed
|
||||
}
|
||||
|
||||
return NewTypeSubstitutorByConstructorMap(newSubstitutorMap)
|
||||
}
|
||||
|
||||
private fun KotlinType.withNullabilityFromExplicitTypeArgument(typeArgument: SimpleTypeArgument) =
|
||||
(if (typeArgument.type.isMarkedNullable) makeNullable() else makeNotNullable()).unwrap()
|
||||
|
||||
private fun createValueArguments(): Map<ValueParameterDescriptor, ResolvedValueArgument> =
|
||||
LinkedHashMap<ValueParameterDescriptor, ResolvedValueArgument>().also { result ->
|
||||
|
||||
@@ -325,7 +325,10 @@ internal fun createSimplePSICallArgument(
|
||||
call: Call
|
||||
): SimplePSIKotlinCallArgument? {
|
||||
val ktExpression = KtPsiUtil.getLastElementDeparenthesized(valueArgument.getArgumentExpression(), statementFilter) ?: return null
|
||||
val partiallyResolvedCall = ktExpression.getCall(bindingContext)?.let {
|
||||
val ktExpressionToExtractResolvedCall =
|
||||
if (ktExpression is KtCallableReferenceExpression) ktExpression.callableReference else ktExpression
|
||||
|
||||
val partiallyResolvedCall = ktExpressionToExtractResolvedCall.getCall(bindingContext)?.let {
|
||||
bindingContext.get(BindingContext.ONLY_RESOLVED_CALL, it)?.result
|
||||
}
|
||||
// todo hack for if expression: sometimes we not write properly type information for branches
|
||||
|
||||
+59
-185
@@ -7,61 +7,53 @@ package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
|
||||
import org.jetbrains.kotlin.psi.ValueArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.substitute
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.substituteAndApproximateTypes
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.util.isNotSimpleCall
|
||||
import org.jetbrains.kotlin.resolve.calls.util.toResolutionStatus
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
|
||||
class NewCallableReferenceResolvedCall<D : CallableDescriptor>(
|
||||
val resolvedAtom: ResolvedCallableReferenceAtom,
|
||||
val typeApproximator: TypeApproximator,
|
||||
substitutor: NewTypeSubstitutor?,
|
||||
override val typeApproximator: TypeApproximator,
|
||||
override val languageVersionSettings: LanguageVersionSettings,
|
||||
substitutor: NewTypeSubstitutor? = null,
|
||||
) : NewAbstractResolvedCall<D>() {
|
||||
override var isCompleted = false
|
||||
private set
|
||||
override val positionDependentApproximation: Boolean = true
|
||||
override val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument> = emptyMap()
|
||||
|
||||
override val resolvedCallAtom: MutableResolvedCallAtom? = when (resolvedAtom) {
|
||||
is ResolvedCallableReferenceCallAtom -> resolvedAtom
|
||||
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate?.resolvedCall
|
||||
}
|
||||
override val resolvedCallAtom: ResolvedCallableReferenceCallAtom?
|
||||
get() = when (resolvedAtom) {
|
||||
is ResolvedCallableReferenceCallAtom -> resolvedAtom
|
||||
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate?.resolvedCall
|
||||
}
|
||||
|
||||
override val psiKotlinCall: PSIKotlinCall = when (resolvedAtom) {
|
||||
is ResolvedCallableReferenceCallAtom -> resolvedAtom.atom.psiKotlinCall
|
||||
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.atom.call.psiKotlinCall
|
||||
}
|
||||
override val psiKotlinCall: PSIKotlinCall =
|
||||
when (resolvedAtom) {
|
||||
is ResolvedCallableReferenceCallAtom -> resolvedAtom.atom.psiKotlinCall
|
||||
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.atom.call.psiKotlinCall
|
||||
}
|
||||
|
||||
init {
|
||||
setResultingSubstitutor(substitutor)
|
||||
}
|
||||
override val freshSubstitutor: FreshVariableNewTypeSubstitutor?
|
||||
get() = when (resolvedAtom) {
|
||||
is ResolvedCallableReferenceCallAtom -> resolvedAtom.freshVariablesSubstitutor
|
||||
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate?.freshVariablesSubstitutor
|
||||
}
|
||||
|
||||
override val kotlinCall: KotlinCall?
|
||||
get() = when (resolvedAtom) {
|
||||
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate?.kotlinCall?.call
|
||||
is ResolvedCallableReferenceCallAtom -> resolvedAtom.atom
|
||||
}
|
||||
|
||||
var diagnostics: Collection<KotlinCallDiagnostic> = mutableListOf()
|
||||
private lateinit var resultingDescriptor: D
|
||||
private lateinit var typeArguments: List<UnwrappedType>
|
||||
|
||||
override fun getStatus(): ResolutionStatus {
|
||||
return getResultApplicability(diagnostics).toResolutionStatus()
|
||||
}
|
||||
|
||||
override fun getCandidateDescriptor(): D = when (resolvedAtom) {
|
||||
is ResolvedCallableReferenceCallAtom -> resolvedAtom.candidateDescriptor as D
|
||||
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate?.candidate as D
|
||||
}
|
||||
|
||||
override fun getResultingDescriptor(): D = resultingDescriptor
|
||||
|
||||
private var extensionReceiver = when (resolvedAtom) {
|
||||
private var extensionReceiver: ReceiverValue? = when (resolvedAtom) {
|
||||
is ResolvedCallableReferenceCallAtom -> resolvedAtom.extensionReceiverArgument?.receiverValue
|
||||
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate?.extensionReceiver?.receiver?.receiverValue
|
||||
}
|
||||
@@ -72,35 +64,25 @@ class NewCallableReferenceResolvedCall<D : CallableDescriptor>(
|
||||
}
|
||||
|
||||
override fun getExtensionReceiver(): ReceiverValue? = extensionReceiver
|
||||
|
||||
override fun getDispatchReceiver(): ReceiverValue? = dispatchReceiver
|
||||
|
||||
override fun getExplicitReceiverKind(): ExplicitReceiverKind = when (resolvedAtom) {
|
||||
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate!!.explicitReceiverKind
|
||||
is ResolvedCallableReferenceCallAtom -> resolvedAtom.explicitReceiverKind
|
||||
override fun updateDispatchReceiverType(newType: KotlinType) {
|
||||
if (dispatchReceiver?.type == newType) return
|
||||
dispatchReceiver = dispatchReceiver?.replaceType(newType)
|
||||
}
|
||||
|
||||
override fun getValueArguments(): Map<ValueParameterDescriptor, ResolvedValueArgument> = _valueArguments ?: emptyMap()
|
||||
|
||||
override fun getValueArgumentsByIndex(): List<ResolvedValueArgument>? {
|
||||
val arguments = ArrayList<ResolvedValueArgument?>(candidateDescriptor.valueParameters.size)
|
||||
for (i in 0 until candidateDescriptor.valueParameters.size) {
|
||||
arguments.add(null)
|
||||
}
|
||||
|
||||
for ((parameterDescriptor, value) in valueArguments) {
|
||||
val oldValue = arguments.set(parameterDescriptor.index, value)
|
||||
if (oldValue != null) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments.any { it == null }) return null
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return arguments as List<ResolvedValueArgument>
|
||||
override fun updateExtensionReceiverType(newType: KotlinType) {
|
||||
if (extensionReceiver?.type == newType) return
|
||||
extensionReceiver = extensionReceiver?.replaceType(newType)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun getCandidateDescriptor(): D = when (resolvedAtom) {
|
||||
is ResolvedCallableReferenceCallAtom -> resolvedAtom.candidateDescriptor as D
|
||||
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate?.candidate as D
|
||||
}
|
||||
|
||||
override fun getResultingDescriptor(): D = resultingDescriptor
|
||||
override fun getArgumentMapping(valueArgument: ValueArgument): ArgumentMapping = ArgumentUnmapped
|
||||
|
||||
override fun getTypeArguments(): Map<TypeParameterDescriptor, KotlinType> {
|
||||
@@ -108,150 +90,42 @@ class NewCallableReferenceResolvedCall<D : CallableDescriptor>(
|
||||
return typeParameters.zip(typeArguments).toMap()
|
||||
}
|
||||
|
||||
private lateinit var typeArguments: List<UnwrappedType>
|
||||
override fun getStatus() = CandidateApplicability.RESOLVED.toResolutionStatus()
|
||||
|
||||
override fun getExplicitReceiverKind() = when (resolvedAtom) {
|
||||
is ResolvedCallableReferenceArgumentAtom ->
|
||||
resolvedAtom.candidate?.explicitReceiverKind ?: ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
|
||||
is ResolvedCallableReferenceCallAtom -> resolvedAtom.explicitReceiverKind
|
||||
}
|
||||
|
||||
override fun getDataFlowInfoForArguments(): DataFlowInfoForArguments =
|
||||
MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY)
|
||||
|
||||
override fun getSmartCastDispatchReceiverType(): KotlinType? = null
|
||||
|
||||
|
||||
private fun updateDispatchReceiverType(newType: KotlinType) {
|
||||
if (dispatchReceiver?.type == newType) return
|
||||
dispatchReceiver = dispatchReceiver?.replaceType(newType)
|
||||
}
|
||||
|
||||
private fun updateExtensionReceiverType(newType: KotlinType) {
|
||||
if (extensionReceiver?.type == newType) return
|
||||
extensionReceiver = extensionReceiver?.replaceType(newType)
|
||||
}
|
||||
|
||||
override fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?) {
|
||||
//clear cached values
|
||||
if (substitutor != null) {
|
||||
isCompleted = true
|
||||
dispatchReceiver?.type?.let {
|
||||
val newType = substitutor.safeSubstitute(it.unwrap())
|
||||
updateDispatchReceiverType(newType)
|
||||
}
|
||||
|
||||
extensionReceiver?.type?.let {
|
||||
val newType = substitutor.safeSubstitute(it.unwrap())
|
||||
updateExtensionReceiverType(newType)
|
||||
}
|
||||
}
|
||||
substituteReceivers(substitutor)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
resultingDescriptor = substitutedResultingDescriptor(substitutor) as D
|
||||
|
||||
val sub = when (resolvedAtom) {
|
||||
is ResolvedCallableReferenceCallAtom -> resolvedAtom.freshVariablesSubstitutor
|
||||
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate!!.freshVariablesSubstitutor!!
|
||||
}
|
||||
|
||||
typeArguments = sub.freshVariables.map {
|
||||
val substituted = (substitutor ?: FreshVariableNewTypeSubstitutor.Empty).safeSubstitute(it.defaultType)
|
||||
typeApproximator
|
||||
.approximateToSuperType(substituted, TypeApproximatorConfiguration.IntegerLiteralsTypesApproximation)
|
||||
?: substituted
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSubstitutorWithoutFlexibleTypes(
|
||||
currentSubstitutor: NewTypeSubstitutor?,
|
||||
explicitTypeArguments: List<SimpleTypeArgument>,
|
||||
): NewTypeSubstitutor? {
|
||||
if (currentSubstitutor !is NewTypeSubstitutorByConstructorMap || explicitTypeArguments.isEmpty()) return currentSubstitutor
|
||||
if (!currentSubstitutor.map.any { (_, value) -> value.isFlexible() }) return currentSubstitutor
|
||||
|
||||
val sub = when (resolvedAtom) {
|
||||
is ResolvedCallableReferenceCallAtom -> resolvedAtom.freshVariablesSubstitutor
|
||||
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate!!.freshVariablesSubstitutor!!
|
||||
}
|
||||
|
||||
val typeVariables = sub.freshVariables
|
||||
val newSubstitutorMap = currentSubstitutor.map.toMutableMap()
|
||||
|
||||
explicitTypeArguments.forEachIndexed { index, typeArgument ->
|
||||
val typeVariableConstructor = typeVariables.getOrNull(index)?.freshTypeConstructor ?: return@forEachIndexed
|
||||
|
||||
newSubstitutorMap[typeVariableConstructor] =
|
||||
newSubstitutorMap[typeVariableConstructor]?.withNullabilityFromExplicitTypeArgument(typeArgument)
|
||||
?: return@forEachIndexed
|
||||
}
|
||||
|
||||
return NewTypeSubstitutorByConstructorMap(newSubstitutorMap)
|
||||
}
|
||||
|
||||
private fun KotlinType.withNullabilityFromExplicitTypeArgument(typeArgument: SimpleTypeArgument) =
|
||||
(if (typeArgument.type.isMarkedNullable) makeNullable() else makeNotNullable()).unwrap()
|
||||
|
||||
private fun substitutedResultingDescriptor(substitutor: NewTypeSubstitutor?): CallableDescriptor {
|
||||
val candidateDescriptor = when (resolvedAtom) {
|
||||
is ResolvedCallableReferenceCallAtom -> resolvedAtom.candidateDescriptor
|
||||
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate!!.candidate
|
||||
}
|
||||
|
||||
return when (candidateDescriptor) {
|
||||
is ClassConstructorDescriptor, is SyntheticMemberDescriptor<*> -> {
|
||||
val explicitTypeArguments = emptyList<SimpleTypeArgument>()
|
||||
|
||||
candidateDescriptor.substituteInferredVariablesAndApproximate(
|
||||
getSubstitutorWithoutFlexibleTypes(substitutor, explicitTypeArguments),
|
||||
)
|
||||
freshSubstitutor?.let { freshSubstitutor ->
|
||||
typeArguments = freshSubstitutor.freshVariables.map {
|
||||
val substituted = (substitutor ?: FreshVariableNewTypeSubstitutor.Empty).safeSubstitute(it.defaultType)
|
||||
typeApproximator.approximateToSuperType(substituted, TypeApproximatorConfiguration.IntegerLiteralsTypesApproximation)
|
||||
?: substituted
|
||||
}
|
||||
is FunctionDescriptor -> {
|
||||
candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor, candidateDescriptor.isNotSimpleCall())
|
||||
}
|
||||
is PropertyDescriptor -> {
|
||||
if (candidateDescriptor.isNotSimpleCall()) {
|
||||
candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor)
|
||||
} else {
|
||||
candidateDescriptor
|
||||
}
|
||||
}
|
||||
else -> candidateDescriptor
|
||||
}
|
||||
}
|
||||
|
||||
private fun CallableDescriptor.substituteInferredVariablesAndApproximate(
|
||||
substitutor: NewTypeSubstitutor?,
|
||||
shouldApproximate: Boolean = true
|
||||
): CallableDescriptor {
|
||||
val sub = when (resolvedAtom) {
|
||||
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate!!.freshVariablesSubstitutor!!
|
||||
is ResolvedCallableReferenceCallAtom -> resolvedAtom.freshVariablesSubstitutor
|
||||
}
|
||||
|
||||
val inferredTypeVariablesSubstitutor = substitutor ?: FreshVariableNewTypeSubstitutor.Empty
|
||||
|
||||
return substitute(sub).substituteAndApproximateTypes(
|
||||
inferredTypeVariablesSubstitutor,
|
||||
typeApproximator = if (shouldApproximate) typeApproximator else null,
|
||||
positionDependentApproximation = true
|
||||
)
|
||||
}
|
||||
|
||||
override val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
|
||||
get() = TODO("Not yet implemented")
|
||||
|
||||
override val kotlinCall: KotlinCall
|
||||
get() = when (resolvedAtom) {
|
||||
is ResolvedCallableReferenceArgumentAtom ->
|
||||
(resolvedAtom.candidate?.kotlinCall as CallableReferenceKotlinCallArgument).call
|
||||
is ResolvedCallableReferenceCallAtom -> resolvedAtom.atom
|
||||
}
|
||||
override val languageVersionSettings: LanguageVersionSettings
|
||||
get() = TODO("Not yet implemented")
|
||||
|
||||
override fun containsOnlyOnlyInputTypesErrors(): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
override fun containsOnlyOnlyInputTypesErrors(): Boolean = false
|
||||
|
||||
override fun argumentToParameterMap(
|
||||
resultingDescriptor: CallableDescriptor,
|
||||
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>
|
||||
): Map<ValueArgument, ArgumentMatchImpl> {
|
||||
TODO("Not yet implemented")
|
||||
): Map<ValueArgument, ArgumentMatchImpl> = emptyMap()
|
||||
|
||||
init {
|
||||
setResultingSubstitutor(substitutor)
|
||||
}
|
||||
}
|
||||
+112
-191
@@ -7,67 +7,68 @@ package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.ValueArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.substitute
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.substituteAndApproximateTypes
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.util.isNotSimpleCall
|
||||
import org.jetbrains.kotlin.resolve.calls.util.toResolutionStatus
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
override val resolvedCallAtom: ResolvedCallAtom,
|
||||
substitutor: NewTypeSubstitutor?,
|
||||
private var diagnostics: Collection<KotlinCallDiagnostic>,
|
||||
private val typeApproximator: TypeApproximator,
|
||||
override val typeApproximator: TypeApproximator,
|
||||
override val languageVersionSettings: LanguageVersionSettings,
|
||||
) : NewAbstractResolvedCall<D>() {
|
||||
override val psiKotlinCall: PSIKotlinCall = resolvedCallAtom.atom.psiKotlinCall
|
||||
override val kotlinCall: KotlinCall = resolvedCallAtom.atom
|
||||
|
||||
override var isCompleted = false
|
||||
private set
|
||||
private lateinit var resultingDescriptor: D
|
||||
|
||||
private lateinit var typeArguments: List<UnwrappedType>
|
||||
|
||||
private var extensionReceiver = resolvedCallAtom.extensionReceiverArgument?.receiver?.receiverValue
|
||||
private var dispatchReceiver = resolvedCallAtom.dispatchReceiverArgument?.receiver?.receiverValue
|
||||
private var smartCastDispatchReceiverType: KotlinType? = null
|
||||
private var expectedTypeForSamConvertedArgumentMap: MutableMap<ValueArgument, UnwrappedType>? = null
|
||||
private var expectedTypeForSuspendConvertedArgumentMap: MutableMap<ValueArgument, UnwrappedType>? = null
|
||||
private var expectedTypeForUnitConvertedArgumentMap: MutableMap<ValueArgument, UnwrappedType>? = null
|
||||
private var argumentTypeForConstantConvertedMap: MutableMap<KtExpression, IntegerValueTypeConstant>? = null
|
||||
|
||||
|
||||
override val kotlinCall: KotlinCall get() = resolvedCallAtom.atom
|
||||
|
||||
override fun getStatus(): ResolutionStatus = getResultApplicability(diagnostics).toResolutionStatus()
|
||||
override val freshSubstitutor: FreshVariableNewTypeSubstitutor
|
||||
get() = resolvedCallAtom.freshVariablesSubstitutor
|
||||
|
||||
override val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
|
||||
get() = resolvedCallAtom.argumentMappingByOriginal
|
||||
|
||||
private lateinit var resultingDescriptor: D
|
||||
private lateinit var typeArguments: List<UnwrappedType>
|
||||
private var smartCastDispatchReceiverType: KotlinType? = null
|
||||
private var expectedTypeForSamConvertedArgumentMap: Map<ValueArgument, UnwrappedType>? = null
|
||||
private var expectedTypeForSuspendConvertedArgumentMap: Map<ValueArgument, UnwrappedType>? = null
|
||||
private var expectedTypeForUnitConvertedArgumentMap: Map<ValueArgument, UnwrappedType>? = null
|
||||
private var argumentTypeForConstantConvertedMap: Map<KtExpression, IntegerValueTypeConstant>? = null
|
||||
private var extensionReceiver = resolvedCallAtom.extensionReceiverArgument?.receiver?.receiverValue
|
||||
private var dispatchReceiver = resolvedCallAtom.dispatchReceiverArgument?.receiver?.receiverValue
|
||||
|
||||
override fun getExtensionReceiver(): ReceiverValue? = extensionReceiver
|
||||
override fun getDispatchReceiver(): ReceiverValue? = dispatchReceiver
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun getCandidateDescriptor(): D = resolvedCallAtom.candidateDescriptor as D
|
||||
override fun getResultingDescriptor(): D = resultingDescriptor
|
||||
override fun getExtensionReceiver(): ReceiverValue? = extensionReceiver
|
||||
override fun getDispatchReceiver(): ReceiverValue? = dispatchReceiver
|
||||
override fun getExplicitReceiverKind(): ExplicitReceiverKind = resolvedCallAtom.explicitReceiverKind
|
||||
|
||||
override fun updateDispatchReceiverType(newType: KotlinType) {
|
||||
if (dispatchReceiver?.type == newType) return
|
||||
dispatchReceiver = dispatchReceiver?.replaceType(newType)
|
||||
}
|
||||
|
||||
override fun updateExtensionReceiverType(newType: KotlinType) {
|
||||
if (extensionReceiver?.type == newType) return
|
||||
extensionReceiver = extensionReceiver?.replaceType(newType)
|
||||
}
|
||||
|
||||
override fun getStatus(): ResolutionStatus = getResultApplicability(diagnostics).toResolutionStatus()
|
||||
|
||||
override fun getTypeArguments(): Map<TypeParameterDescriptor, KotlinType> {
|
||||
val typeParameters = candidateDescriptor.typeParameters.takeIf { it.isNotEmpty() } ?: return emptyMap()
|
||||
return typeParameters.zip(typeArguments).toMap()
|
||||
@@ -78,56 +79,17 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
|
||||
override fun getSmartCastDispatchReceiverType(): KotlinType? = smartCastDispatchReceiverType
|
||||
|
||||
fun updateExtensionReceiverWithSmartCastIfNeeded(smartCastExtensionReceiverType: KotlinType) {
|
||||
if (extensionReceiver is ImplicitClassReceiver) {
|
||||
extensionReceiver = CastImplicitClassReceiver(
|
||||
(extensionReceiver as ImplicitClassReceiver).classDescriptor,
|
||||
smartCastExtensionReceiverType,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun setSmartCastDispatchReceiverType(smartCastDispatchReceiverType: KotlinType) {
|
||||
this.smartCastDispatchReceiverType = smartCastDispatchReceiverType
|
||||
}
|
||||
|
||||
fun updateDiagnostics(completedDiagnostics: Collection<KotlinCallDiagnostic>) {
|
||||
diagnostics = completedDiagnostics
|
||||
}
|
||||
|
||||
private fun updateExtensionReceiverType(newType: KotlinType) {
|
||||
if (extensionReceiver?.type == newType) return
|
||||
extensionReceiver = extensionReceiver?.replaceType(newType)
|
||||
}
|
||||
|
||||
private fun updateDispatchReceiverType(newType: KotlinType) {
|
||||
if (dispatchReceiver?.type == newType) return
|
||||
dispatchReceiver = dispatchReceiver?.replaceType(newType)
|
||||
}
|
||||
|
||||
override fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?) {
|
||||
//clear cached values
|
||||
argumentToParameterMap = null
|
||||
_valueArguments = null
|
||||
if (substitutor != null) {
|
||||
// todo: add asset that we do not complete call many times
|
||||
isCompleted = true
|
||||
updateArgumentsMapping(null)
|
||||
updateValueArguments(null)
|
||||
|
||||
dispatchReceiver?.type?.let {
|
||||
val newType = substitutor.safeSubstitute(it.unwrap())
|
||||
updateDispatchReceiverType(newType)
|
||||
}
|
||||
|
||||
extensionReceiver?.type?.let {
|
||||
val newType = substitutor.safeSubstitute(it.unwrap())
|
||||
updateExtensionReceiverType(newType)
|
||||
}
|
||||
}
|
||||
substituteReceivers(substitutor)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
resultingDescriptor = substitutedResultingDescriptor(substitutor) as D
|
||||
|
||||
typeArguments = resolvedCallAtom.freshVariablesSubstitutor.freshVariables.map {
|
||||
typeArguments = freshSubstitutor.freshVariables.map {
|
||||
val substituted = (substitutor ?: FreshVariableNewTypeSubstitutor.Empty).safeSubstitute(it.defaultType)
|
||||
typeApproximator
|
||||
.approximateToSuperType(substituted, TypeApproximatorConfiguration.IntegerLiteralsTypesApproximation)
|
||||
@@ -140,126 +102,6 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
calculateExpectedTypeForConstantConvertedArgumentMap()
|
||||
}
|
||||
|
||||
private fun KotlinType.withNullabilityFromExplicitTypeArgument(typeArgument: SimpleTypeArgument) =
|
||||
(if (typeArgument.type.isMarkedNullable) makeNullable() else makeNotNullable()).unwrap()
|
||||
|
||||
private fun getSubstitutorWithoutFlexibleTypes(
|
||||
currentSubstitutor: NewTypeSubstitutor?,
|
||||
explicitTypeArguments: List<SimpleTypeArgument>,
|
||||
): NewTypeSubstitutor? {
|
||||
if (currentSubstitutor !is NewTypeSubstitutorByConstructorMap || explicitTypeArguments.isEmpty()) return currentSubstitutor
|
||||
if (!currentSubstitutor.map.any { (_, value) -> value.isFlexible() }) return currentSubstitutor
|
||||
|
||||
val typeVariables = resolvedCallAtom.freshVariablesSubstitutor.freshVariables
|
||||
val newSubstitutorMap = currentSubstitutor.map.toMutableMap()
|
||||
|
||||
explicitTypeArguments.forEachIndexed { index, typeArgument ->
|
||||
val typeVariableConstructor = typeVariables.getOrNull(index)?.freshTypeConstructor ?: return@forEachIndexed
|
||||
|
||||
newSubstitutorMap[typeVariableConstructor] =
|
||||
newSubstitutorMap[typeVariableConstructor]?.withNullabilityFromExplicitTypeArgument(typeArgument)
|
||||
?: return@forEachIndexed
|
||||
}
|
||||
|
||||
return NewTypeSubstitutorByConstructorMap(newSubstitutorMap)
|
||||
}
|
||||
|
||||
private fun substitutedResultingDescriptor(substitutor: NewTypeSubstitutor?) =
|
||||
when (val candidateDescriptor = resolvedCallAtom.candidateDescriptor) {
|
||||
is ClassConstructorDescriptor, is SyntheticMemberDescriptor<*> -> {
|
||||
val explicitTypeArguments = resolvedCallAtom.atom.typeArguments.filterIsInstance<SimpleTypeArgument>()
|
||||
|
||||
candidateDescriptor.substituteInferredVariablesAndApproximate(
|
||||
getSubstitutorWithoutFlexibleTypes(substitutor, explicitTypeArguments),
|
||||
)
|
||||
}
|
||||
is FunctionDescriptor -> {
|
||||
candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor, candidateDescriptor.isNotSimpleCall())
|
||||
}
|
||||
is PropertyDescriptor -> {
|
||||
if (candidateDescriptor.isNotSimpleCall()) {
|
||||
candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor)
|
||||
} else {
|
||||
candidateDescriptor
|
||||
}
|
||||
}
|
||||
else -> candidateDescriptor
|
||||
}
|
||||
|
||||
private fun CallableDescriptor.substituteInferredVariablesAndApproximate(
|
||||
substitutor: NewTypeSubstitutor?,
|
||||
shouldApproximate: Boolean = true
|
||||
): CallableDescriptor {
|
||||
val inferredTypeVariablesSubstitutor = substitutor ?: FreshVariableNewTypeSubstitutor.Empty
|
||||
|
||||
// TODO: merge last two substitutors to avoid redundant descriptor substitutions
|
||||
return substitute(resolvedCallAtom.freshVariablesSubstitutor)
|
||||
.substitute(resolvedCallAtom.knownParametersSubstitutor)
|
||||
.substituteAndApproximateTypes(
|
||||
inferredTypeVariablesSubstitutor,
|
||||
typeApproximator.takeIf { shouldApproximate }
|
||||
)
|
||||
}
|
||||
|
||||
fun getArgumentTypeForConstantConvertedArgument(valueArgument: ValueArgument): IntegerValueTypeConstant? {
|
||||
val expression = valueArgument.getArgumentExpression() ?: return null
|
||||
return argumentTypeForConstantConvertedMap?.get(expression)
|
||||
}
|
||||
|
||||
fun getExpectedTypeForSamConvertedArgument(valueArgument: ValueArgument): UnwrappedType? =
|
||||
expectedTypeForSamConvertedArgumentMap?.get(valueArgument)
|
||||
|
||||
fun getExpectedTypeForSuspendConvertedArgument(valueArgument: ValueArgument): UnwrappedType? =
|
||||
expectedTypeForSuspendConvertedArgumentMap?.get(valueArgument)
|
||||
|
||||
fun getExpectedTypeForUnitConvertedArgument(valueArgument: ValueArgument): UnwrappedType? =
|
||||
expectedTypeForUnitConvertedArgumentMap?.get(valueArgument)
|
||||
|
||||
private fun calculateExpectedTypeForConstantConvertedArgumentMap() {
|
||||
if (resolvedCallAtom.argumentsWithConstantConversion.isEmpty()) return
|
||||
|
||||
argumentTypeForConstantConvertedMap = hashMapOf()
|
||||
for ((argument, convertedConstant) in resolvedCallAtom.argumentsWithConstantConversion) {
|
||||
val expression = argument.psiExpression ?: continue
|
||||
argumentTypeForConstantConvertedMap!![expression] = convertedConstant
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateExpectedTypeForSamConvertedArgumentMap(substitutor: NewTypeSubstitutor?) {
|
||||
if (resolvedCallAtom.argumentsWithConversion.isEmpty()) return
|
||||
|
||||
expectedTypeForSamConvertedArgumentMap = hashMapOf()
|
||||
for ((argument, description) in resolvedCallAtom.argumentsWithConversion) {
|
||||
val typeWithFreshVariables =
|
||||
resolvedCallAtom.freshVariablesSubstitutor.safeSubstitute(description.convertedTypeByCandidateParameter)
|
||||
val expectedType = substitutor?.safeSubstitute(typeWithFreshVariables) ?: typeWithFreshVariables
|
||||
expectedTypeForSamConvertedArgumentMap!![argument.psiCallArgument.valueArgument] = expectedType
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateExpectedTypeForSuspendConvertedArgumentMap(substitutor: NewTypeSubstitutor?) {
|
||||
if (resolvedCallAtom.argumentsWithSuspendConversion.isEmpty()) return
|
||||
|
||||
expectedTypeForSuspendConvertedArgumentMap = hashMapOf()
|
||||
for ((argument, convertedType) in resolvedCallAtom.argumentsWithSuspendConversion) {
|
||||
val typeWithFreshVariables = resolvedCallAtom.freshVariablesSubstitutor.safeSubstitute(convertedType)
|
||||
val expectedType = substitutor?.safeSubstitute(typeWithFreshVariables) ?: typeWithFreshVariables
|
||||
expectedTypeForSuspendConvertedArgumentMap!![argument.psiCallArgument.valueArgument] = expectedType
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateExpectedTypeForUnitConvertedArgumentMap(substitutor: NewTypeSubstitutor?) {
|
||||
if (resolvedCallAtom.argumentsWithUnitConversion.isEmpty()) return
|
||||
|
||||
expectedTypeForUnitConvertedArgumentMap = hashMapOf()
|
||||
for ((argument, convertedType) in resolvedCallAtom.argumentsWithUnitConversion) {
|
||||
val typeWithFreshVariables = resolvedCallAtom.freshVariablesSubstitutor.safeSubstitute(convertedType)
|
||||
val expectedType = substitutor?.safeSubstitute(typeWithFreshVariables) ?: typeWithFreshVariables
|
||||
expectedTypeForUnitConvertedArgumentMap!![argument.psiCallArgument.valueArgument] = expectedType
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun argumentToParameterMap(
|
||||
resultingDescriptor: CallableDescriptor,
|
||||
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>,
|
||||
@@ -279,6 +121,85 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
}
|
||||
}
|
||||
|
||||
fun updateExtensionReceiverWithSmartCastIfNeeded(smartCastExtensionReceiverType: KotlinType) {
|
||||
if (extensionReceiver is ImplicitClassReceiver) {
|
||||
extensionReceiver = CastImplicitClassReceiver(
|
||||
(extensionReceiver as ImplicitClassReceiver).classDescriptor,
|
||||
smartCastExtensionReceiverType,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun setSmartCastDispatchReceiverType(smartCastDispatchReceiverType: KotlinType) {
|
||||
this.smartCastDispatchReceiverType = smartCastDispatchReceiverType
|
||||
}
|
||||
|
||||
fun updateDiagnostics(completedDiagnostics: Collection<KotlinCallDiagnostic>) {
|
||||
diagnostics = completedDiagnostics
|
||||
}
|
||||
|
||||
fun getArgumentTypeForConstantConvertedArgument(valueArgument: ValueArgument): IntegerValueTypeConstant? {
|
||||
val expression = valueArgument.getArgumentExpression() ?: return null
|
||||
return argumentTypeForConstantConvertedMap?.get(expression)
|
||||
}
|
||||
|
||||
fun getExpectedTypeForSamConvertedArgument(valueArgument: ValueArgument): UnwrappedType? =
|
||||
expectedTypeForSamConvertedArgumentMap?.get(valueArgument)
|
||||
|
||||
fun getExpectedTypeForSuspendConvertedArgument(valueArgument: ValueArgument): UnwrappedType? =
|
||||
expectedTypeForSuspendConvertedArgumentMap?.get(valueArgument)
|
||||
|
||||
fun getExpectedTypeForUnitConvertedArgument(valueArgument: ValueArgument): UnwrappedType? =
|
||||
expectedTypeForUnitConvertedArgumentMap?.get(valueArgument)
|
||||
|
||||
private fun calculateExpectedTypeForConvertedArguments(
|
||||
arguments: Map<KotlinCallArgument, UnwrappedType>,
|
||||
substitutor: NewTypeSubstitutor?,
|
||||
): Map<ValueArgument, UnwrappedType>? {
|
||||
if (arguments.isEmpty()) return null
|
||||
|
||||
val expectedTypeForConvertedArguments = hashMapOf<ValueArgument, UnwrappedType>()
|
||||
for ((argument, convertedType) in arguments) {
|
||||
val typeWithFreshVariables = resolvedCallAtom.freshVariablesSubstitutor.safeSubstitute(convertedType)
|
||||
val expectedType = substitutor?.safeSubstitute(typeWithFreshVariables) ?: typeWithFreshVariables
|
||||
expectedTypeForConvertedArguments[argument.psiCallArgument.valueArgument] = expectedType
|
||||
}
|
||||
|
||||
return expectedTypeForConvertedArguments
|
||||
}
|
||||
|
||||
private fun calculateExpectedTypeForConstantConvertedArgumentMap() {
|
||||
if (resolvedCallAtom.argumentsWithConstantConversion.isEmpty()) return
|
||||
|
||||
val expectedTypeForConvertedArguments = hashMapOf<KtExpression, IntegerValueTypeConstant>()
|
||||
|
||||
for ((argument, convertedConstant) in resolvedCallAtom.argumentsWithConstantConversion) {
|
||||
val expression = argument.psiExpression ?: continue
|
||||
expectedTypeForConvertedArguments[expression] = convertedConstant
|
||||
}
|
||||
|
||||
argumentTypeForConstantConvertedMap = expectedTypeForConvertedArguments
|
||||
}
|
||||
|
||||
private fun calculateExpectedTypeForSamConvertedArgumentMap(substitutor: NewTypeSubstitutor?) {
|
||||
expectedTypeForSamConvertedArgumentMap = calculateExpectedTypeForConvertedArguments(
|
||||
resolvedCallAtom.argumentsWithConversion.mapValues { it.value.convertedTypeByCandidateParameter },
|
||||
substitutor
|
||||
)
|
||||
}
|
||||
|
||||
private fun calculateExpectedTypeForSuspendConvertedArgumentMap(substitutor: NewTypeSubstitutor?) {
|
||||
expectedTypeForSuspendConvertedArgumentMap = calculateExpectedTypeForConvertedArguments(
|
||||
resolvedCallAtom.argumentsWithSuspendConversion, substitutor
|
||||
)
|
||||
}
|
||||
|
||||
private fun calculateExpectedTypeForUnitConvertedArgumentMap(substitutor: NewTypeSubstitutor?) {
|
||||
expectedTypeForUnitConvertedArgumentMap = calculateExpectedTypeForConvertedArguments(
|
||||
resolvedCallAtom.argumentsWithUnitConversion, substitutor
|
||||
)
|
||||
}
|
||||
|
||||
private fun collectErrorPositions(): Map<ValueArgument, List<KotlinCallDiagnostic>> {
|
||||
val result = mutableListOf<Pair<ValueArgument, KotlinCallDiagnostic>>()
|
||||
|
||||
|
||||
+24
-11
@@ -5,21 +5,31 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallAtom
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeApproximator
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
class NewVariableAsFunctionResolvedCallImpl(
|
||||
override val variableCall: NewAbstractResolvedCall<VariableDescriptor>,
|
||||
override val functionCall: NewAbstractResolvedCall<FunctionDescriptor>,
|
||||
) : VariableAsFunctionResolvedCall, NewAbstractResolvedCall<FunctionDescriptor>() {
|
||||
override val resolvedCallAtom = functionCall.resolvedCallAtom
|
||||
val baseCall: PSIKotlinCallImpl = functionCall.psiKotlinCall.cast<PSIKotlinCallForInvoke>().baseCall
|
||||
|
||||
override val resolvedCallAtom: ResolvedCallAtom? = functionCall.resolvedCallAtom
|
||||
override val psiKotlinCall: PSIKotlinCall = functionCall.psiKotlinCall
|
||||
val baseCall get() = functionCall.psiKotlinCall.cast<PSIKotlinCallForInvoke>().baseCall
|
||||
override val typeApproximator: TypeApproximator = functionCall.typeApproximator
|
||||
override val freshSubstitutor: FreshVariableNewTypeSubstitutor? = functionCall.freshSubstitutor
|
||||
override val argumentMappingByOriginal = functionCall.argumentMappingByOriginal
|
||||
override val kotlinCall = functionCall.kotlinCall
|
||||
override val languageVersionSettings = functionCall.languageVersionSettings
|
||||
|
||||
override fun getStatus() = functionCall.status
|
||||
override fun getCandidateDescriptor() = functionCall.candidateDescriptor
|
||||
override fun getResultingDescriptor() = functionCall.resultingDescriptor
|
||||
@@ -28,13 +38,16 @@ class NewVariableAsFunctionResolvedCallImpl(
|
||||
override fun getExplicitReceiverKind() = functionCall.explicitReceiverKind
|
||||
override fun getTypeArguments() = functionCall.typeArguments
|
||||
override fun getSmartCastDispatchReceiverType() = functionCall.smartCastDispatchReceiverType
|
||||
override val argumentMappingByOriginal = functionCall.argumentMappingByOriginal
|
||||
override val kotlinCall = functionCall.kotlinCall
|
||||
override val languageVersionSettings = functionCall.languageVersionSettings
|
||||
override fun containsOnlyOnlyInputTypesErrors() = functionCall.containsOnlyOnlyInputTypesErrors()
|
||||
override fun updateDispatchReceiverType(newType: KotlinType) = functionCall.updateDispatchReceiverType(newType)
|
||||
override fun updateExtensionReceiverType(newType: KotlinType) = functionCall.updateExtensionReceiverType(newType)
|
||||
override fun argumentToParameterMap(
|
||||
resultingDescriptor: CallableDescriptor,
|
||||
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>
|
||||
) = functionCall.argumentToParameterMap(resultingDescriptor, valueArguments)
|
||||
override val isCompleted: Boolean = functionCall.isCompleted
|
||||
}
|
||||
|
||||
override fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?) {
|
||||
functionCall.setResultingSubstitutor(substitutor)
|
||||
variableCall.setResultingSubstitutor(substitutor)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,8 @@ class PSICallResolver(
|
||||
val defaultResolutionKinds = setOf(
|
||||
NewResolutionOldInference.ResolutionKind.Function,
|
||||
NewResolutionOldInference.ResolutionKind.Variable,
|
||||
NewResolutionOldInference.ResolutionKind.Invoke
|
||||
NewResolutionOldInference.ResolutionKind.Invoke,
|
||||
NewResolutionOldInference.ResolutionKind.CallableReference
|
||||
)
|
||||
|
||||
fun <D : CallableDescriptor> runResolutionAndInference(
|
||||
@@ -98,10 +99,9 @@ class PSICallResolver(
|
||||
val resolutionCallbacks = createResolutionCallbacks(context)
|
||||
|
||||
val expectedType = calculateExpectedType(context)
|
||||
var result =
|
||||
kotlinCallResolver.resolveCall(scopeTower, resolutionCallbacks, kotlinCall, expectedType, context.collectAllCandidates) {
|
||||
FactoryProviderForInvoke(context, scopeTower, kotlinCall)
|
||||
}
|
||||
var result = kotlinCallResolver.resolveAndCompleteCall(
|
||||
scopeTower, resolutionCallbacks, kotlinCall, expectedType, context.collectAllCandidates
|
||||
)
|
||||
|
||||
val shouldUseOperatorRem = languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)
|
||||
if (isBinaryRemOperator && shouldUseOperatorRem && (result.isEmpty() || result.areAllInapplicable())) {
|
||||
@@ -141,7 +141,7 @@ class PSICallResolver(
|
||||
)
|
||||
}
|
||||
|
||||
val result = kotlinCallResolver.resolveGivenCandidates(
|
||||
val result = kotlinCallResolver.resolveAndCompleteGivenCandidates(
|
||||
scopeTower, resolutionCallbacks, kotlinCall, calculateExpectedType(context), givenCandidates, context.collectAllCandidates
|
||||
)
|
||||
val overloadResolutionResults = convertToOverloadResolutionResults<D>(context, result, tracingStrategy)
|
||||
@@ -169,11 +169,9 @@ class PSICallResolver(
|
||||
val callWithDeprecatedName = toKotlinCall(
|
||||
context, kotlinCallKind, context.call, deprecatedName, tracingStrategy, isSpecialFunction = false
|
||||
)
|
||||
return kotlinCallResolver.resolveCall(
|
||||
return kotlinCallResolver.resolveAndCompleteCall(
|
||||
scopeTower, resolutionCallbacks, callWithDeprecatedName, expectedType, context.collectAllCandidates
|
||||
) {
|
||||
FactoryProviderForInvoke(context, scopeTower, callWithDeprecatedName)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun refineNameForRemOperator(isBinaryRemOperator: Boolean, name: Name): Name {
|
||||
@@ -190,17 +188,14 @@ class PSICallResolver(
|
||||
argumentTypeResolver, languageVersionSettings, kotlinToResolvedCallTransformer,
|
||||
dataFlowValueFactory, inferenceSession, constantExpressionEvaluator, typeResolver,
|
||||
this, postponedArgumentsAnalyzer, kotlinConstraintSystemCompleter, callComponents,
|
||||
doubleColonExpressionResolver, deprecationResolver, moduleDescriptor, context, missingSupertypesResolver
|
||||
doubleColonExpressionResolver, deprecationResolver, moduleDescriptor, context, missingSupertypesResolver, kotlinCallResolver
|
||||
)
|
||||
|
||||
private fun calculateExpectedType(context: BasicCallResolutionContext): UnwrappedType? {
|
||||
val expectedType = context.expectedType.unwrap()
|
||||
|
||||
return if (context.contextDependency == ContextDependency.DEPENDENT) {
|
||||
assert(TypeUtils.noExpectedType(expectedType)) {
|
||||
"Should have no expected type, got: $expectedType"
|
||||
}
|
||||
null
|
||||
if (TypeUtils.noExpectedType(expectedType)) null else expectedType
|
||||
} else {
|
||||
if (expectedType.isError) TypeUtils.NO_EXPECTED_TYPE else expectedType
|
||||
}
|
||||
@@ -282,7 +277,7 @@ class PSICallResolver(
|
||||
): ManyCandidates<D> {
|
||||
val resolvedCalls = diagnostic.candidates.map {
|
||||
kotlinToResolvedCallTransformer.onlyTransform<D>(
|
||||
it.resolvedCall, it.diagnosticsFromResolutionParts + it.getSystem().errors.asDiagnostics()
|
||||
it.resolvedCall, it.diagnostics + it.getSystem().errors.asDiagnostics()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -454,7 +449,7 @@ class PSICallResolver(
|
||||
}
|
||||
}
|
||||
|
||||
private inner class FactoryProviderForInvoke(
|
||||
inner class FactoryProviderForInvoke(
|
||||
val context: BasicCallResolutionContext,
|
||||
val scopeTower: ImplicitScopeTower,
|
||||
val kotlinCall: PSIKotlinCallImpl
|
||||
@@ -472,9 +467,7 @@ class PSICallResolver(
|
||||
override fun factoryForVariable(stripExplicitReceiver: Boolean): CandidateFactory<ResolutionCandidate> {
|
||||
val explicitReceiver = if (stripExplicitReceiver) null else kotlinCall.explicitReceiver
|
||||
val variableCall = PSIKotlinCallForVariable(kotlinCall, explicitReceiver, kotlinCall.name)
|
||||
return SimpleCandidateFactory(
|
||||
callComponents, scopeTower, variableCall, createResolutionCallbacks(context), callableReferenceResolver
|
||||
)
|
||||
return SimpleCandidateFactory(callComponents, scopeTower, variableCall, createResolutionCallbacks(context))
|
||||
}
|
||||
|
||||
override fun factoryForInvoke(variable: ResolutionCandidate, useExplicitReceiver: Boolean):
|
||||
@@ -554,7 +547,7 @@ class PSICallResolver(
|
||||
is NewResolutionOldInference.ResolutionKind.Function -> KotlinCallKind.FUNCTION
|
||||
is NewResolutionOldInference.ResolutionKind.Variable -> KotlinCallKind.VARIABLE
|
||||
is NewResolutionOldInference.ResolutionKind.Invoke -> KotlinCallKind.INVOKE
|
||||
is NewResolutionOldInference.ResolutionKind.CallableReference -> KotlinCallKind.UNSUPPORTED
|
||||
is NewResolutionOldInference.ResolutionKind.CallableReference -> KotlinCallKind.CALLABLE_REFERENCE
|
||||
is NewResolutionOldInference.ResolutionKind.GivenCandidates -> KotlinCallKind.UNSUPPORTED
|
||||
}
|
||||
|
||||
@@ -822,52 +815,22 @@ class PSICallResolver(
|
||||
startDataFlowInfo: DataFlowInfo,
|
||||
valueArgument: ValueArgument,
|
||||
argumentName: Name?,
|
||||
outerCallContext: BasicCallResolutionContext
|
||||
outerCallContext: BasicCallResolutionContext,
|
||||
tracingStrategy: TracingStrategy
|
||||
): CallableReferenceKotlinCallArgumentImpl {
|
||||
checkNoSpread(outerCallContext, valueArgument)
|
||||
|
||||
val expressionTypingContext = ExpressionTypingContext.newContext(context)
|
||||
val lhsResult = if (ktExpression.isEmptyLHS) null else doubleColonExpressionResolver.resolveDoubleColonLHS(
|
||||
ktExpression,
|
||||
expressionTypingContext
|
||||
)
|
||||
val newDataFlowInfo = (lhsResult as? DoubleColonLHS.Expression)?.dataFlowInfo ?: startDataFlowInfo
|
||||
val name = ktExpression.callableReference.getReferencedNameAsName()
|
||||
|
||||
val lhsNewResult = when (lhsResult) {
|
||||
null -> LHSResult.Empty
|
||||
is DoubleColonLHS.Expression -> {
|
||||
if (lhsResult.isObjectQualifier) {
|
||||
val classifier = lhsResult.type.constructor.declarationDescriptor
|
||||
val calleeExpression = ktExpression.receiverExpression?.getCalleeExpressionIfAny()
|
||||
if (calleeExpression is KtSimpleNameExpression && classifier is ClassDescriptor) {
|
||||
LHSResult.Object(ClassQualifier(calleeExpression, classifier))
|
||||
} else {
|
||||
LHSResult.Error
|
||||
}
|
||||
} else {
|
||||
val fakeArgument = FakeValueArgumentForLeftCallableReference(ktExpression)
|
||||
|
||||
val kotlinCallArgument = createSimplePSICallArgument(context, fakeArgument, lhsResult.typeInfo)
|
||||
kotlinCallArgument?.let { LHSResult.Expression(it as SimpleKotlinCallArgument) } ?: LHSResult.Error
|
||||
}
|
||||
}
|
||||
is DoubleColonLHS.Type -> {
|
||||
val qualifiedExpression = ktExpression.receiverExpression!!
|
||||
val qualifier = expressionTypingContext.trace.get(BindingContext.QUALIFIER, qualifiedExpression)
|
||||
val classifier = lhsResult.type.constructor.declarationDescriptor
|
||||
if (classifier !is ClassDescriptor) {
|
||||
expressionTypingContext.trace.report(Errors.CALLABLE_REFERENCE_LHS_NOT_A_CLASS.on(ktExpression))
|
||||
LHSResult.Error
|
||||
} else {
|
||||
LHSResult.Type(qualifier, lhsResult.type.unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
val (doubleColonLhs, lhsResult) = getLhsResult(context, ktExpression)
|
||||
val newDataFlowInfo = (doubleColonLhs as? DoubleColonLHS.Expression)?.dataFlowInfo ?: startDataFlowInfo
|
||||
val rhsExpression = ktExpression.callableReference
|
||||
val rhsName = rhsExpression.getReferencedNameAsName()
|
||||
val call = outerCallContext.trace[BindingContext.CALL, rhsExpression]
|
||||
?: CallMaker.makeCall(rhsExpression, null, null, rhsExpression, emptyList())
|
||||
val kotlinCall = toKotlinCall(context, KotlinCallKind.CALLABLE_REFERENCE, call, rhsName, tracingStrategy, isSpecialFunction = false)
|
||||
|
||||
return CallableReferenceKotlinCallArgumentImpl(
|
||||
ASTScopeTower(context, ktExpression.callableReference), valueArgument, startDataFlowInfo, newDataFlowInfo,
|
||||
ktExpression, argumentName, lhsNewResult, name
|
||||
ASTScopeTower(context, rhsExpression), valueArgument, startDataFlowInfo,
|
||||
newDataFlowInfo, ktExpression, argumentName, lhsResult, rhsName, kotlinCall
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+108
-69
@@ -25,6 +25,8 @@ import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReference
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ComposedSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.EmptySubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
@@ -33,6 +35,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategyImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||
import org.jetbrains.kotlin.resolve.calls.util.extractCallableReferenceExpression
|
||||
import org.jetbrains.kotlin.resolve.checkers.MissingDependencySupertypeChecker
|
||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
@@ -68,7 +71,7 @@ class ResolvedAtomCompleter(
|
||||
val dispatchReceiver: ReceiverValue?,
|
||||
val extensionReceiver: ReceiverValue?,
|
||||
val explicitReceiver: ReceiverValue?,
|
||||
val substitutor: TypeSubstitutor,
|
||||
val substitutor: NewTypeSubstitutor,
|
||||
val resultType: KotlinType
|
||||
)
|
||||
|
||||
@@ -109,18 +112,32 @@ class ResolvedAtomCompleter(
|
||||
complete(resolvedAtom)
|
||||
}
|
||||
|
||||
fun completeSubCallArgument(resolvedSubCallArgument: ResolvedSubCallArgument) {
|
||||
val contextWithoutExpectedType = topLevelCallContext.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)
|
||||
kotlinToResolvedCallTransformer.updateRecordedType(
|
||||
resolvedSubCallArgument.atom.psiExpression ?: return,
|
||||
parameter = null,
|
||||
context = contextWithoutExpectedType,
|
||||
reportErrorForTypeMismatch = true,
|
||||
convertedArgumentType = null
|
||||
)
|
||||
private fun completeSubCallArgument(resolvedSubCallArgument: ResolvedSubCallArgument) {
|
||||
val deparenthesizedExpression =
|
||||
KtPsiUtil.getLastElementDeparenthesized(resolvedSubCallArgument.atom.psiExpression, topLevelCallContext.statementFilter)
|
||||
|
||||
if (deparenthesizedExpression is KtCallableReferenceExpression) {
|
||||
val callableReferenceResolvedCall = kotlinToResolvedCallTransformer.getResolvedCallForArgumentExpression(
|
||||
deparenthesizedExpression.callableReference, topLevelCallContext
|
||||
) as? NewCallableReferenceResolvedCall<*>
|
||||
if (callableReferenceResolvedCall != null) {
|
||||
completeCallableReferenceCall(callableReferenceResolvedCall)
|
||||
}
|
||||
} else {
|
||||
kotlinToResolvedCallTransformer.updateRecordedType(
|
||||
resolvedSubCallArgument.atom.psiExpression ?: return,
|
||||
parameter = null,
|
||||
context = topLevelCallContext.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE),
|
||||
reportErrorForTypeMismatch = true,
|
||||
convertedArgumentType = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun completeResolvedCall(resolvedCallAtom: ResolvedCallAtom, diagnostics: Collection<KotlinCallDiagnostic>): ResolvedCall<*>? {
|
||||
fun completeResolvedCall(
|
||||
resolvedCallAtom: ResolvedCallAtom,
|
||||
diagnostics: Collection<KotlinCallDiagnostic>
|
||||
): NewAbstractResolvedCall<*>? {
|
||||
val diagnosticsFromPartiallyResolvedCall = extractDiagnosticsFromPartiallyResolvedCall(resolvedCallAtom)
|
||||
|
||||
clearPartiallyResolvedCall(resolvedCallAtom)
|
||||
@@ -137,9 +154,11 @@ class ResolvedAtomCompleter(
|
||||
allDiagnostics
|
||||
)
|
||||
|
||||
val lastCall = if (resolvedCall is VariableAsFunctionResolvedCall) resolvedCall.functionCall else resolvedCall
|
||||
val lastCall = if (resolvedCall is VariableAsFunctionResolvedCall) {
|
||||
resolvedCall.functionCall as NewAbstractResolvedCall<*>
|
||||
} else resolvedCall
|
||||
if (ErrorUtils.isError(resolvedCall.candidateDescriptor)) {
|
||||
kotlinToResolvedCallTransformer.runArgumentsChecks(topLevelCallContext, lastCall as NewResolvedCallImpl<*>)
|
||||
kotlinToResolvedCallTransformer.runArgumentsChecks(topLevelCallContext, lastCall)
|
||||
checkMissingReceiverSupertypes(resolvedCall, missingSupertypesResolver, topLevelTrace)
|
||||
return resolvedCall
|
||||
}
|
||||
@@ -173,7 +192,7 @@ class ResolvedAtomCompleter(
|
||||
|
||||
kotlinToResolvedCallTransformer.bind(topLevelTrace, resolvedCall)
|
||||
|
||||
kotlinToResolvedCallTransformer.runArgumentsChecks(topLevelCallContext, lastCall as NewResolvedCallImpl<*>)
|
||||
kotlinToResolvedCallTransformer.runArgumentsChecks(topLevelCallContext, lastCall)
|
||||
kotlinToResolvedCallTransformer.runCallCheckers(resolvedCall, callCheckerContext)
|
||||
kotlinToResolvedCallTransformer.runAdditionalReceiversCheckers(resolvedCall, topLevelCallContext)
|
||||
|
||||
@@ -340,25 +359,20 @@ class ResolvedAtomCompleter(
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateCallableReferenceResultType(
|
||||
callableCandidate: CallableReferenceCandidate,
|
||||
callableReferenceExpression: KtCallableReferenceExpression
|
||||
): CallableReferenceResultTypeInfo {
|
||||
val resultTypeParameters =
|
||||
callableCandidate.freshSubstitutor!!.freshVariables.map { resultSubstitutor.safeSubstitute(it.defaultType) }
|
||||
|
||||
private fun updateCallableReferenceResultType(callableCandidate: CallableReferenceResolutionCandidate): CallableReferenceResultTypeInfo? {
|
||||
val callableReferenceExpression =
|
||||
callableCandidate.resolvedCall.atom.psiKotlinCall.psiCall.callElement.parent as? KtCallableReferenceExpression ?: return null
|
||||
val freshSubstitutor = callableCandidate.freshVariablesSubstitutor ?: return null
|
||||
val resultTypeParameters = freshSubstitutor.freshVariables.map { resultSubstitutor.safeSubstitute(it.defaultType) }
|
||||
val typeParametersSubstitutor = NewTypeSubstitutorByConstructorMap(
|
||||
(callableCandidate.candidate.typeParameters.map { it.typeConstructor } zip resultTypeParameters).toMap()
|
||||
callableCandidate.candidate.typeParameters.map { it.typeConstructor }.zip(resultTypeParameters).toMap()
|
||||
)
|
||||
|
||||
val resultSubstitutor = if (callableCandidate.candidate.isSupportedForCallableReference()) {
|
||||
val firstSubstitution = typeParametersSubstitutor.toOldSubstitution()
|
||||
val secondSubstitution = resultSubstitutor.toOldSubstitution()
|
||||
TypeSubstitutor.createChainedSubstitutor(firstSubstitution, secondSubstitution)
|
||||
} else TypeSubstitutor.EMPTY
|
||||
ComposedSubstitutor(typeParametersSubstitutor, resultSubstitutor)
|
||||
} else EmptySubstitutor
|
||||
|
||||
// write down type for callable reference expression
|
||||
val resultType = resultSubstitutor.safeSubstitute(callableCandidate.reflectionCandidateType, Variance.INVARIANT)
|
||||
val resultType = resultSubstitutor.safeSubstitute(callableCandidate.reflectionCandidateType)
|
||||
|
||||
argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(
|
||||
topLevelTrace, expressionTypingServices.statementFilter, resultType, callableReferenceExpression
|
||||
@@ -415,7 +429,7 @@ class ResolvedAtomCompleter(
|
||||
dispatchReceiver,
|
||||
extensionReceiver,
|
||||
explicitCallableReceiver,
|
||||
TypeSubstitutor.EMPTY,
|
||||
EmptySubstitutor,
|
||||
callableCandidate.reflectionCandidateType.replaceFunctionTypeArgumentsByDescriptor(recordedDescriptor)
|
||||
)
|
||||
}
|
||||
@@ -437,79 +451,106 @@ class ResolvedAtomCompleter(
|
||||
else -> this
|
||||
}
|
||||
|
||||
private fun completeCallableReference(resolvedAtom: ResolvedCallableReferenceAtom) {
|
||||
fun completeCallableReferenceCall(resolvedCall: NewCallableReferenceResolvedCall<*>): KotlinType? {
|
||||
val candidate = resolvedCall.resolvedCallAtom?.candidate ?: return null
|
||||
return completeCallableReference(candidate, resolvedCall.resultingDescriptor, resolvedCall)
|
||||
}
|
||||
|
||||
fun completeCallableReferenceArgument(resolvedAtom: ResolvedCallableReferenceArgumentAtom): KotlinType? {
|
||||
if (resolvedAtom.completed) return null
|
||||
|
||||
val psiCallArgument = resolvedAtom.atom.psiCallArgument as CallableReferenceKotlinCallArgumentImpl
|
||||
val callableReferenceExpression = psiCallArgument.ktCallableReferenceExpression
|
||||
val callableCandidate = resolvedAtom.candidate
|
||||
if (callableCandidate == null || resolvedAtom.completed) {
|
||||
// todo report meanfull diagnostic here
|
||||
return
|
||||
}
|
||||
val recorderDescriptor = when (callableCandidate.candidate) {
|
||||
is FunctionDescriptor -> topLevelCallContext.trace.get(BindingContext.FUNCTION, callableReferenceExpression)
|
||||
is PropertyDescriptor -> topLevelCallContext.trace.get(BindingContext.VARIABLE, callableReferenceExpression)
|
||||
val callableReferenceCallCandidate = resolvedAtom.candidate ?: return null
|
||||
val descriptor = when (callableReferenceCallCandidate.candidate) {
|
||||
is FunctionDescriptor -> topLevelCallContext.trace.get(BindingContext.FUNCTION, psiCallArgument.ktCallableReferenceExpression)
|
||||
is PropertyDescriptor -> topLevelCallContext.trace.get(BindingContext.VARIABLE, psiCallArgument.ktCallableReferenceExpression)
|
||||
else -> null
|
||||
}
|
||||
val dataFlowInfo = resolvedAtom.atom.psiCallArgument.dataFlowInfoAfterThisArgument
|
||||
val resolvedCall = NewCallableReferenceResolvedCall<CallableDescriptor>(
|
||||
resolvedAtom,
|
||||
typeApproximator,
|
||||
expressionTypingServices.languageVersionSettings
|
||||
)
|
||||
|
||||
return completeCallableReference(callableReferenceCallCandidate, descriptor, resolvedCall, dataFlowInfo)
|
||||
.also { resolvedAtom.completed = true }
|
||||
}
|
||||
|
||||
private fun completeCallableReference(
|
||||
callableCandidate: CallableReferenceResolutionCandidate,
|
||||
recordedDescriptor: CallableDescriptor?,
|
||||
resolvedCall: NewAbstractResolvedCall<*>,
|
||||
additionalDataFlowInfo: DataFlowInfo? = null,
|
||||
): KotlinType? {
|
||||
val rawExtensionReceiver = callableCandidate.extensionReceiver
|
||||
|
||||
val unrestrictedBuilderInferenceSupported =
|
||||
topLevelCallContext.languageVersionSettings.supportsFeature(LanguageFeature.UnrestrictedBuilderInference)
|
||||
val callableReferenceExpression =
|
||||
callableCandidate.resolvedCall.atom.psiKotlinCall.extractCallableReferenceExpression() ?: return null
|
||||
|
||||
if (rawExtensionReceiver != null && !unrestrictedBuilderInferenceSupported && rawExtensionReceiver.receiver.receiverValue.type.contains { it is StubTypeForBuilderInference }) {
|
||||
topLevelTrace.reportDiagnosticOnce(Errors.TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE.on(callableReferenceExpression))
|
||||
return
|
||||
return null
|
||||
}
|
||||
|
||||
// For some callable references we can already have recorder descriptor (see `DoubleColonExpressionResolver.getCallableReferenceType`)
|
||||
val resultTypeInfo = if (recorderDescriptor != null) {
|
||||
extractCallableReferenceResultTypeInfoFromDescriptor(callableCandidate, recorderDescriptor)
|
||||
val resultTypeInfo = if (recordedDescriptor != null) {
|
||||
extractCallableReferenceResultTypeInfoFromDescriptor(callableCandidate, recordedDescriptor)
|
||||
} else {
|
||||
updateCallableReferenceResultType(callableCandidate, psiCallArgument.ktCallableReferenceExpression)
|
||||
updateCallableReferenceResultType(callableCandidate)
|
||||
}
|
||||
|
||||
val reference = callableReferenceExpression.callableReference
|
||||
val psiCall = CallMaker.makeCall(reference, resultTypeInfo.explicitReceiver, null, reference, emptyList())
|
||||
if (resultTypeInfo == null) return null
|
||||
|
||||
val tracing = TracingStrategyImpl.create(reference, psiCall)
|
||||
val temporaryTrace = TemporaryBindingTrace.create(topLevelTrace, "callable reference fake call")
|
||||
|
||||
val resolvedCall = ResolvedCallImpl(
|
||||
psiCall, callableCandidate.candidate, resultTypeInfo.dispatchReceiver,
|
||||
resultTypeInfo.extensionReceiver, callableCandidate.explicitReceiverKind,
|
||||
null, temporaryTrace, tracing, MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY)
|
||||
)
|
||||
|
||||
resolvedCall.setSubstitutor(resultTypeInfo.substitutor)
|
||||
resolvedCall.apply {
|
||||
if (resultTypeInfo.dispatchReceiver != null) {
|
||||
updateDispatchReceiverType(resultTypeInfo.dispatchReceiver.type)
|
||||
}
|
||||
if (resultTypeInfo.extensionReceiver != null) {
|
||||
updateExtensionReceiverType(resultTypeInfo.extensionReceiver.type)
|
||||
}
|
||||
setResultingSubstitutor(resultTypeInfo.substitutor)
|
||||
}
|
||||
|
||||
recordArgumentAdaptationForCallableReference(resolvedCall, callableCandidate.callableReferenceAdaptation)
|
||||
|
||||
val psiCall = CallMaker.makeCall(
|
||||
callableReferenceExpression.callableReference,
|
||||
resultTypeInfo.explicitReceiver,
|
||||
null,
|
||||
callableReferenceExpression.callableReference,
|
||||
emptyList()
|
||||
)
|
||||
val tracing = TracingStrategyImpl.create(callableReferenceExpression.callableReference, psiCall)
|
||||
|
||||
tracing.bindCall(topLevelTrace, psiCall)
|
||||
tracing.bindReference(topLevelTrace, resolvedCall)
|
||||
tracing.bindResolvedCall(topLevelTrace, resolvedCall)
|
||||
|
||||
resolvedCall.setStatusToSuccess()
|
||||
resolvedCall.markCallAsCompleted()
|
||||
|
||||
// TODO: probably we should also record key 'DATA_FLOW_INFO_BEFORE', see ExpressionTypingVisitorDispatcher.getTypeInfo
|
||||
val typeInfo = createTypeInfo(resultTypeInfo.resultType, resolvedAtom.atom.psiCallArgument.dataFlowInfoAfterThisArgument)
|
||||
val typeInfo = if (additionalDataFlowInfo != null) {
|
||||
createTypeInfo(resultTypeInfo.resultType, additionalDataFlowInfo)
|
||||
} else {
|
||||
createTypeInfo(resultTypeInfo.resultType)
|
||||
}
|
||||
|
||||
topLevelTrace.record(BindingContext.EXPRESSION_TYPE_INFO, callableReferenceExpression, typeInfo)
|
||||
topLevelTrace.record(BindingContext.PROCESSED, callableReferenceExpression)
|
||||
|
||||
kotlinToResolvedCallTransformer.runCallCheckers(resolvedCall, topLevelCallCheckerContext)
|
||||
resolvedAtom.completed = true
|
||||
|
||||
return resultTypeInfo.resultType
|
||||
}
|
||||
|
||||
private fun ReceiverValue.updateReceiverValue(substitutor: TypeSubstitutor): ReceiverValue {
|
||||
val newType = substitutor.safeSubstitute(type, Variance.INVARIANT).let {
|
||||
private fun ReceiverValue.updateReceiverValue(substitutor: NewTypeSubstitutor): ReceiverValue {
|
||||
val newType = substitutor.safeSubstitute(type.unwrap()).let {
|
||||
typeApproximator.approximateToSuperType(it, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference) ?: it
|
||||
}
|
||||
return if (type != newType) replaceType(newType as KotlinType) else this
|
||||
}
|
||||
|
||||
private fun recordArgumentAdaptationForCallableReference(
|
||||
resolvedCall: ResolvedCallImpl<CallableDescriptor>,
|
||||
resolvedCall: NewAbstractResolvedCall<*>,
|
||||
callableReferenceAdaptation: CallableReferenceAdaptation?
|
||||
) {
|
||||
if (callableReferenceAdaptation == null) return
|
||||
@@ -560,14 +601,12 @@ class ResolvedAtomCompleter(
|
||||
mappedArguments.add(valueParameter to resolvedValueArgument)
|
||||
}
|
||||
if (hasNonTrivialMapping || isCallableReferenceWithImplicitConversion(resolvedCall, callableReferenceAdaptation)) {
|
||||
for ((valueParameter, resolvedValueArgument) in mappedArguments) {
|
||||
resolvedCall.recordValueArgument(valueParameter, resolvedValueArgument)
|
||||
}
|
||||
resolvedCall.updateValueArguments(mappedArguments.toMap())
|
||||
}
|
||||
}
|
||||
|
||||
private fun isCallableReferenceWithImplicitConversion(
|
||||
resolvedCall: ResolvedCall<CallableDescriptor>,
|
||||
resolvedCall: NewAbstractResolvedCall<*>,
|
||||
callableReferenceAdaptation: CallableReferenceAdaptation
|
||||
): Boolean {
|
||||
val resultingDescriptor = resolvedCall.resultingDescriptor
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.psiKotlinCall
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
@@ -275,9 +276,16 @@ fun Call.isCallableReference(): Boolean {
|
||||
return callElement.isCallableReference()
|
||||
}
|
||||
|
||||
fun KtElement.isCallableReference(): Boolean =
|
||||
fun PsiElement.isCallableReference(): Boolean =
|
||||
this is KtNameReferenceExpression && (parent as? KtCallableReferenceExpression)?.callableReference == this
|
||||
|
||||
fun PsiElement.asCallableReferenceExpression(): KtCallableReferenceExpression? =
|
||||
when {
|
||||
isCallableReference() -> parent as KtCallableReferenceExpression
|
||||
this is KtCallableReferenceExpression -> this
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun Call.createLookupLocation(): KotlinLookupLocation {
|
||||
val calleeExpression = calleeExpression
|
||||
val element =
|
||||
@@ -339,3 +347,8 @@ fun <D : CallableDescriptor> ResolvedCallImpl<D>.shouldBeSubstituteWithStubTypes
|
||||
|| dispatchReceiver?.type?.contains { it is StubTypeForBuilderInference } == true
|
||||
|| extensionReceiver?.type?.contains { it is StubTypeForBuilderInference } == true
|
||||
|| valueArguments.any { argument -> argument.key.type.contains { it is StubTypeForBuilderInference } }
|
||||
|
||||
fun KotlinCall.extractCallableReferenceExpression(): KtCallableReferenceExpression? =
|
||||
psiKotlinCall.psiCall.extractCallableReferenceExpression()
|
||||
|
||||
fun Call.extractCallableReferenceExpression(): KtCallableReferenceExpression? = callElement.asCallableReferenceExpression()
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.util
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtCallElement
|
||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
@@ -17,7 +17,8 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.NewAbstractResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getOwnerForEffectiveDispatchReceiverParameter
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassValueReceiver
|
||||
@@ -98,7 +99,8 @@ fun KtCallElement.getArgumentByParameterIndex(index: Int, context: BindingContex
|
||||
val parameterToProcess = resolvedCall.resultingDescriptor.valueParameters.getOrNull(index) ?: return emptyList()
|
||||
return resolvedCall.valueArguments[parameterToProcess]?.arguments ?: emptyList()
|
||||
}
|
||||
fun CallableMemberDescriptor.isNotSimpleCall(): Boolean =
|
||||
|
||||
fun CallableDescriptor.isNotSimpleCall(): Boolean =
|
||||
typeParameters.isNotEmpty() ||
|
||||
(returnType?.let { type ->
|
||||
type.contains {
|
||||
@@ -109,7 +111,7 @@ fun CallableMemberDescriptor.isNotSimpleCall(): Boolean =
|
||||
}
|
||||
} ?: false)
|
||||
|
||||
fun ResolvedCall<*>.isNewNotCompleted(): Boolean = if (this is NewAbstractResolvedCall) !isCompleted else false
|
||||
fun ResolvedCall<*>.isNewNotCompleted(): Boolean = if (this is NewAbstractResolvedCall) !isCompleted() else false
|
||||
|
||||
fun ResolvedCall<*>.hasInferredReturnType(): Boolean {
|
||||
if (isNewNotCompleted()) return false
|
||||
|
||||
@@ -511,3 +511,15 @@ fun PsiElement?.unwrapParenthesesLabelsAndAnnotations(): PsiElement? {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun PsiElement.unwrapParenthesesLabelsAndAnnotationsDeeply(): PsiElement {
|
||||
var current: PsiElement = this
|
||||
var unwrapped: PsiElement?
|
||||
|
||||
do {
|
||||
unwrapped = current.parent?.unwrapParenthesesLabelsAndAnnotations()
|
||||
current = current.parent
|
||||
} while (unwrapped != current)
|
||||
|
||||
return unwrapped
|
||||
}
|
||||
|
||||
+4
@@ -41,6 +41,10 @@ abstract class ArgumentConstraintPosition<out T>(val argument: T) : ConstraintPo
|
||||
override fun toString(): String = "Argument $argument"
|
||||
}
|
||||
|
||||
abstract class CallableReferenceConstraintPosition<out T>(val call: T) : ConstraintPosition(), OnlyInputTypeConstraintPosition {
|
||||
override fun toString(): String = "Callable reference $call"
|
||||
}
|
||||
|
||||
abstract class ReceiverConstraintPosition<T>(val argument: T) : ConstraintPosition(), OnlyInputTypeConstraintPosition {
|
||||
override fun toString(): String = "Receiver $argument"
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+74
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+46
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
+17
-44
@@ -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" }
|
||||
|
||||
-162
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -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(
|
||||
|
||||
+17
-1
@@ -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
|
||||
|
||||
+29
-14
@@ -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)
|
||||
|
||||
+5
-3
@@ -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")
|
||||
|
||||
|
||||
+26
-6
@@ -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
|
||||
|
||||
+4
-2
@@ -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 ||
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+44
-46
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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()
|
||||
}
|
||||
|
||||
+9
-3
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -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(
|
||||
|
||||
+3
@@ -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(
|
||||
|
||||
+62
-63
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
+29
-24
@@ -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()
|
||||
|
||||
+3
-1
@@ -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)
|
||||
}
|
||||
|
||||
+13
@@ -19,8 +19,21 @@ val j1: J<String> = Impl("O")
|
||||
// would produce an error.
|
||||
val x by j1::value
|
||||
|
||||
@Target(AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.EXPRESSION, AnnotationTarget.FILE)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class Anno
|
||||
|
||||
fun box(): String {
|
||||
val j2: J<String> = Impl("K")
|
||||
val y by j2::value
|
||||
val y1 by @Anno j2::value
|
||||
val y2 by (j2::value)
|
||||
val y3 by (j2)::value
|
||||
val y4 by ((j2)::value)
|
||||
val y5 by (((j2)::value))
|
||||
val y6 by @Anno() (((j2)::value))
|
||||
val y7 by (@Anno() ((j2)::value))
|
||||
val y8 by ((@Anno() (j2)::value))
|
||||
val y9 by @Anno() ((@Anno() (j2)::value))
|
||||
return x + y
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS
|
||||
fun box(): String {
|
||||
val z = "K"
|
||||
open class A(val x: String) {
|
||||
|
||||
+1
-1
@@ -37,5 +37,5 @@ fun test() {
|
||||
val r7 = c::foo
|
||||
checkSubtype<() -> String>(r7)
|
||||
|
||||
C::<!UNRESOLVED_REFERENCE!>bar<!>
|
||||
C::bar
|
||||
}
|
||||
|
||||
+5
-5
@@ -6,10 +6,10 @@ public interface J {
|
||||
|
||||
// FILE: test.kt
|
||||
|
||||
fun f1(x: Int?): Any = x::<!UNSAFE_CALL!>hashCode<!>
|
||||
fun <T> f2(t: T): Any = t::<!UNSAFE_CALL!>hashCode<!>
|
||||
fun <S : String?> f3(s: S): Any = s::<!UNSAFE_CALL!>hashCode<!>
|
||||
fun <U : Any> f4(u: U?): Any = u::<!UNSAFE_CALL!>hashCode<!>
|
||||
fun f5(c: List<*>): Any = c[0]::<!UNSAFE_CALL!>hashCode<!>
|
||||
fun f1(x: Int?): Any = x::<!TYPE_MISMATCH, UNSAFE_CALL!>hashCode<!>
|
||||
fun <T> f2(t: T): Any = t::<!TYPE_MISMATCH, UNSAFE_CALL!>hashCode<!>
|
||||
fun <S : String?> f3(s: S): Any = s::<!TYPE_MISMATCH, UNSAFE_CALL!>hashCode<!>
|
||||
fun <U : Any> f4(u: U?): Any = u::<!TYPE_MISMATCH, UNSAFE_CALL!>hashCode<!>
|
||||
fun f5(c: List<*>): Any = c[0]::<!TYPE_MISMATCH, UNSAFE_CALL!>hashCode<!>
|
||||
|
||||
fun f6(j: J): Any = j.platformString()::hashCode
|
||||
|
||||
+3
-3
@@ -18,9 +18,9 @@ class Test {
|
||||
val <T> List<T>.b: Int? get() = size
|
||||
|
||||
fun <T> List<T>.testCallable1(): () -> Unit = <!RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS!>a<T><!>::foo
|
||||
fun <T> List<T>.testCallable2(): () -> Unit = <!RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS!>b<!>?::<!UNSAFE_CALL!>foo<!>
|
||||
fun <T> List<T>.testCallable3(): () -> Unit = <!RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS!>b<T, Any><!>::<!UNSAFE_CALL!>foo<!>
|
||||
fun <T> List<T>.testCallable4(): () -> Unit = <!RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS!>b<T><!>?::<!UNSAFE_CALL!>foo<!>
|
||||
fun <T> List<T>.testCallable2(): () -> Unit = <!RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS!>b<!>?::<!TYPE_MISMATCH, UNSAFE_CALL!>foo<!>
|
||||
fun <T> List<T>.testCallable3(): () -> Unit = <!RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS!>b<T, Any><!>::<!TYPE_MISMATCH, UNSAFE_CALL!>foo<!>
|
||||
fun <T> List<T>.testCallable4(): () -> Unit = <!RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS!>b<T><!>?::<!TYPE_MISMATCH, UNSAFE_CALL!>foo<!>
|
||||
|
||||
fun <T> List<T>.testClassLiteral1() = <!RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS!>a<T><!>::class
|
||||
fun <T> List<T>.testClassLiteral2() = <!EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS, RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS!>b<!>?::class
|
||||
|
||||
+1
-1
@@ -4,4 +4,4 @@ package test
|
||||
fun nullableFun(): Int? = null
|
||||
fun Int.foo() {}
|
||||
|
||||
val test1 = <!RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS!>nullableFun()<!>?::<!UNSAFE_CALL!>foo<!>
|
||||
val test1 = <!RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS!>nullableFun()<!>?::<!TYPE_MISMATCH, UNSAFE_CALL!>foo<!>
|
||||
|
||||
+3
@@ -1,8 +1,11 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
fun <K> id(x: K) = x
|
||||
|
||||
class A1 {
|
||||
fun <T> a1(t: T): Unit {}
|
||||
fun test1(): (String) -> Unit = A1()::a1
|
||||
fun test2(): (String) -> Unit = id(A1()::a1)
|
||||
}
|
||||
|
||||
class A2 {
|
||||
|
||||
+4
-1
@@ -1,8 +1,11 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
fun <K> id(x: K) = x
|
||||
|
||||
class A1 {
|
||||
fun <T> a1(t: T): Unit {}
|
||||
fun test1(): (String) -> Unit = A1()::a1
|
||||
fun test2(): (String) -> Unit = id(A1()::a1)
|
||||
}
|
||||
|
||||
class A2 {
|
||||
@@ -19,6 +22,6 @@ class A3<T> {
|
||||
fun test2(): (T) -> Unit = A3<T>()::a3
|
||||
fun test3(): (Int) -> String = A3<Int>()::a3
|
||||
|
||||
fun <R> test4(): (R) -> Unit = <!TYPE_MISMATCH!>this::<!TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR!>a3<!><!>
|
||||
fun <R> test4(): (R) -> Unit = this::<!TYPE_MISMATCH!>a3<!>
|
||||
fun <R> test5(): (T) -> R = this::a3
|
||||
}
|
||||
+3
@@ -1,11 +1,14 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ K> id(/*0*/ x: K): K
|
||||
|
||||
public final class A1 {
|
||||
public constructor A1()
|
||||
public final fun </*0*/ T> a1(/*0*/ t: T): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final fun test1(): (kotlin.String) -> kotlin.Unit
|
||||
public final fun test2(): (kotlin.String) -> kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -5,5 +5,5 @@ class Foo {
|
||||
}
|
||||
|
||||
fun test() {
|
||||
Foo::<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>bar<!> <!SYNTAX!>< <!DEBUG_INFO_MISSING_UNRESOLVED!>Int<!> ><!> <!SYNTAX!>(2 <!DEBUG_INFO_MISSING_UNRESOLVED!>+<!> 2)<!>
|
||||
Foo::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>bar<!> <!SYNTAX!>< <!DEBUG_INFO_MISSING_UNRESOLVED!>Int<!> ><!> <!SYNTAX!>(2 <!DEBUG_INFO_MISSING_UNRESOLVED!>+<!> 2)<!>
|
||||
}
|
||||
|
||||
compiler/testData/diagnostics/tests/callableReference/referenceAdaptationHasDependencyOnApi14.fir.kt
Vendored
-18
@@ -1,18 +0,0 @@
|
||||
// !API_VERSION: 1.3
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
class A {
|
||||
fun foo(s: String = "", vararg xs: Long): String = "foo"
|
||||
}
|
||||
|
||||
fun coercionToUnit(f: (A, String, LongArray) -> Unit): Any = f
|
||||
fun varargToElement(f: (A, String, Long, Long) -> String): Any = f
|
||||
fun defaultAndVararg(f: (A) -> String): Any = f
|
||||
fun allOfTheAbove(f: (A) -> Unit): Any = f
|
||||
|
||||
fun test() {
|
||||
coercionToUnit(A::foo)
|
||||
varargToElement(A::foo)
|
||||
defaultAndVararg(A::foo)
|
||||
allOfTheAbove(A::foo)
|
||||
}
|
||||
Vendored
-18
@@ -1,18 +0,0 @@
|
||||
// !API_VERSION: 1.3
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
class A {
|
||||
fun foo(s: String = "", vararg xs: Long): String = "foo"
|
||||
}
|
||||
|
||||
fun coercionToUnit(f: (A, String, LongArray) -> Unit): Any = f
|
||||
fun varargToElement(f: (A, String, Long, Long) -> String): Any = f
|
||||
fun defaultAndVararg(f: (A) -> String): Any = f
|
||||
fun allOfTheAbove(f: (A) -> Unit): Any = f
|
||||
|
||||
fun test() {
|
||||
coercionToUnit(<!TYPE_MISMATCH!>A::foo<!>)
|
||||
varargToElement(<!TYPE_MISMATCH!>A::foo<!>)
|
||||
defaultAndVararg(<!TYPE_MISMATCH!>A::foo<!>)
|
||||
allOfTheAbove(<!TYPE_MISMATCH!>A::foo<!>)
|
||||
}
|
||||
Vendored
-15
@@ -1,15 +0,0 @@
|
||||
package
|
||||
|
||||
public fun allOfTheAbove(/*0*/ f: (A) -> kotlin.Unit): kotlin.Any
|
||||
public fun coercionToUnit(/*0*/ f: (A, kotlin.String, kotlin.LongArray) -> kotlin.Unit): kotlin.Any
|
||||
public fun defaultAndVararg(/*0*/ f: (A) -> kotlin.String): kotlin.Any
|
||||
public fun test(): kotlin.Unit
|
||||
public fun varargToElement(/*0*/ f: (A, kotlin.String, kotlin.Long, kotlin.Long) -> kotlin.String): kotlin.Any
|
||||
|
||||
public final class A {
|
||||
public constructor A()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun foo(/*0*/ s: kotlin.String = ..., /*1*/ vararg xs: kotlin.Long /*kotlin.LongArray*/): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -26,6 +26,6 @@ fun main() {
|
||||
// It must be OK
|
||||
val x18 = String?::hashCode <!USELESS_ELVIS!>?: ::foo<!>
|
||||
val x19 = String::hashCode <!USELESS_ELVIS!>?: ::foo<!>
|
||||
val x20 = String?::<!UNSAFE_CALL!>hashCode<!>::hashCode
|
||||
val x21 = kotlin.String?::<!UNSAFE_CALL!>hashCode<!>::hashCode
|
||||
val x20 = String?::hashCode::hashCode
|
||||
val x21 = kotlin.String?::hashCode::hashCode
|
||||
}
|
||||
|
||||
compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferences.kt
Vendored
+1
-1
@@ -381,7 +381,7 @@ fun poll65(): Flow<String> {
|
||||
|
||||
fun poll66(): Flow<String> {
|
||||
return flow {
|
||||
val inv = ::<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Foo7<!>
|
||||
val inv = ::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Foo7<!>
|
||||
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>inv<!>
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -383,7 +383,7 @@ fun poll65(): Flow<String> {
|
||||
|
||||
fun poll66(): Flow<String> {
|
||||
return flow {
|
||||
val inv = ::<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Foo7<!>
|
||||
val inv = ::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Foo7<!>
|
||||
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>inv<!>
|
||||
}
|
||||
}
|
||||
|
||||
+19
@@ -23,38 +23,57 @@ fun <T> Foo2<T>.setX(y: T): T {
|
||||
|
||||
fun Float.bar() {}
|
||||
|
||||
fun <K> id(x: K) = x
|
||||
|
||||
fun test1() {
|
||||
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, CapturedType(*), CapturedType(*)>")!>Foo<*>::setX<!>
|
||||
|
||||
val fooSetRef2 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, kotlin.Nothing, kotlin.Number>")!>id(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, CapturedType(*), CapturedType(*)>")!>Foo<*>::setX<!>
|
||||
)<!>
|
||||
val foo = Foo<Float>(1f)
|
||||
|
||||
fooSetRef.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>1<!>)
|
||||
fooSetRef2.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>1<!>)
|
||||
|
||||
foo.x.bar()
|
||||
}
|
||||
|
||||
fun test2() {
|
||||
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, CapturedType(*), CapturedType(*)>")!>Foo<*>::setX1<!>
|
||||
val fooSetRef2 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, kotlin.Nothing, kotlin.Number>")!>id(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, CapturedType(*), CapturedType(*)>")!>Foo<*>::setX1<!>
|
||||
)<!>
|
||||
val foo = Foo<Float>(1f)
|
||||
|
||||
fooSetRef.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>1<!>)
|
||||
fooSetRef2.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>1<!>)
|
||||
|
||||
foo.x.bar()
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, CapturedType(*), CapturedType(*)>")!>Foo2<*>::setX<!>
|
||||
val fooSetRef2 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, kotlin.Nothing, kotlin.Any?>")!>id(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, CapturedType(*), CapturedType(*)>")!>Foo2<*>::setX<!>
|
||||
)<!>
|
||||
val foo = Foo2<Int>(1)
|
||||
|
||||
fooSetRef.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>""<!>)
|
||||
fooSetRef2.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>""<!>)
|
||||
|
||||
foo.x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>bar<!>()
|
||||
}
|
||||
|
||||
fun test4() {
|
||||
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, CapturedType(*), CapturedType(*)>")!>Foo2<*>::setX1<!>
|
||||
val fooSetRef2 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, kotlin.Nothing, kotlin.Any?>")!>id(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, CapturedType(*), CapturedType(*)>")!>Foo2<*>::setX1<!>
|
||||
)<!>
|
||||
val foo = Foo2<Int>(1)
|
||||
|
||||
fooSetRef.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>""<!>)
|
||||
fooSetRef2.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>""<!>)
|
||||
|
||||
foo.x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>bar<!>()
|
||||
}
|
||||
|
||||
compiler/testData/diagnostics/tests/inference/capturedTypes/approximateContravariantCapturedTypes.kt
Vendored
+21
-2
@@ -23,38 +23,57 @@ fun <T> Foo2<T>.setX(y: T): T {
|
||||
|
||||
fun Float.bar() {}
|
||||
|
||||
fun <K> id(x: K) = x
|
||||
|
||||
fun test1() {
|
||||
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, kotlin.Nothing, kotlin.Number>")!>Foo<*>::<!TYPE_MISMATCH("Nothing; Foo<*>")!>setX<!><!>
|
||||
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, kotlin.Nothing, kotlin.Number>")!>Foo<*>::<!TYPE_MISMATCH, TYPE_MISMATCH!>setX<!><!>
|
||||
|
||||
val fooSetRef2 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, kotlin.Nothing, kotlin.Number>")!>id(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, CapturedType(*), CapturedType(*)>")!>Foo<*>::setX<!>
|
||||
)<!>
|
||||
val foo = Foo<Float>(1f)
|
||||
|
||||
fooSetRef.invoke(foo, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
|
||||
fooSetRef2.invoke(foo, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
|
||||
|
||||
foo.x.bar()
|
||||
}
|
||||
|
||||
fun test2() {
|
||||
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, kotlin.Nothing, kotlin.Number>")!>Foo<*>::setX1<!>
|
||||
val fooSetRef2 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, kotlin.Nothing, kotlin.Number>")!>id(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, kotlin.Nothing, kotlin.Number>")!>Foo<*>::setX1<!>
|
||||
)<!>
|
||||
val foo = Foo<Float>(1f)
|
||||
|
||||
fooSetRef.invoke(foo, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
|
||||
fooSetRef2.invoke(foo, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
|
||||
|
||||
foo.x.bar()
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, kotlin.Nothing, kotlin.Any?>")!>Foo2<*>::<!TYPE_MISMATCH("Nothing; Foo2<*>")!>setX<!><!>
|
||||
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, kotlin.Nothing, kotlin.Any?>")!>Foo2<*>::<!TYPE_MISMATCH, TYPE_MISMATCH!>setX<!><!>
|
||||
val fooSetRef2 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, kotlin.Nothing, kotlin.Any?>")!>id(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, CapturedType(*), CapturedType(*)>")!>Foo2<*>::setX<!>
|
||||
)<!>
|
||||
val foo = Foo2<Int>(1)
|
||||
|
||||
fooSetRef.invoke(foo, <!TYPE_MISMATCH!>""<!>)
|
||||
fooSetRef2.invoke(foo, <!TYPE_MISMATCH!>""<!>)
|
||||
|
||||
foo.x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>bar<!>()
|
||||
}
|
||||
|
||||
fun test4() {
|
||||
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, kotlin.Nothing, kotlin.Any?>")!>Foo2<*>::setX1<!>
|
||||
val fooSetRef2 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, kotlin.Nothing, kotlin.Any?>")!>id(
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, kotlin.Nothing, kotlin.Any?>")!>Foo2<*>::setX1<!>
|
||||
)<!>
|
||||
val foo = Foo2<Int>(1)
|
||||
|
||||
fooSetRef.invoke(foo, <!TYPE_MISMATCH!>""<!>)
|
||||
fooSetRef2.invoke(foo, <!TYPE_MISMATCH!>""<!>)
|
||||
|
||||
foo.x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>bar<!>()
|
||||
}
|
||||
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ K> id(/*0*/ x: K): K
|
||||
public fun test1(): kotlin.Unit
|
||||
public fun test2(): kotlin.Unit
|
||||
public fun test3(): kotlin.Unit
|
||||
|
||||
@@ -114,14 +114,14 @@ fun <T : Foo, R: Number, D: Int> main() {
|
||||
bar7(Foo::resolve) // OK
|
||||
|
||||
// with LHS and sentension function expected type
|
||||
bar10<D>(<!TYPE_MISMATCH!>Int::<!CALLABLE_REFERENCE_RESOLUTION_AMBIGUITY!>x1<!><!>) // ERROR before the fix in NI
|
||||
bar10<D>(<!TYPE_MISMATCH!>Int::x1<!>) // ERROR before the fix in NI
|
||||
bar10<Int>(Int::x1) // OK
|
||||
bar10(Int::x1) // OK
|
||||
|
||||
fun Int.ext() {
|
||||
// with LHS and sentension function expected type
|
||||
bar10<D>(::<!CALLABLE_REFERENCE_RESOLUTION_AMBIGUITY!>x1<!>) // ERROR before the fix in NI
|
||||
bar10<Int>(::<!CALLABLE_REFERENCE_RESOLUTION_AMBIGUITY!>x1<!>) // OK
|
||||
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>bar10<!>(::<!CALLABLE_REFERENCE_RESOLUTION_AMBIGUITY!>x1<!>) // OK
|
||||
bar10<D>(<!TYPE_MISMATCH("KProperty1<TypeVariable(K), String>; KProperty0<String>")!>::x1<!>) // ERROR before the fix in NI
|
||||
bar10<Int>(<!TYPE_MISMATCH("KProperty1<TypeVariable(K), String>; KProperty0<String>")!>::x1<!>) // OK
|
||||
bar10(<!TYPE_MISMATCH("KProperty1<TypeVariable(K), String>; KProperty0<String>")!>::x1<!>) // OK
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -9,8 +9,8 @@ class Foo7<T>
|
||||
fun foo7() = null as Foo7<Int>
|
||||
|
||||
fun poll17(flag: Boolean): Any? {
|
||||
val inv = if (flag) { foo7() } else { <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>::Foo7<!> }
|
||||
return <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>inv<!>
|
||||
val inv = if (flag) { <!IMPLICIT_CAST_TO_ANY!>foo7()<!> } else { <!IMPLICIT_CAST_TO_ANY!>::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Foo7<!><!> }
|
||||
return inv
|
||||
}
|
||||
|
||||
fun poll26(flag: Boolean): Any? {
|
||||
@@ -24,6 +24,6 @@ fun poll36(flag: Boolean): Any? {
|
||||
}
|
||||
|
||||
fun poll56(): Any? {
|
||||
val inv = try { <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>::Foo7<!> } catch (e: Exception) { foo7() } finally { foo7() }
|
||||
return <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>inv<!>
|
||||
val inv = try { ::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Foo7<!> } catch (e: Exception) { foo7() } finally { foo7() }
|
||||
return inv
|
||||
}
|
||||
|
||||
+5
@@ -18,6 +18,11 @@ class Foo6
|
||||
class Foo7<T>
|
||||
fun foo7() = null as Foo7<Int>
|
||||
|
||||
fun poll0(flag: Boolean) {
|
||||
val inv = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction0<kotlin.Int>")!>if (flag) { ::bar2 } else { ::foo4 }<!>
|
||||
inv()
|
||||
}
|
||||
|
||||
fun poll1(flag: Boolean) {
|
||||
val inv = if (flag) { ::bar2 } else { ::foo2 }
|
||||
inv()
|
||||
|
||||
+15
-10
@@ -18,6 +18,11 @@ class Foo6
|
||||
class Foo7<T>
|
||||
fun foo7() = null as Foo7<Int>
|
||||
|
||||
fun poll0(flag: Boolean) {
|
||||
val inv = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction0<kotlin.Int>")!>if (flag) { ::bar2 } else { ::foo4 }<!>
|
||||
inv()
|
||||
}
|
||||
|
||||
fun poll1(flag: Boolean) {
|
||||
val inv = if (flag) { ::bar2 } else { ::foo2 }
|
||||
inv()
|
||||
@@ -39,7 +44,7 @@ fun poll13(flag: Boolean) {
|
||||
}
|
||||
|
||||
fun poll14(flag: Boolean) {
|
||||
val inv = if (flag) { <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>::bar4<!> } else { <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>::foo4<!> }
|
||||
val inv = if (flag) { ::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>bar4<!> } else { ::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo4<!> }
|
||||
<!DEBUG_INFO_MISSING_UNRESOLVED!>inv<!>()
|
||||
}
|
||||
|
||||
@@ -54,8 +59,8 @@ fun poll16(flag: Boolean) {
|
||||
}
|
||||
|
||||
fun poll17(flag: Boolean) {
|
||||
val inv = if (flag) { foo7() } else { <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>::Foo7<!> }
|
||||
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>inv<!>
|
||||
val inv = if (flag) { <!IMPLICIT_CAST_TO_ANY!>foo7()<!> } else { <!IMPLICIT_CAST_TO_ANY!>::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Foo7<!><!> }
|
||||
inv
|
||||
}
|
||||
|
||||
fun poll2(flag: Boolean) {
|
||||
@@ -144,7 +149,7 @@ fun poll42() {
|
||||
}
|
||||
|
||||
fun poll43() {
|
||||
val inv = try { <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>::bar4<!> } finally { ::<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo4<!> }
|
||||
val inv = try { ::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>bar4<!> } finally { ::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo4<!> }
|
||||
<!DEBUG_INFO_MISSING_UNRESOLVED!>inv<!>()
|
||||
}
|
||||
|
||||
@@ -159,7 +164,7 @@ fun poll45() {
|
||||
}
|
||||
|
||||
fun poll46() {
|
||||
val inv = try { foo7() } finally { ::<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Foo7<!> }
|
||||
val inv = try { foo7() } finally { ::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Foo7<!> }
|
||||
inv
|
||||
}
|
||||
|
||||
@@ -179,7 +184,7 @@ fun poll52() {
|
||||
}
|
||||
|
||||
fun poll53() {
|
||||
val inv = try { <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>::bar4<!> } catch (e: Exception) { <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>::foo4<!> } finally { ::<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo4<!> }
|
||||
val inv = try { ::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>bar4<!> } catch (e: Exception) { ::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo4<!> } finally { ::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo4<!> }
|
||||
<!DEBUG_INFO_MISSING_UNRESOLVED!>inv<!>()
|
||||
}
|
||||
|
||||
@@ -194,8 +199,8 @@ fun poll55() {
|
||||
}
|
||||
|
||||
fun poll56() {
|
||||
val inv = try { <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>::Foo7<!> } catch (e: Exception) { foo7() } finally { foo7() }
|
||||
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>inv<!>
|
||||
val inv = try { ::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Foo7<!> } catch (e: Exception) { foo7() } finally { foo7() }
|
||||
inv
|
||||
}
|
||||
|
||||
fun poll6() {
|
||||
@@ -214,7 +219,7 @@ fun poll62() {
|
||||
}
|
||||
|
||||
fun poll63() {
|
||||
val inv = ::<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>bar4<!>
|
||||
val inv = ::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>bar4<!>
|
||||
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>inv<!>
|
||||
}
|
||||
|
||||
@@ -229,7 +234,7 @@ fun poll65() {
|
||||
}
|
||||
|
||||
fun poll66() {
|
||||
val inv = ::<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Foo7<!>
|
||||
val inv = ::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Foo7<!>
|
||||
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>inv<!>
|
||||
}
|
||||
|
||||
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
// !LANGUAGE: -ProhibitVisibilityOfNestedClassifiersFromSupertypesOfCompanion
|
||||
|
||||
import A.Base.Companion.FromABaseCompanion
|
||||
import B.Base.Companion.FromBBaseCompanion
|
||||
import C.Base.Companion.FromCBaseCompanion
|
||||
import D.Base.Companion.FromDBaseCompanion
|
||||
|
||||
// ===== Case 1: LHS is a class
|
||||
//
|
||||
object A {
|
||||
open class Base {
|
||||
companion object {
|
||||
class FromABaseCompanion {
|
||||
fun foo() = 42
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Derived : Base() {
|
||||
val a = FromABaseCompanion::foo
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Case 2: LHS is a class with companion object, function comes from class
|
||||
|
||||
object B {
|
||||
open class Base {
|
||||
companion object {
|
||||
class FromBBaseCompanion {
|
||||
fun foo() = 42
|
||||
|
||||
companion object {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Derived : Base() {
|
||||
val a = FromBBaseCompanion::foo
|
||||
}
|
||||
}
|
||||
|
||||
// ==== Case 3: LHS is a class with companion object, function comes from companion
|
||||
|
||||
object C {
|
||||
open class Base {
|
||||
companion object {
|
||||
class FromCBaseCompanion {
|
||||
companion object {
|
||||
fun foo() = 42
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Derived : Base() {
|
||||
val a = FromCBaseCompanion::foo
|
||||
}
|
||||
}
|
||||
|
||||
// ==== Case 4: LHS is an object
|
||||
|
||||
object D {
|
||||
open class Base {
|
||||
companion object {
|
||||
object FromDBaseCompanion {
|
||||
fun foo() = 42
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Derived : Base() {
|
||||
val a = FromDBaseCompanion::foo
|
||||
}
|
||||
}
|
||||
Vendored
+2
-1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !LANGUAGE: -ProhibitVisibilityOfNestedClassifiersFromSupertypesOfCompanion
|
||||
|
||||
import A.Base.Companion.FromABaseCompanion
|
||||
@@ -53,7 +54,7 @@ object C {
|
||||
}
|
||||
|
||||
class Derived : Base() {
|
||||
val a = FromCBaseCompanion::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
val a = FromCBaseCompanion::foo
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -118,7 +118,7 @@ public object C {
|
||||
|
||||
public final class Derived : C.Base {
|
||||
public constructor Derived()
|
||||
public final val a: [ERROR : Type for FromCBaseCompanion::foo]
|
||||
public final val a: kotlin.reflect.KFunction1<C.Base.Companion.FromCBaseCompanion, kotlin.Int>
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
// !LANGUAGE: -ProhibitVisibilityOfNestedClassifiersFromSupertypesOfCompanion
|
||||
|
||||
// ===== Case 1: LHS is a class
|
||||
//
|
||||
object A {
|
||||
open class Base {
|
||||
companion object {
|
||||
class FromBaseCompanion {
|
||||
fun foo() = 42
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Derived : Base() {
|
||||
val a = A.Base.Companion.FromBaseCompanion::foo
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Case 2: LHS is a class with companion object, function comes from class
|
||||
|
||||
object B {
|
||||
open class Base {
|
||||
companion object {
|
||||
class FromBaseCompanion {
|
||||
fun foo() = 42
|
||||
|
||||
companion object {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Derived : Base() {
|
||||
val a = B.Base.Companion.FromBaseCompanion::foo
|
||||
}
|
||||
}
|
||||
|
||||
// ==== Case 3: LHS is a class with companion object, function comes from companion
|
||||
|
||||
object C {
|
||||
open class Base {
|
||||
companion object {
|
||||
class FromBaseCompanion {
|
||||
companion object {
|
||||
fun foo() = 42
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Derived : Base() {
|
||||
val a = C.Base.Companion.FromBaseCompanion::foo
|
||||
}
|
||||
}
|
||||
|
||||
// ==== Case 4: LHS is an object
|
||||
|
||||
object D {
|
||||
open class Base {
|
||||
companion object {
|
||||
object FromBaseCompanion {
|
||||
fun foo() = 42
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Derived : Base() {
|
||||
val a = D.Base.Companion.FromBaseCompanion::foo
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !LANGUAGE: -ProhibitVisibilityOfNestedClassifiersFromSupertypesOfCompanion
|
||||
|
||||
// ===== Case 1: LHS is a class
|
||||
@@ -48,7 +49,7 @@ object C {
|
||||
}
|
||||
|
||||
class Derived : Base() {
|
||||
val a = C.Base.Companion.FromBaseCompanion::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
val a = C.Base.Companion.FromBaseCompanion::foo
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ public object C {
|
||||
|
||||
public final class Derived : C.Base {
|
||||
public constructor Derived()
|
||||
public final val a: [ERROR : Type for C.Base.Companion.FromBaseCompanion::foo]
|
||||
public final val a: kotlin.reflect.KFunction1<C.Base.Companion.FromBaseCompanion, kotlin.Int>
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ object C {
|
||||
}
|
||||
|
||||
class Derived : Base() {
|
||||
val a = <!DEPRECATED_ACCESS_BY_SHORT_NAME!>FromBaseCompanion<!>::<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
val a = <!DEPRECATED_ACCESS_BY_SHORT_NAME!>FromBaseCompanion<!>::foo
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ public object C {
|
||||
|
||||
public final class Derived : C.Base {
|
||||
public constructor Derived()
|
||||
public final val a: [ERROR : Type for FromBaseCompanion::foo]
|
||||
public final val a: kotlin.reflect.KFunction1<C.Base.Companion.FromBaseCompanion, kotlin.Int>
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ fun box() {
|
||||
|
||||
println(::<!CALL_TO_JS_MODULE_WITHOUT_MODULE_SYSTEM!>bar<!>.name)
|
||||
println(::<!CALL_TO_JS_MODULE_WITHOUT_MODULE_SYSTEM!>baz<!>.name)
|
||||
println(<!CALL_TO_JS_MODULE_WITHOUT_MODULE_SYSTEM!>A<!>::f.name)
|
||||
println(<!CALL_TO_JS_MODULE_WITHOUT_MODULE_SYSTEM!>A<!>::<!CALL_TO_JS_MODULE_WITHOUT_MODULE_SYSTEM!>f<!>.name)
|
||||
|
||||
B.<!CALL_TO_JS_MODULE_WITHOUT_MODULE_SYSTEM!>Nested<!>()
|
||||
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ fun box() {
|
||||
B.<!CALL_TO_JS_NON_MODULE_WITH_MODULE_SYSTEM!>Nested<!>()
|
||||
|
||||
println(::<!CALL_TO_JS_NON_MODULE_WITH_MODULE_SYSTEM!>bar<!>.name)
|
||||
println(<!CALL_TO_JS_NON_MODULE_WITH_MODULE_SYSTEM!>A<!>::f.name)
|
||||
println(<!CALL_TO_JS_NON_MODULE_WITH_MODULE_SYSTEM!>A<!>::<!CALL_TO_JS_NON_MODULE_WITH_MODULE_SYSTEM!>f<!>.name)
|
||||
|
||||
boo<<!CALL_TO_JS_NON_MODULE_WITH_MODULE_SYSTEM!>B?<!>>(null)
|
||||
<!CALL_TO_JS_NON_MODULE_WITH_MODULE_SYSTEM!>boo<!>(null as B?)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
fun f(x: Any): String {
|
||||
when {
|
||||
x is A<*> -> { // BLOCK
|
||||
return x /*as A<*> */ /*as A<T> */.call(block = local fun <anonymous>(y: Any?): @FlexibleNullability String? {
|
||||
return x /*as A<*> */.call(block = local fun <anonymous>(y: Any?): @FlexibleNullability String? {
|
||||
return "OK"
|
||||
}
|
||||
/*-> @FlexibleNullability I<@FlexibleNullability T?>? */) /*!! String */
|
||||
/*-> @FlexibleNullability I<Nothing>? */) /*!! String */
|
||||
}
|
||||
}
|
||||
return "Fail"
|
||||
|
||||
@@ -10,10 +10,9 @@ FILE fqName:<root> fileName:/genericSamSmartcast.kt
|
||||
RETURN type=kotlin.Nothing from='public final fun f (x: kotlin.Any): kotlin.String declared in <root>'
|
||||
TYPE_OP type=kotlin.String origin=IMPLICIT_NOTNULL typeOperand=kotlin.String
|
||||
CALL 'public open fun call (block: @[FlexibleNullability] <root>.A.I<@[FlexibleNullability] T of <root>.A?>?): @[FlexibleNullability] kotlin.String? declared in <root>.A' type=@[FlexibleNullability] kotlin.String? origin=null
|
||||
$this: TYPE_OP type=<root>.A<T of <root>.A> origin=IMPLICIT_CAST typeOperand=<root>.A<T of <root>.A>
|
||||
TYPE_OP type=<root>.A<*> origin=IMPLICIT_CAST typeOperand=<root>.A<*>
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.f' type=kotlin.Any origin=null
|
||||
block: TYPE_OP type=@[FlexibleNullability] <root>.A.I<@[FlexibleNullability] T of <root>.A?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] <root>.A.I<@[FlexibleNullability] T of <root>.A?>?
|
||||
$this: TYPE_OP type=<root>.A<*> origin=IMPLICIT_CAST typeOperand=<root>.A<*>
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.f' type=kotlin.Any origin=null
|
||||
block: TYPE_OP type=@[FlexibleNullability] <root>.A.I<kotlin.Nothing>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] <root>.A.I<kotlin.Nothing>?
|
||||
FUN_EXPR type=kotlin.Function1<kotlin.Any?, @[FlexibleNullability] kotlin.String?> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (y:kotlin.Any?) returnType:@[FlexibleNullability] kotlin.String?
|
||||
VALUE_PARAMETER name:y index:0 type:kotlin.Any?
|
||||
|
||||
-1
@@ -8,7 +8,6 @@ class A {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: constructor B(arg: String) defined in A.B
|
||||
Resulting descriptor: constructor B(arg: String) defined in A.B
|
||||
|
||||
Explicit receiver kind = DISPATCH_RECEIVER
|
||||
|
||||
-1
@@ -9,7 +9,6 @@ class A {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: constructor B(x: String) defined in A.B
|
||||
Resulting descriptor: constructor B(x: String) defined in A.B
|
||||
|
||||
Explicit receiver kind = DISPATCH_RECEIVER
|
||||
|
||||
@@ -8,7 +8,6 @@ class A : B, C {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: constructor B(x: Int) defined in B
|
||||
Resulting descriptor: constructor B(x: Int) defined in B
|
||||
|
||||
Explicit receiver kind = NO_EXPLICIT_RECEIVER
|
||||
|
||||
@@ -8,7 +8,6 @@ class A : B, C {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: constructor B() defined in B
|
||||
Resulting descriptor: constructor B() defined in B
|
||||
|
||||
Explicit receiver kind = NO_EXPLICIT_RECEIVER
|
||||
|
||||
@@ -8,7 +8,6 @@ class A : B, C {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: constructor B() defined in B
|
||||
Resulting descriptor: constructor B() defined in B
|
||||
|
||||
Explicit receiver kind = NO_EXPLICIT_RECEIVER
|
||||
|
||||
@@ -10,7 +10,6 @@ class A : B, C {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: constructor B(x: Int) defined in B
|
||||
Resulting descriptor: constructor B(x: Int) defined in B
|
||||
|
||||
Explicit receiver kind = NO_EXPLICIT_RECEIVER
|
||||
|
||||
-1
@@ -10,7 +10,6 @@ class A : B, C {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: constructor B() defined in B
|
||||
Resulting descriptor: constructor B() defined in B
|
||||
|
||||
Explicit receiver kind = NO_EXPLICIT_RECEIVER
|
||||
|
||||
-1
@@ -11,7 +11,6 @@ class A : B, C {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: constructor B(x: String) defined in B
|
||||
Resulting descriptor: constructor B(x: String) defined in B
|
||||
|
||||
Explicit receiver kind = NO_EXPLICIT_RECEIVER
|
||||
|
||||
@@ -6,7 +6,6 @@ class A(x: Int) {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: constructor A(x: Int) defined in A
|
||||
Resulting descriptor: constructor A(x: Int) defined in A
|
||||
|
||||
Explicit receiver kind = NO_EXPLICIT_RECEIVER
|
||||
|
||||
@@ -7,7 +7,6 @@ class A {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: constructor A(x: Int) defined in A
|
||||
Resulting descriptor: constructor A(x: Int) defined in A
|
||||
|
||||
Explicit receiver kind = NO_EXPLICIT_RECEIVER
|
||||
|
||||
@@ -8,7 +8,6 @@ class A(x: Double) {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: constructor A(x: String) defined in A
|
||||
Resulting descriptor: constructor A(x: String) defined in A
|
||||
|
||||
Explicit receiver kind = NO_EXPLICIT_RECEIVER
|
||||
|
||||
@@ -10,7 +10,6 @@ class A : B {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: constructor B(vararg x: Int) defined in B
|
||||
Resulting descriptor: constructor B(vararg x: Int) defined in B
|
||||
|
||||
Explicit receiver kind = NO_EXPLICIT_RECEIVER
|
||||
|
||||
@@ -7,7 +7,6 @@ fun test() {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: fun foo(f: (Int) -> String): Unit defined in root package
|
||||
Resulting descriptor: fun foo(f: (Int) -> String): Unit defined in root package
|
||||
|
||||
Explicit receiver kind = NO_EXPLICIT_RECEIVER
|
||||
|
||||
@@ -5,7 +5,6 @@ annotation class MyA(val i: Int)
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: constructor MyA(i: Int) defined in MyA
|
||||
Resulting descriptor: constructor MyA(i: Int) defined in MyA
|
||||
|
||||
Explicit receiver kind = NO_EXPLICIT_RECEIVER
|
||||
|
||||
-1
@@ -5,7 +5,6 @@ class B: <caret>A() {}
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: constructor A() defined in A
|
||||
Resulting descriptor: constructor A() defined in A
|
||||
|
||||
Explicit receiver kind = NO_EXPLICIT_RECEIVER
|
||||
|
||||
@@ -5,7 +5,6 @@ fun foo(array: Array<Int>) {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: operator fun get(index: Int): Int defined in kotlin.Array
|
||||
Resulting descriptor: operator fun get(index: Int): Int defined in kotlin.Array
|
||||
|
||||
Explicit receiver kind = DISPATCH_RECEIVER
|
||||
|
||||
-1
@@ -6,7 +6,6 @@ fun bar(f: Int.()->Unit) {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: operator fun Int.invoke(): Unit defined in kotlin.Function1
|
||||
Resulting descriptor: operator fun Int.invoke(): Unit defined in kotlin.Function1
|
||||
|
||||
Explicit receiver kind = BOTH_RECEIVERS
|
||||
|
||||
@@ -6,7 +6,6 @@ fun bar(f: ()->Unit) {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: operator fun invoke(): Unit defined in kotlin.Function0
|
||||
Resulting descriptor: operator fun invoke(): Unit defined in kotlin.Function0
|
||||
|
||||
Explicit receiver kind = DISPATCH_RECEIVER
|
||||
|
||||
-1
@@ -10,7 +10,6 @@ interface A {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: operator fun Int.invoke(): Unit defined in kotlin.Function1
|
||||
Resulting descriptor: operator fun Int.invoke(): Unit defined in kotlin.Function1
|
||||
|
||||
Explicit receiver kind = BOTH_RECEIVERS
|
||||
|
||||
@@ -9,7 +9,6 @@ fun test(a: A) {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: operator fun invoke(Int): Int defined in kotlin.Function1
|
||||
Resulting descriptor: operator fun invoke(Int): Int defined in kotlin.Function1
|
||||
|
||||
Explicit receiver kind = DISPATCH_RECEIVER
|
||||
|
||||
@@ -6,7 +6,6 @@ fun bar(f: Int.() -> Unit) {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: operator fun Int.invoke(): Unit defined in kotlin.Function1
|
||||
Resulting descriptor: operator fun Int.invoke(): Unit defined in kotlin.Function1
|
||||
|
||||
Explicit receiver kind = BOTH_RECEIVERS
|
||||
|
||||
@@ -8,7 +8,6 @@ fun bar(f: Int.() -> Unit, i: Int) {
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: operator fun Int.invoke(): Unit defined in kotlin.Function1
|
||||
Resulting descriptor: operator fun Int.invoke(): Unit defined in kotlin.Function1
|
||||
|
||||
Explicit receiver kind = DISPATCH_RECEIVER
|
||||
|
||||
@@ -9,7 +9,6 @@ fun test() = A<caret>(1)
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: fun invoke(i: Int): Int defined in A.Companion
|
||||
Resulting descriptor: fun invoke(i: Int): Int defined in A.Companion
|
||||
|
||||
Explicit receiver kind = DISPATCH_RECEIVER
|
||||
|
||||
@@ -10,7 +10,6 @@ fun test() = A.ONE<caret>(1)
|
||||
|
||||
Resolved call:
|
||||
|
||||
Candidate descriptor: fun invoke(i: Int): Int defined in A
|
||||
Resulting descriptor: fun invoke(i: Int): Int defined in A
|
||||
|
||||
Explicit receiver kind = DISPATCH_RECEIVER
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user