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

^KT-47797 Fixed
^KT-47987 Fixed
^KT-45034 Fixed
^KT-48446 Fixed
^KT-13934 Fixed
This commit is contained in:
Victor Petukhov
2021-09-20 17:13:17 +03:00
parent ca13aea26a
commit ee728b6902
115 changed files with 1239 additions and 1325 deletions
@@ -2813,12 +2813,6 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/callableReference/referenceAdaptationCompatibility.kt"); 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 @Test
@TestMetadata("referenceToCompanionObjectMemberViaClassName.kt") @TestMetadata("referenceToCompanionObjectMemberViaClassName.kt")
public void testReferenceToCompanionObjectMemberViaClassName() throws Exception { public void testReferenceToCompanionObjectMemberViaClassName() throws Exception {
@@ -2813,12 +2813,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/callableReference/referenceAdaptationCompatibility.kt"); 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 @Test
@TestMetadata("referenceToCompanionObjectMemberViaClassName.kt") @TestMetadata("referenceToCompanionObjectMemberViaClassName.kt")
public void testReferenceToCompanionObjectMemberViaClassName() throws Exception { public void testReferenceToCompanionObjectMemberViaClassName() throws Exception {
@@ -2813,12 +2813,6 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/callableReference/referenceAdaptationCompatibility.kt"); 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 @Test
@TestMetadata("referenceToCompanionObjectMemberViaClassName.kt") @TestMetadata("referenceToCompanionObjectMemberViaClassName.kt")
public void testReferenceToCompanionObjectMemberViaClassName() throws Exception { public void testReferenceToCompanionObjectMemberViaClassName() throws Exception {
@@ -20,16 +20,23 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.diagnostics.Errors.CALLABLE_REFERENCE_TO_JAVA_SYNTHETIC_PROPERTY import org.jetbrains.kotlin.diagnostics.Errors.CALLABLE_REFERENCE_TO_JAVA_SYNTHETIC_PROPERTY
import org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED 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.CallChecker
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.util.extractCallableReferenceExpression
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
class UnsupportedSyntheticCallableReferenceChecker : CallChecker { class UnsupportedSyntheticCallableReferenceChecker : CallChecker {
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
// TODO: support references to synthetic Java extension properties (KT-8575) // 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 ( val diagnostic = if (
context.languageVersionSettings.supportsFeature(LanguageFeature.NewInference) && context.languageVersionSettings.supportsFeature(LanguageFeature.NewInference) &&
context.languageVersionSettings.supportsFeature(LanguageFeature.ReferencesToSyntheticJavaProperties) context.languageVersionSettings.supportsFeature(LanguageFeature.ReferencesToSyntheticJavaProperties)
@@ -156,16 +156,16 @@ class DiagnosticReporterByTrackingStrategy(
MixingNamedAndPositionArguments::class.java -> MixingNamedAndPositionArguments::class.java ->
trace.report(MIXING_NAMED_AND_POSITIONED_ARGUMENTS.on(callArgument.psiCallArgument.valueArgument.asElement())) trace.report(MIXING_NAMED_AND_POSITIONED_ARGUMENTS.on(callArgument.psiCallArgument.valueArgument.asElement()))
NoneCallableReferenceCandidates::class.java -> { NoneCallableReferenceCallCandidates::class.java -> {
val expression = diagnostic.cast<NoneCallableReferenceCandidates>() val expression = diagnostic.cast<NoneCallableReferenceCallCandidates>()
.argument.safeAs<CallableReferenceKotlinCallArgumentImpl>()?.ktCallableReferenceExpression .argument.safeAs<CallableReferenceKotlinCallArgumentImpl>()?.ktCallableReferenceExpression
if (expression != null) { if (expression != null) {
trace.report(UNRESOLVED_REFERENCE.on(expression.callableReference, expression.callableReference)) trace.report(UNRESOLVED_REFERENCE.on(expression.callableReference, expression.callableReference))
} }
} }
CallableReferenceCandidatesAmbiguity::class.java -> { CallableReferenceCallCandidatesAmbiguity::class.java -> {
val ambiguityDiagnostic = diagnostic as CallableReferenceCandidatesAmbiguity val ambiguityDiagnostic = diagnostic as CallableReferenceCallCandidatesAmbiguity
val expression = when (val psiExpression = ambiguityDiagnostic.argument.psiExpression) { val expression = when (val psiExpression = ambiguityDiagnostic.argument.psiExpression) {
is KtPsiUtil.KtExpressionWrapper -> psiExpression.baseExpression is KtPsiUtil.KtExpressionWrapper -> psiExpression.baseExpression
else -> psiExpression else -> psiExpression
@@ -197,14 +197,18 @@ class DiagnosticReporterByTrackingStrategy(
"diagnostic ($diagnostic) should have type CallableReferencesDefaultArgumentUsed" "diagnostic ($diagnostic) should have type CallableReferencesDefaultArgumentUsed"
} }
diagnostic.argument.psiExpression?.let { val callableReferenceExpression = diagnostic.argument.call.extractCallableReferenceExpression()
trace.report(
UNSUPPORTED_FEATURE.on( require(callableReferenceExpression != null) {
it, LanguageFeature.FunctionReferenceWithDefaultValueAsOtherType to context.languageVersionSettings "A call element must be callable reference for `CallableReferencesDefaultArgumentUsed`"
)
)
} }
trace.report(
UNSUPPORTED_FEATURE.on(
callableReferenceExpression,
LanguageFeature.FunctionReferenceWithDefaultValueAsOtherType to context.languageVersionSettings
)
)
} }
ResolvedToSamWithVarargDiagnostic::class.java -> { 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) { 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 = val argument =
when (position) { when (position) {
is ArgumentConstraintPositionImpl -> position.argument is ArgumentConstraintPositionImpl -> position.argument
@@ -20,15 +20,21 @@ import org.jetbrains.kotlin.psi.psiUtil.getBinaryWithTypeParent
import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver 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.*
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.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter 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.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory 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.calls.util.CallMaker
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
@@ -71,7 +77,8 @@ class KotlinResolutionCallbacksImpl(
private val deprecationResolver: DeprecationResolver, private val deprecationResolver: DeprecationResolver,
private val moduleDescriptor: ModuleDescriptor, private val moduleDescriptor: ModuleDescriptor,
private val topLevelCallContext: BasicCallResolutionContext, private val topLevelCallContext: BasicCallResolutionContext,
private val missingSupertypesResolver: MissingSupertypesResolver private val missingSupertypesResolver: MissingSupertypesResolver,
private val kotlinCallResolver: KotlinCallResolver,
) : KotlinResolutionCallbacks { ) : KotlinResolutionCallbacks {
class LambdaInfo(val expectedType: UnwrappedType, val contextDependency: ContextDependency) { class LambdaInfo(val expectedType: UnwrappedType, val contextDependency: ContextDependency) {
val returnStatements = ArrayList<Pair<KtReturnExpression, LambdaContextInfo?>>() 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( override fun analyzeAndGetLambdaReturnArguments(
lambdaArgument: LambdaKotlinCallArgument, lambdaArgument: LambdaKotlinCallArgument,
isSuspend: Boolean, isSuspend: Boolean,
@@ -113,21 +133,22 @@ class KotlinResolutionCallbacksImpl(
} }
val deparenthesizedExpression = KtPsiUtil.deparenthesize(ktExpression) ?: ktExpression val deparenthesizedExpression = KtPsiUtil.deparenthesize(ktExpression) ?: ktExpression
if (deparenthesizedExpression is KtCallableReferenceExpression) {
return psiCallResolver.createCallableReferenceKotlinCallArgument( return if (deparenthesizedExpression is KtCallableReferenceExpression) {
psiCallResolver.createCallableReferenceKotlinCallArgument(
newContext, deparenthesizedExpression, DataFlowInfo.EMPTY, newContext, deparenthesizedExpression, DataFlowInfo.EMPTY,
CallMaker.makeExternalValueArgument(deparenthesizedExpression), CallMaker.makeExternalValueArgument(deparenthesizedExpression),
argumentName = null, argumentName = null,
outerCallContext, outerCallContext,
tracingStrategy = TracingStrategyImpl.create(deparenthesizedExpression.callableReference, newContext.call) 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( val lambdaInfo = LambdaInfo(
@@ -213,7 +213,10 @@ class KotlinToResolvedCallTransformer(
return if (completedSimpleAtom.atom.callKind == KotlinCallKind.CALLABLE_REFERENCE) { return if (completedSimpleAtom.atom.callKind == KotlinCallKind.CALLABLE_REFERENCE) {
NewCallableReferenceResolvedCall( NewCallableReferenceResolvedCall(
completedSimpleAtom as ResolvedCallableReferenceCallAtom, typeApproximator, resultSubstitutor completedSimpleAtom as ResolvedCallableReferenceCallAtom,
typeApproximator,
expressionTypingServices.languageVersionSettings,
resultSubstitutor
) )
} else { } else {
NewResolvedCallImpl( NewResolvedCallImpl(
@@ -384,7 +387,7 @@ class KotlinToResolvedCallTransformer(
) )
} }
private fun getResolvedCallForArgumentExpression(expression: KtExpression, context: BasicCallResolutionContext) = fun getResolvedCallForArgumentExpression(expression: KtExpression, context: BasicCallResolutionContext) =
if (!ExpressionTypingUtils.dependsOnExpectedType(expression)) if (!ExpressionTypingUtils.dependsOnExpectedType(expression))
null null
else else
@@ -486,7 +489,7 @@ class KotlinToResolvedCallTransformer(
outerTracingStrategy.bindReference(trace, variableCall) outerTracingStrategy.bindReference(trace, variableCall)
outerTracingStrategy.bindResolvedCall(trace, variableAsFunction) outerTracingStrategy.bindResolvedCall(trace, variableAsFunction)
functionCall.kotlinCall.psiKotlinCall.tracingStrategy.bindReference(trace, functionCall) functionCall.psiKotlinCall.tracingStrategy.bindReference(trace, functionCall)
} }
fun reportCallDiagnostic( fun reportCallDiagnostic(
@@ -7,54 +7,68 @@ package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
import org.jetbrains.kotlin.psi.Call import org.jetbrains.kotlin.psi.Call
import org.jetbrains.kotlin.psi.ValueArgument import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.calls.components.isVararg 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.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.model.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo 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.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.compactIfPossible import org.jetbrains.kotlin.utils.addToStdlib.compactIfPossible
sealed class NewAbstractResolvedCall<D : CallableDescriptor> : ResolvedCall<D> { sealed class NewAbstractResolvedCall<D : CallableDescriptor> : ResolvedCall<D> {
abstract val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument> abstract val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
abstract val kotlinCall: KotlinCall abstract val kotlinCall: KotlinCall?
abstract val languageVersionSettings: LanguageVersionSettings abstract val languageVersionSettings: LanguageVersionSettings
abstract val resolvedCallAtom: ResolvedCallAtom? abstract val resolvedCallAtom: ResolvedCallAtom?
abstract val psiKotlinCall: PSIKotlinCall abstract val psiKotlinCall: PSIKotlinCall
abstract val isCompleted: Boolean abstract val typeApproximator: TypeApproximator
abstract val freshSubstitutor: FreshVariableNewTypeSubstitutor?
protected var argumentToParameterMap: Map<ValueArgument, ArgumentMatchImpl>? = null protected open val positionDependentApproximation = false
protected var _valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>? = null
private var argumentToParameterMap: Map<ValueArgument, ArgumentMatchImpl>? = null
private var valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>? = null
private var nonTrivialUpdatedResultInfo: DataFlowInfo? = 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 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> { override fun getValueArguments(): Map<ValueParameterDescriptor, ResolvedValueArgument> {
if (_valueArguments == null) { if (valueArguments == null) {
_valueArguments = createValueArguments() valueArguments = createValueArguments()
} }
return _valueArguments!! return valueArguments!!
} }
fun setValueArguments(m: Map<ValueParameterDescriptor, ResolvedValueArgument>) {
_valueArguments = m
}
open fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?) {}
override fun getValueArgumentsByIndex(): List<ResolvedValueArgument>? { override fun getValueArgumentsByIndex(): List<ResolvedValueArgument>? {
val arguments = ArrayList<ResolvedValueArgument?>(candidateDescriptor.valueParameters.size) val arguments = ArrayList<ResolvedValueArgument?>(candidateDescriptor.valueParameters.size)
for (i in 0 until candidateDescriptor.valueParameters.size) { for (i in 0 until candidateDescriptor.valueParameters.size) {
arguments.add(null) arguments.add(null)
} }
for ((parameterDescriptor, value) in valueArguments) { for ((parameterDescriptor, value) in getValueArguments()) {
val oldValue = arguments.set(parameterDescriptor.index, value) val oldValue = arguments.set(parameterDescriptor.index, value)
if (oldValue != null) { if (oldValue != null) {
return null return null
@@ -69,36 +83,121 @@ sealed class NewAbstractResolvedCall<D : CallableDescriptor> : ResolvedCall<D> {
override fun getArgumentMapping(valueArgument: ValueArgument): ArgumentMapping { override fun getArgumentMapping(valueArgument: ValueArgument): ArgumentMapping {
if (argumentToParameterMap == null) { if (argumentToParameterMap == null) {
argumentToParameterMap = argumentToParameterMap(resultingDescriptor, valueArguments) updateArgumentsMapping(argumentToParameterMap(resultingDescriptor, getValueArguments()))
} }
return argumentToParameterMap!![valueArgument] ?: ArgumentUnmapped return argumentToParameterMap!![valueArgument] ?: ArgumentUnmapped
} }
override fun getDataFlowInfoForArguments() = object : DataFlowInfoForArguments { 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 { override fun getInfo(valueArgument: ValueArgument): DataFlowInfo {
val externalPsiCallArgument = kotlinCall.externalArgument?.psiCallArgument val externalPsiCallArgument = kotlinCall?.externalArgument?.psiCallArgument
if (externalPsiCallArgument?.valueArgument == valueArgument) { if (externalPsiCallArgument?.valueArgument == valueArgument) {
return externalPsiCallArgument.dataFlowInfoAfterThisArgument 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 // Currently, updated only with info from effect system
internal fun updateResultingDataFlowInfo(dataFlowInfo: DataFlowInfo) { internal fun updateResultingDataFlowInfo(dataFlowInfo: DataFlowInfo) {
if (dataFlowInfo == DataFlowInfo.EMPTY) return if (dataFlowInfo == DataFlowInfo.EMPTY) return
assert(nonTrivialUpdatedResultInfo == null) { assert(nonTrivialUpdatedResultInfo == null) {
"Attempt to rewrite resulting dataFlowInfo enhancement for call: $kotlinCall" "Attempt to rewrite resulting dataFlowInfo enhancement for call: $kotlinCall"
} }
nonTrivialUpdatedResultInfo = dataFlowInfo.and(kotlinCall.psiKotlinCall.resultDataFlowInfo) nonTrivialUpdatedResultInfo = dataFlowInfo.and(psiKotlinCall.resultDataFlowInfo)
} }
abstract fun argumentToParameterMap( protected fun updateArgumentsMapping(newMapping: Map<ValueArgument, ArgumentMatchImpl>?) {
resultingDescriptor: CallableDescriptor, argumentToParameterMap = newMapping
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>, }
): Map<ValueArgument, ArgumentMatchImpl>
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> = private fun createValueArguments(): Map<ValueParameterDescriptor, ResolvedValueArgument> =
LinkedHashMap<ValueParameterDescriptor, ResolvedValueArgument>().also { result -> LinkedHashMap<ValueParameterDescriptor, ResolvedValueArgument>().also { result ->
@@ -325,7 +325,10 @@ internal fun createSimplePSICallArgument(
call: Call call: Call
): SimplePSIKotlinCallArgument? { ): SimplePSIKotlinCallArgument? {
val ktExpression = KtPsiUtil.getLastElementDeparenthesized(valueArgument.getArgumentExpression(), statementFilter) ?: return null 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 bindingContext.get(BindingContext.ONLY_RESOLVED_CALL, it)?.result
} }
// todo hack for if expression: sometimes we not write properly type information for branches // todo hack for if expression: sometimes we not write properly type information for branches
@@ -7,61 +7,53 @@ package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
import org.jetbrains.kotlin.psi.ValueArgument import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor 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.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.model.*
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind 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.calls.util.toResolutionStatus
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.makeNullable
class NewCallableReferenceResolvedCall<D : CallableDescriptor>( class NewCallableReferenceResolvedCall<D : CallableDescriptor>(
val resolvedAtom: ResolvedCallableReferenceAtom, val resolvedAtom: ResolvedCallableReferenceAtom,
val typeApproximator: TypeApproximator, override val typeApproximator: TypeApproximator,
substitutor: NewTypeSubstitutor?, override val languageVersionSettings: LanguageVersionSettings,
substitutor: NewTypeSubstitutor? = null,
) : NewAbstractResolvedCall<D>() { ) : NewAbstractResolvedCall<D>() {
override var isCompleted = false override val positionDependentApproximation: Boolean = true
private set override val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument> = emptyMap()
override val resolvedCallAtom: MutableResolvedCallAtom? = when (resolvedAtom) { override val resolvedCallAtom: ResolvedCallableReferenceCallAtom?
is ResolvedCallableReferenceCallAtom -> resolvedAtom get() = when (resolvedAtom) {
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate?.resolvedCall is ResolvedCallableReferenceCallAtom -> resolvedAtom
} is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate?.resolvedCall
}
override val psiKotlinCall: PSIKotlinCall = when (resolvedAtom) { override val psiKotlinCall: PSIKotlinCall =
is ResolvedCallableReferenceCallAtom -> resolvedAtom.atom.psiKotlinCall when (resolvedAtom) {
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.atom.call.psiKotlinCall is ResolvedCallableReferenceCallAtom -> resolvedAtom.atom.psiKotlinCall
} is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.atom.call.psiKotlinCall
}
init { override val freshSubstitutor: FreshVariableNewTypeSubstitutor?
setResultingSubstitutor(substitutor) 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 resultingDescriptor: D
private lateinit var typeArguments: List<UnwrappedType>
override fun getStatus(): ResolutionStatus { private var extensionReceiver: ReceiverValue? = when (resolvedAtom) {
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) {
is ResolvedCallableReferenceCallAtom -> resolvedAtom.extensionReceiverArgument?.receiverValue is ResolvedCallableReferenceCallAtom -> resolvedAtom.extensionReceiverArgument?.receiverValue
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate?.extensionReceiver?.receiver?.receiverValue is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate?.extensionReceiver?.receiver?.receiverValue
} }
@@ -72,35 +64,25 @@ class NewCallableReferenceResolvedCall<D : CallableDescriptor>(
} }
override fun getExtensionReceiver(): ReceiverValue? = extensionReceiver override fun getExtensionReceiver(): ReceiverValue? = extensionReceiver
override fun getDispatchReceiver(): ReceiverValue? = dispatchReceiver override fun getDispatchReceiver(): ReceiverValue? = dispatchReceiver
override fun getExplicitReceiverKind(): ExplicitReceiverKind = when (resolvedAtom) { override fun updateDispatchReceiverType(newType: KotlinType) {
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate!!.explicitReceiverKind if (dispatchReceiver?.type == newType) return
is ResolvedCallableReferenceCallAtom -> resolvedAtom.explicitReceiverKind dispatchReceiver = dispatchReceiver?.replaceType(newType)
} }
override fun getValueArguments(): Map<ValueParameterDescriptor, ResolvedValueArgument> = _valueArguments ?: emptyMap() override fun updateExtensionReceiverType(newType: KotlinType) {
if (extensionReceiver?.type == newType) return
override fun getValueArgumentsByIndex(): List<ResolvedValueArgument>? { extensionReceiver = extensionReceiver?.replaceType(newType)
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>
} }
@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 getArgumentMapping(valueArgument: ValueArgument): ArgumentMapping = ArgumentUnmapped
override fun getTypeArguments(): Map<TypeParameterDescriptor, KotlinType> { override fun getTypeArguments(): Map<TypeParameterDescriptor, KotlinType> {
@@ -108,150 +90,42 @@ class NewCallableReferenceResolvedCall<D : CallableDescriptor>(
return typeParameters.zip(typeArguments).toMap() 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 = override fun getDataFlowInfoForArguments(): DataFlowInfoForArguments =
MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY) MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY)
override fun getSmartCastDispatchReceiverType(): KotlinType? = null 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?) { override fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?) {
//clear cached values substituteReceivers(substitutor)
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)
}
}
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
resultingDescriptor = substitutedResultingDescriptor(substitutor) as D resultingDescriptor = substitutedResultingDescriptor(substitutor) as D
val sub = when (resolvedAtom) { freshSubstitutor?.let { freshSubstitutor ->
is ResolvedCallableReferenceCallAtom -> resolvedAtom.freshVariablesSubstitutor typeArguments = freshSubstitutor.freshVariables.map {
is ResolvedCallableReferenceArgumentAtom -> resolvedAtom.candidate!!.freshVariablesSubstitutor!! val substituted = (substitutor ?: FreshVariableNewTypeSubstitutor.Empty).safeSubstitute(it.defaultType)
} typeApproximator.approximateToSuperType(substituted, TypeApproximatorConfiguration.IntegerLiteralsTypesApproximation)
?: substituted
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),
)
} }
is FunctionDescriptor -> {
candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor, candidateDescriptor.isNotSimpleCall())
}
is PropertyDescriptor -> {
if (candidateDescriptor.isNotSimpleCall()) {
candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor)
} else {
candidateDescriptor
}
}
else -> candidateDescriptor
} }
} }
private fun CallableDescriptor.substituteInferredVariablesAndApproximate( override fun containsOnlyOnlyInputTypesErrors(): Boolean = false
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 argumentToParameterMap( override fun argumentToParameterMap(
resultingDescriptor: CallableDescriptor, resultingDescriptor: CallableDescriptor,
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>
): Map<ValueArgument, ArgumentMatchImpl> { ): Map<ValueArgument, ArgumentMatchImpl> = emptyMap()
TODO("Not yet implemented")
init {
setResultingSubstitutor(substitutor)
} }
} }
@@ -7,67 +7,68 @@ package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.ValueArgument import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor 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.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.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.model.*
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind 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.calls.util.toResolutionStatus
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.* 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 import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class NewResolvedCallImpl<D : CallableDescriptor>( class NewResolvedCallImpl<D : CallableDescriptor>(
override val resolvedCallAtom: ResolvedCallAtom, override val resolvedCallAtom: ResolvedCallAtom,
substitutor: NewTypeSubstitutor?, substitutor: NewTypeSubstitutor?,
private var diagnostics: Collection<KotlinCallDiagnostic>, private var diagnostics: Collection<KotlinCallDiagnostic>,
private val typeApproximator: TypeApproximator, override val typeApproximator: TypeApproximator,
override val languageVersionSettings: LanguageVersionSettings, override val languageVersionSettings: LanguageVersionSettings,
) : NewAbstractResolvedCall<D>() { ) : NewAbstractResolvedCall<D>() {
override val psiKotlinCall: PSIKotlinCall = resolvedCallAtom.atom.psiKotlinCall override val psiKotlinCall: PSIKotlinCall = resolvedCallAtom.atom.psiKotlinCall
override val kotlinCall: KotlinCall = resolvedCallAtom.atom
override var isCompleted = false override val freshSubstitutor: FreshVariableNewTypeSubstitutor
private set get() = resolvedCallAtom.freshVariablesSubstitutor
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 argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument> override val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
get() = resolvedCallAtom.argumentMappingByOriginal 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") @Suppress("UNCHECKED_CAST")
override fun getCandidateDescriptor(): D = resolvedCallAtom.candidateDescriptor as D override fun getCandidateDescriptor(): D = resolvedCallAtom.candidateDescriptor as D
override fun getResultingDescriptor(): D = resultingDescriptor override fun getResultingDescriptor(): D = resultingDescriptor
override fun getExtensionReceiver(): ReceiverValue? = extensionReceiver
override fun getDispatchReceiver(): ReceiverValue? = dispatchReceiver
override fun getExplicitReceiverKind(): ExplicitReceiverKind = resolvedCallAtom.explicitReceiverKind 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> { override fun getTypeArguments(): Map<TypeParameterDescriptor, KotlinType> {
val typeParameters = candidateDescriptor.typeParameters.takeIf { it.isNotEmpty() } ?: return emptyMap() val typeParameters = candidateDescriptor.typeParameters.takeIf { it.isNotEmpty() } ?: return emptyMap()
return typeParameters.zip(typeArguments).toMap() return typeParameters.zip(typeArguments).toMap()
@@ -78,56 +79,17 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
override fun getSmartCastDispatchReceiverType(): KotlinType? = smartCastDispatchReceiverType 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?) { override fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?) {
//clear cached values //clear cached values
argumentToParameterMap = null updateArgumentsMapping(null)
_valueArguments = null updateValueArguments(null)
if (substitutor != null) {
// todo: add asset that we do not complete call many times
isCompleted = true
dispatchReceiver?.type?.let { substituteReceivers(substitutor)
val newType = substitutor.safeSubstitute(it.unwrap())
updateDispatchReceiverType(newType)
}
extensionReceiver?.type?.let {
val newType = substitutor.safeSubstitute(it.unwrap())
updateExtensionReceiverType(newType)
}
}
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
resultingDescriptor = substitutedResultingDescriptor(substitutor) as D resultingDescriptor = substitutedResultingDescriptor(substitutor) as D
typeArguments = resolvedCallAtom.freshVariablesSubstitutor.freshVariables.map { typeArguments = freshSubstitutor.freshVariables.map {
val substituted = (substitutor ?: FreshVariableNewTypeSubstitutor.Empty).safeSubstitute(it.defaultType) val substituted = (substitutor ?: FreshVariableNewTypeSubstitutor.Empty).safeSubstitute(it.defaultType)
typeApproximator typeApproximator
.approximateToSuperType(substituted, TypeApproximatorConfiguration.IntegerLiteralsTypesApproximation) .approximateToSuperType(substituted, TypeApproximatorConfiguration.IntegerLiteralsTypesApproximation)
@@ -140,126 +102,6 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
calculateExpectedTypeForConstantConvertedArgumentMap() 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( override fun argumentToParameterMap(
resultingDescriptor: CallableDescriptor, resultingDescriptor: CallableDescriptor,
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>, 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>> { private fun collectErrorPositions(): Map<ValueArgument, List<KotlinCallDiagnostic>> {
val result = mutableListOf<Pair<ValueArgument, KotlinCallDiagnostic>>() val result = mutableListOf<Pair<ValueArgument, KotlinCallDiagnostic>>()
@@ -5,21 +5,31 @@
package org.jetbrains.kotlin.resolve.calls.tower package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallAtom
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall 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 import org.jetbrains.kotlin.utils.addToStdlib.cast
class NewVariableAsFunctionResolvedCallImpl( class NewVariableAsFunctionResolvedCallImpl(
override val variableCall: NewAbstractResolvedCall<VariableDescriptor>, override val variableCall: NewAbstractResolvedCall<VariableDescriptor>,
override val functionCall: NewAbstractResolvedCall<FunctionDescriptor>, override val functionCall: NewAbstractResolvedCall<FunctionDescriptor>,
) : VariableAsFunctionResolvedCall, 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 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 getStatus() = functionCall.status
override fun getCandidateDescriptor() = functionCall.candidateDescriptor override fun getCandidateDescriptor() = functionCall.candidateDescriptor
override fun getResultingDescriptor() = functionCall.resultingDescriptor override fun getResultingDescriptor() = functionCall.resultingDescriptor
@@ -28,13 +38,16 @@ class NewVariableAsFunctionResolvedCallImpl(
override fun getExplicitReceiverKind() = functionCall.explicitReceiverKind override fun getExplicitReceiverKind() = functionCall.explicitReceiverKind
override fun getTypeArguments() = functionCall.typeArguments override fun getTypeArguments() = functionCall.typeArguments
override fun getSmartCastDispatchReceiverType() = functionCall.smartCastDispatchReceiverType 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 containsOnlyOnlyInputTypesErrors() = functionCall.containsOnlyOnlyInputTypesErrors()
override fun updateDispatchReceiverType(newType: KotlinType) = functionCall.updateDispatchReceiverType(newType)
override fun updateExtensionReceiverType(newType: KotlinType) = functionCall.updateExtensionReceiverType(newType)
override fun argumentToParameterMap( override fun argumentToParameterMap(
resultingDescriptor: CallableDescriptor, resultingDescriptor: CallableDescriptor,
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>
) = functionCall.argumentToParameterMap(resultingDescriptor, valueArguments) ) = 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( val defaultResolutionKinds = setOf(
NewResolutionOldInference.ResolutionKind.Function, NewResolutionOldInference.ResolutionKind.Function,
NewResolutionOldInference.ResolutionKind.Variable, NewResolutionOldInference.ResolutionKind.Variable,
NewResolutionOldInference.ResolutionKind.Invoke NewResolutionOldInference.ResolutionKind.Invoke,
NewResolutionOldInference.ResolutionKind.CallableReference
) )
fun <D : CallableDescriptor> runResolutionAndInference( fun <D : CallableDescriptor> runResolutionAndInference(
@@ -98,10 +99,9 @@ class PSICallResolver(
val resolutionCallbacks = createResolutionCallbacks(context) val resolutionCallbacks = createResolutionCallbacks(context)
val expectedType = calculateExpectedType(context) val expectedType = calculateExpectedType(context)
var result = var result = kotlinCallResolver.resolveAndCompleteCall(
kotlinCallResolver.resolveCall(scopeTower, resolutionCallbacks, kotlinCall, expectedType, context.collectAllCandidates) { scopeTower, resolutionCallbacks, kotlinCall, expectedType, context.collectAllCandidates
FactoryProviderForInvoke(context, scopeTower, kotlinCall) )
}
val shouldUseOperatorRem = languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem) val shouldUseOperatorRem = languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)
if (isBinaryRemOperator && shouldUseOperatorRem && (result.isEmpty() || result.areAllInapplicable())) { 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 scopeTower, resolutionCallbacks, kotlinCall, calculateExpectedType(context), givenCandidates, context.collectAllCandidates
) )
val overloadResolutionResults = convertToOverloadResolutionResults<D>(context, result, tracingStrategy) val overloadResolutionResults = convertToOverloadResolutionResults<D>(context, result, tracingStrategy)
@@ -169,11 +169,9 @@ class PSICallResolver(
val callWithDeprecatedName = toKotlinCall( val callWithDeprecatedName = toKotlinCall(
context, kotlinCallKind, context.call, deprecatedName, tracingStrategy, isSpecialFunction = false context, kotlinCallKind, context.call, deprecatedName, tracingStrategy, isSpecialFunction = false
) )
return kotlinCallResolver.resolveCall( return kotlinCallResolver.resolveAndCompleteCall(
scopeTower, resolutionCallbacks, callWithDeprecatedName, expectedType, context.collectAllCandidates scopeTower, resolutionCallbacks, callWithDeprecatedName, expectedType, context.collectAllCandidates
) { )
FactoryProviderForInvoke(context, scopeTower, callWithDeprecatedName)
}
} }
private fun refineNameForRemOperator(isBinaryRemOperator: Boolean, name: Name): Name { private fun refineNameForRemOperator(isBinaryRemOperator: Boolean, name: Name): Name {
@@ -190,17 +188,14 @@ class PSICallResolver(
argumentTypeResolver, languageVersionSettings, kotlinToResolvedCallTransformer, argumentTypeResolver, languageVersionSettings, kotlinToResolvedCallTransformer,
dataFlowValueFactory, inferenceSession, constantExpressionEvaluator, typeResolver, dataFlowValueFactory, inferenceSession, constantExpressionEvaluator, typeResolver,
this, postponedArgumentsAnalyzer, kotlinConstraintSystemCompleter, callComponents, this, postponedArgumentsAnalyzer, kotlinConstraintSystemCompleter, callComponents,
doubleColonExpressionResolver, deprecationResolver, moduleDescriptor, context, missingSupertypesResolver doubleColonExpressionResolver, deprecationResolver, moduleDescriptor, context, missingSupertypesResolver, kotlinCallResolver
) )
private fun calculateExpectedType(context: BasicCallResolutionContext): UnwrappedType? { private fun calculateExpectedType(context: BasicCallResolutionContext): UnwrappedType? {
val expectedType = context.expectedType.unwrap() val expectedType = context.expectedType.unwrap()
return if (context.contextDependency == ContextDependency.DEPENDENT) { return if (context.contextDependency == ContextDependency.DEPENDENT) {
assert(TypeUtils.noExpectedType(expectedType)) { if (TypeUtils.noExpectedType(expectedType)) null else expectedType
"Should have no expected type, got: $expectedType"
}
null
} else { } else {
if (expectedType.isError) TypeUtils.NO_EXPECTED_TYPE else expectedType if (expectedType.isError) TypeUtils.NO_EXPECTED_TYPE else expectedType
} }
@@ -282,7 +277,7 @@ class PSICallResolver(
): ManyCandidates<D> { ): ManyCandidates<D> {
val resolvedCalls = diagnostic.candidates.map { val resolvedCalls = diagnostic.candidates.map {
kotlinToResolvedCallTransformer.onlyTransform<D>( 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 context: BasicCallResolutionContext,
val scopeTower: ImplicitScopeTower, val scopeTower: ImplicitScopeTower,
val kotlinCall: PSIKotlinCallImpl val kotlinCall: PSIKotlinCallImpl
@@ -472,9 +467,7 @@ class PSICallResolver(
override fun factoryForVariable(stripExplicitReceiver: Boolean): CandidateFactory<ResolutionCandidate> { override fun factoryForVariable(stripExplicitReceiver: Boolean): CandidateFactory<ResolutionCandidate> {
val explicitReceiver = if (stripExplicitReceiver) null else kotlinCall.explicitReceiver val explicitReceiver = if (stripExplicitReceiver) null else kotlinCall.explicitReceiver
val variableCall = PSIKotlinCallForVariable(kotlinCall, explicitReceiver, kotlinCall.name) val variableCall = PSIKotlinCallForVariable(kotlinCall, explicitReceiver, kotlinCall.name)
return SimpleCandidateFactory( return SimpleCandidateFactory(callComponents, scopeTower, variableCall, createResolutionCallbacks(context))
callComponents, scopeTower, variableCall, createResolutionCallbacks(context), callableReferenceResolver
)
} }
override fun factoryForInvoke(variable: ResolutionCandidate, useExplicitReceiver: Boolean): override fun factoryForInvoke(variable: ResolutionCandidate, useExplicitReceiver: Boolean):
@@ -554,7 +547,7 @@ class PSICallResolver(
is NewResolutionOldInference.ResolutionKind.Function -> KotlinCallKind.FUNCTION is NewResolutionOldInference.ResolutionKind.Function -> KotlinCallKind.FUNCTION
is NewResolutionOldInference.ResolutionKind.Variable -> KotlinCallKind.VARIABLE is NewResolutionOldInference.ResolutionKind.Variable -> KotlinCallKind.VARIABLE
is NewResolutionOldInference.ResolutionKind.Invoke -> KotlinCallKind.INVOKE 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 is NewResolutionOldInference.ResolutionKind.GivenCandidates -> KotlinCallKind.UNSUPPORTED
} }
@@ -822,52 +815,22 @@ class PSICallResolver(
startDataFlowInfo: DataFlowInfo, startDataFlowInfo: DataFlowInfo,
valueArgument: ValueArgument, valueArgument: ValueArgument,
argumentName: Name?, argumentName: Name?,
outerCallContext: BasicCallResolutionContext outerCallContext: BasicCallResolutionContext,
tracingStrategy: TracingStrategy
): CallableReferenceKotlinCallArgumentImpl { ): CallableReferenceKotlinCallArgumentImpl {
checkNoSpread(outerCallContext, valueArgument) checkNoSpread(outerCallContext, valueArgument)
val expressionTypingContext = ExpressionTypingContext.newContext(context) val (doubleColonLhs, lhsResult) = getLhsResult(context, ktExpression)
val lhsResult = if (ktExpression.isEmptyLHS) null else doubleColonExpressionResolver.resolveDoubleColonLHS( val newDataFlowInfo = (doubleColonLhs as? DoubleColonLHS.Expression)?.dataFlowInfo ?: startDataFlowInfo
ktExpression, val rhsExpression = ktExpression.callableReference
expressionTypingContext val rhsName = rhsExpression.getReferencedNameAsName()
) val call = outerCallContext.trace[BindingContext.CALL, rhsExpression]
val newDataFlowInfo = (lhsResult as? DoubleColonLHS.Expression)?.dataFlowInfo ?: startDataFlowInfo ?: CallMaker.makeCall(rhsExpression, null, null, rhsExpression, emptyList())
val name = ktExpression.callableReference.getReferencedNameAsName() val kotlinCall = toKotlinCall(context, KotlinCallKind.CALLABLE_REFERENCE, call, rhsName, tracingStrategy, isSpecialFunction = false)
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())
}
}
}
return CallableReferenceKotlinCallArgumentImpl( return CallableReferenceKotlinCallArgumentImpl(
ASTScopeTower(context, ktExpression.callableReference), valueArgument, startDataFlowInfo, newDataFlowInfo, ASTScopeTower(context, rhsExpression), valueArgument, startDataFlowInfo,
ktExpression, argumentName, lhsNewResult, name newDataFlowInfo, ktExpression, argumentName, lhsResult, rhsName, kotlinCall
) )
} }
@@ -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.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession 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.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
import org.jetbrains.kotlin.resolve.calls.model.* 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.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategyImpl import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategyImpl
import org.jetbrains.kotlin.resolve.calls.util.CallMaker 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.checkers.MissingDependencySupertypeChecker
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
@@ -68,7 +71,7 @@ class ResolvedAtomCompleter(
val dispatchReceiver: ReceiverValue?, val dispatchReceiver: ReceiverValue?,
val extensionReceiver: ReceiverValue?, val extensionReceiver: ReceiverValue?,
val explicitReceiver: ReceiverValue?, val explicitReceiver: ReceiverValue?,
val substitutor: TypeSubstitutor, val substitutor: NewTypeSubstitutor,
val resultType: KotlinType val resultType: KotlinType
) )
@@ -109,18 +112,32 @@ class ResolvedAtomCompleter(
complete(resolvedAtom) complete(resolvedAtom)
} }
fun completeSubCallArgument(resolvedSubCallArgument: ResolvedSubCallArgument) { private fun completeSubCallArgument(resolvedSubCallArgument: ResolvedSubCallArgument) {
val contextWithoutExpectedType = topLevelCallContext.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE) val deparenthesizedExpression =
kotlinToResolvedCallTransformer.updateRecordedType( KtPsiUtil.getLastElementDeparenthesized(resolvedSubCallArgument.atom.psiExpression, topLevelCallContext.statementFilter)
resolvedSubCallArgument.atom.psiExpression ?: return,
parameter = null, if (deparenthesizedExpression is KtCallableReferenceExpression) {
context = contextWithoutExpectedType, val callableReferenceResolvedCall = kotlinToResolvedCallTransformer.getResolvedCallForArgumentExpression(
reportErrorForTypeMismatch = true, deparenthesizedExpression.callableReference, topLevelCallContext
convertedArgumentType = null ) 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) val diagnosticsFromPartiallyResolvedCall = extractDiagnosticsFromPartiallyResolvedCall(resolvedCallAtom)
clearPartiallyResolvedCall(resolvedCallAtom) clearPartiallyResolvedCall(resolvedCallAtom)
@@ -137,9 +154,11 @@ class ResolvedAtomCompleter(
allDiagnostics 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)) { if (ErrorUtils.isError(resolvedCall.candidateDescriptor)) {
kotlinToResolvedCallTransformer.runArgumentsChecks(topLevelCallContext, lastCall as NewResolvedCallImpl<*>) kotlinToResolvedCallTransformer.runArgumentsChecks(topLevelCallContext, lastCall)
checkMissingReceiverSupertypes(resolvedCall, missingSupertypesResolver, topLevelTrace) checkMissingReceiverSupertypes(resolvedCall, missingSupertypesResolver, topLevelTrace)
return resolvedCall return resolvedCall
} }
@@ -173,7 +192,7 @@ class ResolvedAtomCompleter(
kotlinToResolvedCallTransformer.bind(topLevelTrace, resolvedCall) kotlinToResolvedCallTransformer.bind(topLevelTrace, resolvedCall)
kotlinToResolvedCallTransformer.runArgumentsChecks(topLevelCallContext, lastCall as NewResolvedCallImpl<*>) kotlinToResolvedCallTransformer.runArgumentsChecks(topLevelCallContext, lastCall)
kotlinToResolvedCallTransformer.runCallCheckers(resolvedCall, callCheckerContext) kotlinToResolvedCallTransformer.runCallCheckers(resolvedCall, callCheckerContext)
kotlinToResolvedCallTransformer.runAdditionalReceiversCheckers(resolvedCall, topLevelCallContext) kotlinToResolvedCallTransformer.runAdditionalReceiversCheckers(resolvedCall, topLevelCallContext)
@@ -340,25 +359,20 @@ class ResolvedAtomCompleter(
} }
} }
private fun updateCallableReferenceResultType( private fun updateCallableReferenceResultType(callableCandidate: CallableReferenceResolutionCandidate): CallableReferenceResultTypeInfo? {
callableCandidate: CallableReferenceCandidate, val callableReferenceExpression =
callableReferenceExpression: KtCallableReferenceExpression callableCandidate.resolvedCall.atom.psiKotlinCall.psiCall.callElement.parent as? KtCallableReferenceExpression ?: return null
): CallableReferenceResultTypeInfo { val freshSubstitutor = callableCandidate.freshVariablesSubstitutor ?: return null
val resultTypeParameters = val resultTypeParameters = freshSubstitutor.freshVariables.map { resultSubstitutor.safeSubstitute(it.defaultType) }
callableCandidate.freshSubstitutor!!.freshVariables.map { resultSubstitutor.safeSubstitute(it.defaultType) }
val typeParametersSubstitutor = NewTypeSubstitutorByConstructorMap( 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 resultSubstitutor = if (callableCandidate.candidate.isSupportedForCallableReference()) {
val firstSubstitution = typeParametersSubstitutor.toOldSubstitution() ComposedSubstitutor(typeParametersSubstitutor, resultSubstitutor)
val secondSubstitution = resultSubstitutor.toOldSubstitution() } else EmptySubstitutor
TypeSubstitutor.createChainedSubstitutor(firstSubstitution, secondSubstitution)
} else TypeSubstitutor.EMPTY
// write down type for callable reference expression // write down type for callable reference expression
val resultType = resultSubstitutor.safeSubstitute(callableCandidate.reflectionCandidateType, Variance.INVARIANT) val resultType = resultSubstitutor.safeSubstitute(callableCandidate.reflectionCandidateType)
argumentTypeResolver.updateResultArgumentTypeIfNotDenotable( argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(
topLevelTrace, expressionTypingServices.statementFilter, resultType, callableReferenceExpression topLevelTrace, expressionTypingServices.statementFilter, resultType, callableReferenceExpression
@@ -415,7 +429,7 @@ class ResolvedAtomCompleter(
dispatchReceiver, dispatchReceiver,
extensionReceiver, extensionReceiver,
explicitCallableReceiver, explicitCallableReceiver,
TypeSubstitutor.EMPTY, EmptySubstitutor,
callableCandidate.reflectionCandidateType.replaceFunctionTypeArgumentsByDescriptor(recordedDescriptor) callableCandidate.reflectionCandidateType.replaceFunctionTypeArgumentsByDescriptor(recordedDescriptor)
) )
} }
@@ -437,79 +451,106 @@ class ResolvedAtomCompleter(
else -> this 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 psiCallArgument = resolvedAtom.atom.psiCallArgument as CallableReferenceKotlinCallArgumentImpl
val callableReferenceExpression = psiCallArgument.ktCallableReferenceExpression val callableReferenceCallCandidate = resolvedAtom.candidate ?: return null
val callableCandidate = resolvedAtom.candidate val descriptor = when (callableReferenceCallCandidate.candidate) {
if (callableCandidate == null || resolvedAtom.completed) { is FunctionDescriptor -> topLevelCallContext.trace.get(BindingContext.FUNCTION, psiCallArgument.ktCallableReferenceExpression)
// todo report meanfull diagnostic here is PropertyDescriptor -> topLevelCallContext.trace.get(BindingContext.VARIABLE, psiCallArgument.ktCallableReferenceExpression)
return
}
val recorderDescriptor = when (callableCandidate.candidate) {
is FunctionDescriptor -> topLevelCallContext.trace.get(BindingContext.FUNCTION, callableReferenceExpression)
is PropertyDescriptor -> topLevelCallContext.trace.get(BindingContext.VARIABLE, callableReferenceExpression)
else -> null 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 rawExtensionReceiver = callableCandidate.extensionReceiver
val unrestrictedBuilderInferenceSupported = val unrestrictedBuilderInferenceSupported =
topLevelCallContext.languageVersionSettings.supportsFeature(LanguageFeature.UnrestrictedBuilderInference) 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 }) { if (rawExtensionReceiver != null && !unrestrictedBuilderInferenceSupported && rawExtensionReceiver.receiver.receiverValue.type.contains { it is StubTypeForBuilderInference }) {
topLevelTrace.reportDiagnosticOnce(Errors.TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE.on(callableReferenceExpression)) 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 (recordedDescriptor != null) {
val resultTypeInfo = if (recorderDescriptor != null) { extractCallableReferenceResultTypeInfoFromDescriptor(callableCandidate, recordedDescriptor)
extractCallableReferenceResultTypeInfoFromDescriptor(callableCandidate, recorderDescriptor)
} else { } else {
updateCallableReferenceResultType(callableCandidate, psiCallArgument.ktCallableReferenceExpression) updateCallableReferenceResultType(callableCandidate)
} }
val reference = callableReferenceExpression.callableReference if (resultTypeInfo == null) return null
val psiCall = CallMaker.makeCall(reference, resultTypeInfo.explicitReceiver, null, reference, emptyList())
val tracing = TracingStrategyImpl.create(reference, psiCall) resolvedCall.apply {
val temporaryTrace = TemporaryBindingTrace.create(topLevelTrace, "callable reference fake call") if (resultTypeInfo.dispatchReceiver != null) {
updateDispatchReceiverType(resultTypeInfo.dispatchReceiver.type)
val resolvedCall = ResolvedCallImpl( }
psiCall, callableCandidate.candidate, resultTypeInfo.dispatchReceiver, if (resultTypeInfo.extensionReceiver != null) {
resultTypeInfo.extensionReceiver, callableCandidate.explicitReceiverKind, updateExtensionReceiverType(resultTypeInfo.extensionReceiver.type)
null, temporaryTrace, tracing, MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY) }
) setResultingSubstitutor(resultTypeInfo.substitutor)
}
resolvedCall.setSubstitutor(resultTypeInfo.substitutor)
recordArgumentAdaptationForCallableReference(resolvedCall, callableCandidate.callableReferenceAdaptation) 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.bindCall(topLevelTrace, psiCall)
tracing.bindReference(topLevelTrace, resolvedCall) tracing.bindReference(topLevelTrace, resolvedCall)
tracing.bindResolvedCall(topLevelTrace, resolvedCall) tracing.bindResolvedCall(topLevelTrace, resolvedCall)
resolvedCall.setStatusToSuccess()
resolvedCall.markCallAsCompleted()
// TODO: probably we should also record key 'DATA_FLOW_INFO_BEFORE', see ExpressionTypingVisitorDispatcher.getTypeInfo // 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.EXPRESSION_TYPE_INFO, callableReferenceExpression, typeInfo)
topLevelTrace.record(BindingContext.PROCESSED, callableReferenceExpression) topLevelTrace.record(BindingContext.PROCESSED, callableReferenceExpression)
kotlinToResolvedCallTransformer.runCallCheckers(resolvedCall, topLevelCallCheckerContext) kotlinToResolvedCallTransformer.runCallCheckers(resolvedCall, topLevelCallCheckerContext)
resolvedAtom.completed = true
return resultTypeInfo.resultType
} }
private fun ReceiverValue.updateReceiverValue(substitutor: TypeSubstitutor): ReceiverValue { private fun ReceiverValue.updateReceiverValue(substitutor: NewTypeSubstitutor): ReceiverValue {
val newType = substitutor.safeSubstitute(type, Variance.INVARIANT).let { val newType = substitutor.safeSubstitute(type.unwrap()).let {
typeApproximator.approximateToSuperType(it, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference) ?: it typeApproximator.approximateToSuperType(it, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference) ?: it
} }
return if (type != newType) replaceType(newType as KotlinType) else this return if (type != newType) replaceType(newType as KotlinType) else this
} }
private fun recordArgumentAdaptationForCallableReference( private fun recordArgumentAdaptationForCallableReference(
resolvedCall: ResolvedCallImpl<CallableDescriptor>, resolvedCall: NewAbstractResolvedCall<*>,
callableReferenceAdaptation: CallableReferenceAdaptation? callableReferenceAdaptation: CallableReferenceAdaptation?
) { ) {
if (callableReferenceAdaptation == null) return if (callableReferenceAdaptation == null) return
@@ -560,14 +601,12 @@ class ResolvedAtomCompleter(
mappedArguments.add(valueParameter to resolvedValueArgument) mappedArguments.add(valueParameter to resolvedValueArgument)
} }
if (hasNonTrivialMapping || isCallableReferenceWithImplicitConversion(resolvedCall, callableReferenceAdaptation)) { if (hasNonTrivialMapping || isCallableReferenceWithImplicitConversion(resolvedCall, callableReferenceAdaptation)) {
for ((valueParameter, resolvedValueArgument) in mappedArguments) { resolvedCall.updateValueArguments(mappedArguments.toMap())
resolvedCall.recordValueArgument(valueParameter, resolvedValueArgument)
}
} }
} }
private fun isCallableReferenceWithImplicitConversion( private fun isCallableReferenceWithImplicitConversion(
resolvedCall: ResolvedCall<CallableDescriptor>, resolvedCall: NewAbstractResolvedCall<*>,
callableReferenceAdaptation: CallableReferenceAdaptation callableReferenceAdaptation: CallableReferenceAdaptation
): Boolean { ): Boolean {
val resultingDescriptor = resolvedCall.resultingDescriptor 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.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl 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.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
@@ -275,9 +276,16 @@ fun Call.isCallableReference(): Boolean {
return callElement.isCallableReference() return callElement.isCallableReference()
} }
fun KtElement.isCallableReference(): Boolean = fun PsiElement.isCallableReference(): Boolean =
this is KtNameReferenceExpression && (parent as? KtCallableReferenceExpression)?.callableReference == this 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 { fun Call.createLookupLocation(): KotlinLookupLocation {
val calleeExpression = calleeExpression val calleeExpression = calleeExpression
val element = val element =
@@ -339,3 +347,8 @@ fun <D : CallableDescriptor> ResolvedCallImpl<D>.shouldBeSubstituteWithStubTypes
|| dispatchReceiver?.type?.contains { it is StubTypeForBuilderInference } == true || dispatchReceiver?.type?.contains { it is StubTypeForBuilderInference } == true
|| extensionReceiver?.type?.contains { it is StubTypeForBuilderInference } == true || extensionReceiver?.type?.contains { it is StubTypeForBuilderInference } == true
|| valueArguments.any { argument -> argument.key.type.contains { it is StubTypeForBuilderInference } } || 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 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.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.psi.KtCallElement import org.jetbrains.kotlin.psi.KtCallElement
import org.jetbrains.kotlin.psi.KtPsiUtil 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.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind 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.constants.IntegerLiteralTypeConstructor
import org.jetbrains.kotlin.resolve.descriptorUtil.getOwnerForEffectiveDispatchReceiverParameter import org.jetbrains.kotlin.resolve.descriptorUtil.getOwnerForEffectiveDispatchReceiverParameter
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassValueReceiver 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() val parameterToProcess = resolvedCall.resultingDescriptor.valueParameters.getOrNull(index) ?: return emptyList()
return resolvedCall.valueArguments[parameterToProcess]?.arguments ?: emptyList() return resolvedCall.valueArguments[parameterToProcess]?.arguments ?: emptyList()
} }
fun CallableMemberDescriptor.isNotSimpleCall(): Boolean =
fun CallableDescriptor.isNotSimpleCall(): Boolean =
typeParameters.isNotEmpty() || typeParameters.isNotEmpty() ||
(returnType?.let { type -> (returnType?.let { type ->
type.contains { type.contains {
@@ -109,7 +111,7 @@ fun CallableMemberDescriptor.isNotSimpleCall(): Boolean =
} }
} ?: false) } ?: 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 { fun ResolvedCall<*>.hasInferredReturnType(): Boolean {
if (isNewNotCompleted()) return false 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
}
@@ -41,6 +41,10 @@ abstract class ArgumentConstraintPosition<out T>(val argument: T) : ConstraintPo
override fun toString(): String = "Argument $argument" 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 { abstract class ReceiverConstraintPosition<T>(val argument: T) : ConstraintPosition(), OnlyInputTypeConstraintPosition {
override fun toString(): String = "Receiver $argument" 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.config.LanguageFeature
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceResolver import org.jetbrains.kotlin.resolve.calls.components.*
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.candidate.ResolutionCandidate 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.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.* import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.resolve.descriptorUtil.OVERLOAD_RESOLUTION_BY_LAMBDA_ANNOTATION_FQ_NAME 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 towerResolver: TowerResolver,
private val kotlinCallCompleter: KotlinCallCompleter, private val kotlinCallCompleter: KotlinCallCompleter,
private val overloadingConflictResolver: NewOverloadingConflictResolver, private val overloadingConflictResolver: NewOverloadingConflictResolver,
private val callableReferenceResolver: CallableReferenceResolver, private val callableReferenceArgumentResolver: CallableReferenceArgumentResolver,
private val callComponents: KotlinCallComponents private val callComponents: KotlinCallComponents
) { ) {
fun resolveCall( fun resolveAndCompleteCall(
scopeTower: ImplicitScopeTower, scopeTower: ImplicitScopeTower,
resolutionCallbacks: KotlinResolutionCallbacks, resolutionCallbacks: KotlinResolutionCallbacks,
kotlinCall: KotlinCall, kotlinCall: KotlinCall,
expectedType: UnwrappedType?, expectedType: UnwrappedType?,
collectAllCandidates: Boolean, 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 { ): CallResolutionResult {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
kotlinCall.checkCallInvariants() kotlinCall.checkCallInvariants()
val candidateFactory = SimpleCandidateFactory( val candidateFactory = SimpleCandidateFactory(callComponents, scopeTower, kotlinCall, resolutionCallbacks)
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
) )
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) { val processor = when (kotlinCall.callKind) {
KotlinCallKind.VARIABLE -> { KotlinCallKind.VARIABLE -> {
createVariableAndObjectProcessor(scopeTower, kotlinCall.name, candidateFactory, kotlinCall.explicitReceiver?.receiver) createVariableAndObjectProcessor(scopeTower, kotlinCall.name, candidateFactory, kotlinCall.explicitReceiver?.receiver)
@@ -51,9 +143,12 @@ class KotlinCallResolver(
scopeTower, scopeTower,
kotlinCall.name, kotlinCall.name,
candidateFactory, candidateFactory,
createFactoryProviderForInvoke(), resolutionCallbacks.getCandidateFactoryForInvoke(scopeTower, kotlinCall),
kotlinCall.explicitReceiver?.receiver kotlinCall.explicitReceiver?.receiver
) ) as ScopeTowerProcessor<C>
}
KotlinCallKind.CALLABLE_REFERENCE -> {
createCallableReferenceProcessor(candidateFactory as CallableReferencesCandidateFactory) as ScopeTowerProcessor<C>
} }
KotlinCallKind.INVOKE -> { KotlinCallKind.INVOKE -> {
createProcessorWithReceiverValueOrEmpty(kotlinCall.explicitReceiver?.receiver) { createProcessorWithReceiverValueOrEmpty(kotlinCall.explicitReceiver?.receiver) {
@@ -69,8 +164,7 @@ class KotlinCallResolver(
} }
if (collectAllCandidates) { if (collectAllCandidates) {
val allCandidates = towerResolver.collectAllCandidates(scopeTower, processor, kotlinCall.name) return towerResolver.collectAllCandidates(scopeTower, processor, kotlinCall.name)
return kotlinCallCompleter.createAllCandidatesResult(allCandidates, expectedType, resolutionCallbacks)
} }
val candidates = towerResolver.runResolve( val candidates = towerResolver.runResolve(
@@ -80,73 +174,55 @@ class KotlinCallResolver(
name = kotlinCall.name name = kotlinCall.name
) )
return choseMostSpecific(candidateFactory, resolutionCallbacks, expectedType, candidates) @Suppress("UNCHECKED_CAST")
} return choseMostSpecific(kotlinCall, resolutionCallbacks, candidates) as Set<C>
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)
} }
private fun choseMostSpecific( private fun choseMostSpecific(
candidateFactory: SimpleCandidateFactory, kotlinCall: KotlinCall,
resolutionCallbacks: KotlinResolutionCallbacks, resolutionCallbacks: KotlinResolutionCallbacks,
expectedType: UnwrappedType?,
candidates: Collection<ResolutionCandidate> candidates: Collection<ResolutionCandidate>
): CallResolutionResult { ): Set<ResolutionCandidate> {
var refinedCandidates = candidates 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 } val nonSynthesized = candidates.filter { !it.resolvedCall.candidateDescriptor.isSynthesized }
if (!nonSynthesized.isEmpty()) { if (nonSynthesized.isNotEmpty()) {
refinedCandidates = nonSynthesized refinedCandidates = nonSynthesized
} }
} }
var maximallySpecificCandidates = overloadingConflictResolver.chooseMaximallySpecificCandidates( var maximallySpecificCandidates = if (kotlinCall.callKind == KotlinCallKind.CALLABLE_REFERENCE) {
refinedCandidates, @Suppress("UNCHECKED_CAST")
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, callableReferenceArgumentResolver.callableReferenceOverloadConflictResolver.chooseMaximallySpecificCandidates(
discriminateGenerics = true // todo refinedCandidates as Collection<CallableReferenceResolutionCandidate>,
) CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
discriminateGenerics = true
)
} else {
overloadingConflictResolver.chooseMaximallySpecificCandidates(
refinedCandidates,
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
discriminateGenerics = true // todo
)
}
if ( if (
maximallySpecificCandidates.size > 1 && maximallySpecificCandidates.size > 1 &&
callComponents.languageVersionSettings.supportsFeature(LanguageFeature.OverloadResolutionByLambdaReturnType) && callComponents.languageVersionSettings.supportsFeature(LanguageFeature.OverloadResolutionByLambdaReturnType) &&
candidates.all { resolutionCallbacks.inferenceSession.shouldRunCompletion(it) } candidates.all { resolutionCallbacks.inferenceSession.shouldRunCompletion(it) } &&
kotlinCall.callKind != KotlinCallKind.CALLABLE_REFERENCE
) { ) {
val candidatesWithAnnotation = val candidatesWithAnnotation = candidates.filter {
candidates.filter { it.resolvedCall.candidateDescriptor.annotations.hasAnnotation(OVERLOAD_RESOLUTION_BY_LAMBDA_ANNOTATION_FQ_NAME) } it.resolvedCall.candidateDescriptor.annotations.hasAnnotation(OVERLOAD_RESOLUTION_BY_LAMBDA_ANNOTATION_FQ_NAME)
}.toSet()
val candidatesWithoutAnnotation = candidates - candidatesWithAnnotation val candidatesWithoutAnnotation = candidates - candidatesWithAnnotation
if (candidatesWithAnnotation.isNotEmpty()) { if (candidatesWithAnnotation.isNotEmpty()) {
val newCandidates = kotlinCallCompleter.chooseCandidateRegardingOverloadResolutionByLambdaReturnType(maximallySpecificCandidates, resolutionCallbacks) @Suppress("UNCHECKED_CAST")
val newCandidates = kotlinCallCompleter.chooseCandidateRegardingOverloadResolutionByLambdaReturnType(
maximallySpecificCandidates as Set<SimpleResolutionCandidate>,
resolutionCallbacks
)
maximallySpecificCandidates = overloadingConflictResolver.chooseMaximallySpecificCandidates( maximallySpecificCandidates = overloadingConflictResolver.chooseMaximallySpecificCandidates(
newCandidates, newCandidates,
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
@@ -160,7 +236,6 @@ class KotlinCallResolver(
} }
} }
return kotlinCallCompleter.runCompletion(candidateFactory, maximallySpecificCandidates, expectedType, resolutionCallbacks) return maximallySpecificCandidates
} }
} }
@@ -0,0 +1,74 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.isInapplicable
class CallableReferenceArgumentResolver(val callableReferenceOverloadConflictResolver: CallableReferenceOverloadConflictResolver) {
fun processCallableReferenceArgument(
csBuilder: ConstraintSystemBuilder,
resolvedAtom: ResolvedCallableReferenceArgumentAtom,
diagnosticsHolder: KotlinDiagnosticsHolder,
resolutionCallbacks: KotlinResolutionCallbacks
) {
val argument = resolvedAtom.atom
val expectedType = resolvedAtom.expectedType?.let { (csBuilder.buildCurrentSubstitutor() as NewTypeSubstitutor).safeSubstitute(it) }
val candidates = resolutionCallbacks.resolveCallableReferenceArgument(resolvedAtom.atom, expectedType, csBuilder.currentStorage())
if (candidates.size > 1 && resolvedAtom is EagerCallableReferenceAtom) {
if (candidates.all { it.resultingApplicability.isInapplicable }) {
diagnosticsHolder.addDiagnostic(CallableReferenceCallCandidatesAmbiguity(argument, candidates))
}
resolvedAtom.setAnalyzedResults(
candidate = null,
subResolvedAtoms = listOf(resolvedAtom.transformToPostponed())
)
return
}
val chosenCandidate = candidates.singleOrNull()
if (chosenCandidate != null) {
val toFreshSubstitutor = CreateFreshVariablesSubstitutor.createToFreshVariableSubstitutorAndAddInitialConstraints(
chosenCandidate.candidate,
csBuilder
)
chosenCandidate.addConstraints(csBuilder, toFreshSubstitutor, callableReference = argument)
chosenCandidate.diagnostics.forEach {
val transformedDiagnostic = when (it) {
is CompatibilityWarning -> CompatibilityWarningOnArgument(argument, it.candidate)
else -> it
}
diagnosticsHolder.addDiagnostic(transformedDiagnostic)
}
chosenCandidate.freshVariablesSubstitutor = toFreshSubstitutor
} else {
if (candidates.isEmpty()) {
diagnosticsHolder.addDiagnostic(NoneCallableReferenceCallCandidates(argument))
} else {
diagnosticsHolder.addDiagnostic(CallableReferenceCallCandidatesAmbiguity(argument, candidates))
}
}
// todo -- create this inside CallableReferencesCandidateFactory
val subKtArguments = listOfNotNull(buildResolvedKtArgument(argument.lhsResult))
resolvedAtom.setAnalyzedResults(chosenCandidate, subKtArguments)
}
private fun buildResolvedKtArgument(lhsResult: LHSResult): ResolvedAtom? {
if (lhsResult !is LHSResult.Expression) return null
return when (val lshCallArgument = lhsResult.lshCallArgument) {
is SubKotlinCallArgument -> lshCallArgument.callResult
is ExpressionKotlinCallArgument -> ResolvedExpressionAtom(lshCallArgument)
else -> unexpectedArgument(lshCallArgument)
}
}
}
@@ -0,0 +1,46 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
import org.jetbrains.kotlin.resolve.calls.results.*
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
import org.jetbrains.kotlin.util.CancellationChecker
class CallableReferenceOverloadConflictResolver(
builtIns: KotlinBuiltIns,
module: ModuleDescriptor,
specificityComparator: TypeSpecificityComparator,
platformOverloadsSpecificityComparator: PlatformOverloadsSpecificityComparator,
cancellationChecker: CancellationChecker,
statelessCallbacks: KotlinResolutionStatelessCallbacks,
constraintInjector: ConstraintInjector,
kotlinTypeRefiner: KotlinTypeRefiner,
) : OverloadingConflictResolver<CallableReferenceResolutionCandidate>(
builtIns,
module,
specificityComparator,
platformOverloadsSpecificityComparator,
cancellationChecker,
{ it.candidate },
{ statelessCallbacks.createConstraintSystemForOverloadResolution(constraintInjector, builtIns) },
Companion::createFlatSignature,
{ null },
{ statelessCallbacks.isDescriptorFromSource(it) },
null,
kotlinTypeRefiner,
) {
companion object {
private fun createFlatSignature(candidate: CallableReferenceResolutionCandidate) =
FlatSignature.createFromReflectionType(
candidate, candidate.candidate, candidate.numDefaults, hasBoundExtensionReceiver = candidate.extensionReceiver != null,
candidate.reflectionCandidateType
)
}
}
@@ -6,32 +6,19 @@
package org.jetbrains.kotlin.resolve.calls.components package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.builtins.* 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.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.components.CreateFreshVariablesSubstitutor.createToFreshVariableSubstitutorAndAddInitialConstraints
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor 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.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.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.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.captureFromExpression import org.jetbrains.kotlin.types.checker.captureFromExpression
import org.jetbrains.kotlin.types.expressions.CoercionStrategy import org.jetbrains.kotlin.types.expressions.CoercionStrategy
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes 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.types.typeUtil.supertypes
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addIfNotNull
sealed class CallableReceiver(val receiver: ReceiverValueWithSmartCastInfo) { sealed class CallableReceiver(val receiver: ReceiverValueWithSmartCastInfo) {
class UnboundReference(receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver(receiver) class UnboundReference(receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver(receiver)
@@ -40,10 +27,6 @@ sealed class CallableReceiver(val receiver: ReceiverValueWithSmartCastInfo) {
class ExplicitValueReceiver(receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver(receiver) class ExplicitValueReceiver(receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver(receiver)
} }
// todo investigate similar code in CheckVisibility
private val CallableReceiver.asReceiverValueForVisibilityChecks: ReceiverValue
get() = receiver.receiverValue
class CallableReferenceAdaptation( class CallableReferenceAdaptation(
val argumentTypes: Array<KotlinType>, val argumentTypes: Array<KotlinType>,
val coercionStrategy: CoercionStrategy, val coercionStrategy: CoercionStrategy,
@@ -90,41 +73,31 @@ fun createCallableReferenceProcessor(factory: CallableReferencesCandidateFactory
} }
} }
fun ConstraintSystemOperation.checkCallableReference( fun CallableReferenceResolutionCandidate.addConstraints(
argument: CallableReferenceKotlinCallArgument, constraintSystem: ConstraintSystemOperation,
dispatchReceiver: CallableReceiver?, substitutor: FreshVariableNewTypeSubstitutor,
extensionReceiver: CallableReceiver?, callableReference: CallableReferenceResolutionAtom
candidateDescriptor: CallableDescriptor, ) {
reflectionCandidateType: UnwrappedType, val position = when (callableReference) {
expectedType: UnwrappedType?, is CallableReferenceKotlinCallArgument -> ArgumentConstraintPositionImpl(callableReference)
ownerDescriptor: DeclarationDescriptor is CallableReferenceKotlinCall -> CallableReferenceConstraintPositionImpl(callableReference)
): 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)
} }
if (expectedType != null && !hasContradiction) { if (!ErrorUtils.isError(candidate)) {
addSubtypeConstraint(toFreshSubstitutor.safeSubstitute(reflectionCandidateType), expectedType, position) constraintSystem.addReceiverConstraint(substitutor, dispatchReceiver, candidate.dispatchReceiverParameter, position)
constraintSystem.addReceiverConstraint(substitutor, extensionReceiver, candidate.extensionReceiverParameter, position)
} }
val invisibleMember = DescriptorVisibilities.findInvisibleMember( if (expectedType != null && !TypeUtils.noExpectedType(expectedType) && !constraintSystem.hasContradiction) {
dispatchReceiver?.asReceiverValueForVisibilityChecks, constraintSystem.addSubtypeConstraint(substitutor.safeSubstitute(reflectionCandidateType), expectedType, position)
candidateDescriptor, ownerDescriptor }
)
return toFreshSubstitutor to invisibleMember?.let(::VisibilityError)
} }
private fun ConstraintSystemOperation.addReceiverConstraint( private fun ConstraintSystemOperation.addReceiverConstraint(
toFreshSubstitutor: FreshVariableNewTypeSubstitutor, toFreshSubstitutor: FreshVariableNewTypeSubstitutor,
receiverArgument: CallableReceiver?, receiverArgument: CallableReceiver?,
receiverParameter: ReceiverParameterDescriptor?, receiverParameter: ReceiverParameterDescriptor?,
position: ArgumentConstraintPositionImpl position: ConstraintPosition
) { ) {
if (receiverArgument == null || receiverParameter == null) { if (receiverArgument == null || receiverParameter == null) {
assert(receiverArgument == null) { "Receiver argument should be null if parameter is: $receiverArgument" } assert(receiverArgument == null) { "Receiver argument should be null if parameter is: $receiverArgument" }
@@ -1,162 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.results.*
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower
import org.jetbrains.kotlin.resolve.calls.tower.TowerResolver
import org.jetbrains.kotlin.resolve.calls.tower.isInapplicable
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
import org.jetbrains.kotlin.util.CancellationChecker
class CallableReferenceOverloadConflictResolver(
builtIns: KotlinBuiltIns,
module: ModuleDescriptor,
specificityComparator: TypeSpecificityComparator,
platformOverloadsSpecificityComparator: PlatformOverloadsSpecificityComparator,
cancellationChecker: CancellationChecker,
statelessCallbacks: KotlinResolutionStatelessCallbacks,
constraintInjector: ConstraintInjector,
kotlinTypeRefiner: KotlinTypeRefiner,
) : OverloadingConflictResolver<CallableReferenceCandidate>(
builtIns,
module,
specificityComparator,
platformOverloadsSpecificityComparator,
cancellationChecker,
{ it.candidate },
{ statelessCallbacks.createConstraintSystemForOverloadResolution(constraintInjector, builtIns) },
Companion::createFlatSignature,
{ null },
{ statelessCallbacks.isDescriptorFromSource(it) },
null,
kotlinTypeRefiner,
) {
companion object {
private fun createFlatSignature(candidate: CallableReferenceCandidate) =
FlatSignature.createFromReflectionType(
candidate, candidate.candidate, candidate.numDefaults, hasBoundExtensionReceiver = candidate.extensionReceiver != null,
candidate.reflectionCandidateType
)
}
}
class CallableReferenceResolver(
private val towerResolver: TowerResolver,
private val callableReferenceOverloadConflictResolver: CallableReferenceOverloadConflictResolver,
private val callComponents: KotlinCallComponents
) {
fun processCallableReferenceArgument(
csBuilder: ConstraintSystemBuilder,
resolvedAtom: ResolvedCallableReferenceAtom,
diagnosticsHolder: KotlinDiagnosticsHolder,
resolutionCallbacks: KotlinResolutionCallbacks
) {
val argument = resolvedAtom.atom
val expectedType = resolvedAtom.expectedType?.let { (csBuilder.buildCurrentSubstitutor() as NewTypeSubstitutor).safeSubstitute(it) }
val scopeTower = callComponents.statelessCallbacks.getScopeTowerForCallableReferenceArgument(argument)
val candidates = runRHSResolution(scopeTower, argument, expectedType, csBuilder, resolutionCallbacks) { checkCallableReference ->
csBuilder.runTransaction { checkCallableReference(this); false }
}
if (candidates.size > 1 && resolvedAtom is EagerCallableReferenceAtom) {
if (candidates.all { it.resultingApplicability.isInapplicable }) {
diagnosticsHolder.addDiagnostic(CallableReferenceCandidatesAmbiguity(argument, candidates))
}
resolvedAtom.setAnalyzedResults(
candidate = null,
subResolvedAtoms = listOf(resolvedAtom.transformToPostponed())
)
return
}
val chosenCandidate = candidates.singleOrNull()
if (chosenCandidate != null) {
val (toFreshSubstitutor, diagnostic) = with(chosenCandidate) {
csBuilder.checkCallableReference(
argument, dispatchReceiver, extensionReceiver, candidate,
reflectionCandidateType, expectedType, scopeTower.lexicalScope.ownerDescriptor
)
}
diagnosticsHolder.addDiagnosticIfNotNull(diagnostic)
chosenCandidate.diagnostics.forEach {
val transformedDiagnostic = when (it) {
is CompatibilityWarning -> CompatibilityWarningOnArgument(argument, it.candidate)
else -> it
}
diagnosticsHolder.addDiagnostic(transformedDiagnostic)
}
chosenCandidate.freshSubstitutor = toFreshSubstitutor
} else {
if (candidates.isEmpty()) {
diagnosticsHolder.addDiagnostic(NoneCallableReferenceCandidates(argument))
} else {
diagnosticsHolder.addDiagnostic(CallableReferenceCandidatesAmbiguity(argument, candidates))
}
}
// todo -- create this inside CallableReferencesCandidateFactory
val subKtArguments = listOfNotNull(buildResolvedKtArgument(argument.lhsResult))
resolvedAtom.setAnalyzedResults(chosenCandidate, subKtArguments)
}
private fun buildResolvedKtArgument(lhsResult: LHSResult): ResolvedAtom? {
if (lhsResult !is LHSResult.Expression) return null
val lshCallArgument = lhsResult.lshCallArgument
return when (lshCallArgument) {
is SubKotlinCallArgument -> lshCallArgument.callResult
is ExpressionKotlinCallArgument -> ResolvedExpressionAtom(lshCallArgument)
else -> unexpectedArgument(lshCallArgument)
}
}
private fun runRHSResolution(
scopeTower: ImplicitScopeTower,
callableReference: CallableReferenceKotlinCallArgument,
expectedType: UnwrappedType?, // this type can have not fixed type variable inside
csBuilder: ConstraintSystemBuilder,
resolutionCallbacks: KotlinResolutionCallbacks,
compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit // you can run anything throw this operation and all this operation will be rolled back
): Set<CallableReferenceCandidate> {
val factory = CallableReferencesCandidateFactory(
callableReference, callComponents, scopeTower, compatibilityChecker, expectedType, csBuilder, resolutionCallbacks
)
val processor = createCallableReferenceProcessor(factory)
val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = true, name = callableReference.rhsName)
return callableReferenceOverloadConflictResolver.chooseMaximallySpecificCandidates(
candidates,
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
discriminateGenerics = false // we can't specify generics explicitly for callable references
)
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.resolve.calls.components 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.ConstraintSystemCompletionContext
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
@@ -42,7 +43,7 @@ class CompletionModeCalculator {
if (returnType == null) return ConstraintSystemCompletionMode.PARTIAL if (returnType == null) return ConstraintSystemCompletionMode.PARTIAL
// Full if return type for call has no type variables // 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 // For nested call with variables in return type check possibility of full completion
return CalculatorForNestedCall( return CalculatorForNestedCall(
@@ -11,10 +11,15 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations 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.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.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem 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.calls.tower.ImplicitScopeTower
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -37,7 +42,7 @@ interface KotlinResolutionStatelessCallbacks {
fun isSuperExpression(receiver: SimpleKotlinCallArgument?): Boolean fun isSuperExpression(receiver: SimpleKotlinCallArgument?): Boolean
fun getScopeTowerForCallableReferenceArgument(argument: CallableReferenceKotlinCallArgument): ImplicitScopeTower fun getScopeTowerForCallableReferenceArgument(argument: CallableReferenceKotlinCallArgument): ImplicitScopeTower
fun getVariableCandidateIfInvoke(functionCall: KotlinCall): KotlinResolutionCandidate? fun getVariableCandidateIfInvoke(functionCall: KotlinCall): ResolutionCandidate?
fun isBuilderInferenceCall(argument: KotlinCallArgument, parameter: ValueParameterDescriptor): Boolean fun isBuilderInferenceCall(argument: KotlinCallArgument, parameter: ValueParameterDescriptor): Boolean
fun isApplicableCallForBuilderInference(descriptor: CallableDescriptor, languageVersionSettings: LanguageVersionSettings): Boolean fun isApplicableCallForBuilderInference(descriptor: CallableDescriptor, languageVersionSettings: LanguageVersionSettings): Boolean
@@ -77,6 +82,17 @@ interface KotlinResolutionCallbacks {
stubsForPostponedVariables: Map<NewTypeVariable, StubTypeForBuilderInference>, stubsForPostponedVariables: Map<NewTypeVariable, StubTypeForBuilderInference>,
): ReturnArgumentsAnalysisResult ): ReturnArgumentsAnalysisResult
fun getCandidateFactoryForInvoke(
scopeTower: ImplicitScopeTower,
kotlinCall: KotlinCall,
): CandidateFactoryProviderForInvoke<ResolutionCandidate>
fun resolveCallableReferenceArgument(
argument: CallableReferenceKotlinCallArgument,
expectedType: UnwrappedType?,
baseSystem: ConstraintStorage,
): Collection<CallableReferenceResolutionCandidate>
fun bindStubResolvedCallForCandidate(candidate: ResolvedCallAtom) fun bindStubResolvedCallForCandidate(candidate: ResolvedCallAtom)
fun isCompileTimeConstant(resolvedAtom: ResolvedCallAtom, expectedType: UnwrappedType): Boolean fun isCompileTimeConstant(resolvedAtom: ResolvedCallAtom, expectedType: UnwrappedType): Boolean
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.TrivialConstraint
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage.Empty.hasContradiction import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage.Empty.hasContradiction
import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPositionImpl import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPositionImpl
import org.jetbrains.kotlin.resolve.calls.model.* 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.resolve.calls.tower.forceResolution
import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
@@ -40,22 +41,27 @@ class KotlinCallCompleter(
resolutionCallbacks: KotlinResolutionCallbacks resolutionCallbacks: KotlinResolutionCallbacks
): CallResolutionResult { ): CallResolutionResult {
val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder() val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder()
when { when {
candidates.isEmpty() -> diagnosticHolder.addDiagnostic(NoneCandidatesCallDiagnostic(factory.kotlinCall)) candidates.isEmpty() -> diagnosticHolder.addDiagnostic(NoneCandidatesCallDiagnostic())
candidates.size > 1 -> diagnosticHolder.addDiagnostic(ManyCandidatesCallDiagnostic(factory.kotlinCall, candidates)) candidates.size > 1 -> diagnosticHolder.addDiagnostic(ManyCandidatesCallDiagnostic(candidates))
} }
val candidate = prepareCandidateForCompletion(factory, candidates, resolutionCallbacks) 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) val completionMode = CompletionModeCalculator.computeCompletionMode(
candidate.addExpectedTypeFromCastConstraint(returnType, resolutionCallbacks) candidate, expectedType, resultType, trivialConstraintTypeInferenceOracle, resolutionCallbacks.inferenceSession
candidate.checkSamWithVararg(diagnosticHolder) )
val completionMode =
CompletionModeCalculator.computeCompletionMode(
candidate, expectedType, returnType, trivialConstraintTypeInferenceOracle, resolutionCallbacks.inferenceSession
)
return when (completionMode) { return when (completionMode) {
ConstraintSystemCompletionMode.FULL -> { ConstraintSystemCompletionMode.FULL -> {
@@ -151,7 +157,7 @@ class KotlinCallCompleter(
private fun SimpleResolutionCandidate.getInputTypesOfLambdaAtom(atom: ResolvedLambdaAtom): List<UnwrappedType> { private fun SimpleResolutionCandidate.getInputTypesOfLambdaAtom(atom: ResolvedLambdaAtom): List<UnwrappedType> {
val result = mutableListOf<UnwrappedType>() val result = mutableListOf<UnwrappedType>()
val substitutor = csBuilder.buildCurrentSubstitutor() val substitutor = getSystem().getBuilder().buildCurrentSubstitutor()
val ctx = getSystem().asConstraintSystemCompleterContext() val ctx = getSystem().asConstraintSystemCompleterContext()
for (inputType in atom.inputTypes) { for (inputType in atom.inputTypes) {
result += substitutor.safeSubstitute(ctx, inputType) as UnwrappedType result += substitutor.safeSubstitute(ctx, inputType) as UnwrappedType
@@ -198,7 +204,7 @@ class KotlinCallCompleter(
collectAllCandidatesMode = true collectAllCandidatesMode = true
) )
CandidateWithDiagnostics(candidate, diagnosticsHolder.getDiagnostics() + candidate.diagnosticsFromResolutionParts) CandidateWithDiagnostics(candidate, diagnosticsHolder.getDiagnostics() + candidate.diagnostics)
} }
return AllCandidatesResolutionResult(completedCandidates) return AllCandidatesResolutionResult(completedCandidates)
} }
@@ -264,6 +270,10 @@ class KotlinCallCompleter(
return candidate ?: factory.createErrorCandidate().forceResolution() return candidate ?: factory.createErrorCandidate().forceResolution()
} }
private fun CallableReferenceResolutionCandidate.substitutedReflectionType(): UnwrappedType {
return resolvedCall.freshVariablesSubstitutor.safeSubstitute(this.reflectionCandidateType)
}
private fun ResolutionCandidate.substitutedReturnType(): UnwrappedType? { private fun ResolutionCandidate.substitutedReturnType(): UnwrappedType? {
val returnType = resolvedCall.candidateDescriptor.returnType?.unwrap() ?: return null val returnType = resolvedCall.candidateDescriptor.returnType?.unwrap() ?: return null
return resolvedCall.freshVariablesSubstitutor.safeSubstitute(returnType) return resolvedCall.freshVariablesSubstitutor.safeSubstitute(returnType)
@@ -276,6 +286,8 @@ class KotlinCallCompleter(
if (returnType == null) return if (returnType == null) return
if (expectedType == null || (TypeUtils.noExpectedType(expectedType) && expectedType !== TypeUtils.UNIT_EXPECTED_TYPE)) return if (expectedType == null || (TypeUtils.noExpectedType(expectedType) && expectedType !== TypeUtils.UNIT_EXPECTED_TYPE)) return
val csBuilder = getSystem().getBuilder()
when { when {
csBuilder.currentStorage().notFixedTypeVariables.isEmpty() -> { csBuilder.currentStorage().notFixedTypeVariables.isEmpty() -> {
// This is needed to avoid multiple mismatch errors as we type check resulting type against expected one later // 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 (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ExpectedTypeFromCast)) return
if (returnType == null) return if (returnType == null) return
val expectedType = resolutionCallbacks.getExpectedTypeFromAsExpressionAndRecordItInTrace(resolvedCall) ?: return val expectedType = resolutionCallbacks.getExpectedTypeFromAsExpressionAndRecordItInTrace(resolvedCall) ?: return
val csBuilder = getSystem().getBuilder()
csBuilder.addSubtypeConstraint(returnType, expectedType, ExpectedTypeConstraintPositionImpl(resolvedCall.atom)) csBuilder.addSubtypeConstraint(returnType, expectedType, ExpectedTypeConstraintPositionImpl(resolvedCall.atom))
} }
@@ -314,7 +329,7 @@ class KotlinCallCompleter(
forwardToInferenceSession: Boolean = false forwardToInferenceSession: Boolean = false
): CallResolutionResult { ): CallResolutionResult {
val systemStorage = getSystem().asReadOnlyStorage() val systemStorage = getSystem().asReadOnlyStorage()
val allDiagnostics = diagnosticsHolder.getDiagnostics() + diagnosticsFromResolutionParts val allDiagnostics = diagnosticsHolder.getDiagnostics() + diagnostics
if (isErrorCandidate()) { if (isErrorCandidate()) {
return ErrorCallResolutionResult(resolvedCall, allDiagnostics, systemStorage) return ErrorCallResolutionResult(resolvedCall, allDiagnostics, systemStorage)
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.cast
class PostponedArgumentsAnalyzer( class PostponedArgumentsAnalyzer(
private val callableReferenceResolver: CallableReferenceResolver, private val callableReferenceArgumentResolver: CallableReferenceArgumentResolver,
private val languageVersionSettings: LanguageVersionSettings private val languageVersionSettings: LanguageVersionSettings
) { ) {
@@ -49,8 +49,10 @@ class PostponedArgumentsAnalyzer(
diagnosticsHolder diagnosticsHolder
) )
is ResolvedCallableReferenceAtom -> is ResolvedCallableReferenceArgumentAtom ->
callableReferenceResolver.processCallableReferenceArgument(c.getBuilder(), argument, diagnosticsHolder, resolutionCallbacks) callableReferenceArgumentResolver.processCallableReferenceArgument(
c.getBuilder(), argument, diagnosticsHolder, resolutionCallbacks
)
is ResolvedCollectionLiteralAtom -> TODO("Not supported") is ResolvedCollectionLiteralAtom -> TODO("Not supported")
@@ -119,6 +119,7 @@ internal object NoArguments : ResolutionPart() {
internal object CreateFreshVariablesSubstitutor : ResolutionPart() { internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
override fun ResolutionCandidate.process(workIndex: Int) { override fun ResolutionCandidate.process(workIndex: Int) {
val csBuilder = getSystem().getBuilder()
val toFreshVariables = val toFreshVariables =
if (candidateDescriptor.typeParameters.isEmpty()) if (candidateDescriptor.typeParameters.isEmpty())
FreshVariableNewTypeSubstitutor.Empty FreshVariableNewTypeSubstitutor.Empty
@@ -126,7 +127,7 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
createToFreshVariableSubstitutorAndAddInitialConstraints(candidateDescriptor, csBuilder) createToFreshVariableSubstitutorAndAddInitialConstraints(candidateDescriptor, csBuilder)
val knownTypeParametersSubstitutor = knownTypeParametersResultingSubstitutor?.let { val knownTypeParametersSubstitutor = knownTypeParametersResultingSubstitutor?.let {
createKnownParametersFromFreshVariablesSubstitutor(toFreshVariables, knownTypeParametersResultingSubstitutor) createKnownParametersFromFreshVariablesSubstitutor(toFreshVariables, it)
} ?: EmptySubstitutor } ?: EmptySubstitutor
resolvedCall.freshVariablesSubstitutor = toFreshVariables resolvedCall.freshVariablesSubstitutor = toFreshVariables
@@ -275,6 +276,7 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
internal object PostponedVariablesInitializerResolutionPart : ResolutionPart() { internal object PostponedVariablesInitializerResolutionPart : ResolutionPart() {
override fun ResolutionCandidate.process(workIndex: Int) { override fun ResolutionCandidate.process(workIndex: Int) {
val csBuilder = getSystem().getBuilder()
for ((argument, parameter) in resolvedCall.argumentToCandidateParameter) { for ((argument, parameter) in resolvedCall.argumentToCandidateParameter) {
if (!callComponents.statelessCallbacks.isBuilderInferenceCall(argument, parameter)) continue if (!callComponents.statelessCallbacks.isBuilderInferenceCall(argument, parameter)) continue
val receiverType = parameter.type.getReceiverTypeFromFunctionType() ?: continue val receiverType = parameter.type.getReceiverTypeFromFunctionType() ?: continue
@@ -302,6 +304,7 @@ internal object PostponedVariablesInitializerResolutionPart : ResolutionPart() {
internal object CompatibilityOfTypeVariableAsIntersectionTypePart : ResolutionPart() { internal object CompatibilityOfTypeVariableAsIntersectionTypePart : ResolutionPart() {
override fun ResolutionCandidate.process(workIndex: Int) { override fun ResolutionCandidate.process(workIndex: Int) {
val csBuilder = getSystem().getBuilder()
for ((_, variableWithConstraints) in csBuilder.currentStorage().notFixedTypeVariables) { for ((_, variableWithConstraints) in csBuilder.currentStorage().notFixedTypeVariables) {
val constraints = variableWithConstraints.constraints.filter { csBuilder.isProperType(it.type) } val constraints = variableWithConstraints.constraints.filter { csBuilder.isProperType(it.type) }
@@ -487,13 +490,14 @@ internal object CollectionTypeVariableUsagesInfo : ResolutionPart() {
override fun ResolutionCandidate.process(workIndex: Int) { override fun ResolutionCandidate.process(workIndex: Int) {
for (variable in resolvedCall.freshVariablesSubstitutor.freshVariables) { for (variable in resolvedCall.freshVariablesSubstitutor.freshVariables) {
if (resolvedCall.candidateDescriptor is ClassConstructorDescriptor) { val candidateDescriptor = resolvedCall.candidateDescriptor
val typeParameters = resolvedCall.candidateDescriptor.containingDeclaration.declaredTypeParameters if (candidateDescriptor is ClassConstructorDescriptor) {
val typeParameters = candidateDescriptor.containingDeclaration.declaredTypeParameters
if (isContainedInInvariantOrContravariantPositionsAmongTypeParameters(variable, typeParameters)) { if (isContainedInInvariantOrContravariantPositionsAmongTypeParameters(variable, typeParameters)) {
variable.recordInfoAboutTypeVariableUsagesAsInvariantOrContravariantParameter() variable.recordInfoAboutTypeVariableUsagesAsInvariantOrContravariantParameter()
} }
} else if (getSystem().isContainedInInvariantOrContravariantPositionsWithDependencies(variable, candidateDescriptor)) { } else if (getSystem().isContainedInInvariantOrContravariantPositionsWithDependencies(variable, this.candidateDescriptor)) {
variable.recordInfoAboutTypeVariableUsagesAsInvariantOrContravariantParameter() variable.recordInfoAboutTypeVariableUsagesAsInvariantOrContravariantParameter()
} }
} }
@@ -505,6 +509,7 @@ private fun ResolutionCandidate.resolveKotlinArgument(
candidateParameter: ParameterDescriptor?, candidateParameter: ParameterDescriptor?,
receiverInfo: ReceiverInfo receiverInfo: ReceiverInfo
) { ) {
val csBuilder = getSystem().getBuilder()
val candidateExpectedType = candidateParameter?.let { argument.getExpectedType(it, callComponents.languageVersionSettings) } val candidateExpectedType = candidateParameter?.let { argument.getExpectedType(it, callComponents.languageVersionSettings) }
val isReceiver = receiverInfo.isReceiver val isReceiver = receiverInfo.isReceiver
@@ -602,6 +607,7 @@ private fun ResolutionCandidate.resolveKotlinArgument(
private fun ResolutionCandidate.shouldRunConversionForConstants(expectedType: UnwrappedType): Boolean { private fun ResolutionCandidate.shouldRunConversionForConstants(expectedType: UnwrappedType): Boolean {
if (UnsignedTypes.isUnsignedType(expectedType)) return true if (UnsignedTypes.isUnsignedType(expectedType)) return true
val csBuilder = getSystem().getBuilder()
if (csBuilder.isTypeVariable(expectedType)) { if (csBuilder.isTypeVariable(expectedType)) {
val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[expectedType.constructor] ?: return false val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[expectedType.constructor] ?: return false
return variableWithConstraints.constraints.any { return variableWithConstraints.constraints.any {
@@ -650,7 +656,7 @@ internal object CheckReceivers : ResolutionPart() {
receiverParameter: ReceiverParameterDescriptor?, receiverParameter: ReceiverParameterDescriptor?,
shouldCheckImplicitInvoke: Boolean, 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") error("Inconsistency receiver state for call $kotlinCall and candidate descriptor: $candidateDescriptor")
} }
if (receiverArgument == null || receiverParameter == null) return if (receiverArgument == null || receiverParameter == null) return
@@ -709,11 +715,25 @@ internal object EagerResolveOfCallableReferences : ResolutionPart() {
getSubResolvedAtoms() getSubResolvedAtoms()
.filterIsInstance<EagerCallableReferenceAtom>() .filterIsInstance<EagerCallableReferenceAtom>()
.forEach { .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() { internal object CheckInfixResolutionPart : ResolutionPart() {
override fun ResolutionCandidate.process(workIndex: Int) { override fun ResolutionCandidate.process(workIndex: Int) {
val candidateDescriptor = resolvedCall.candidateDescriptor val candidateDescriptor = resolvedCall.candidateDescriptor
@@ -28,8 +28,10 @@ object UnitTypeConversions : ParameterTypeConversion {
if (argument !is SimpleKotlinCallArgument) return true if (argument !is SimpleKotlinCallArgument) return true
val receiver = argument.receiver val receiver = argument.receiver
if (receiver.receiverValue.type.hasUnitOrSubtypeReturnType(candidate.csBuilder)) return true val csBuilder = candidate.getSystem().getBuilder()
if (receiver.typesFromSmartCasts.any { it.hasUnitOrSubtypeReturnType(candidate.csBuilder) }) return true
if (receiver.receiverValue.type.hasUnitOrSubtypeReturnType(csBuilder)) return true
if (receiver.typesFromSmartCasts.any { it.hasUnitOrSubtypeReturnType(csBuilder) }) return true
if ( if (
!expectedParameterType.isBuiltinFunctionalType || !expectedParameterType.isBuiltinFunctionalType ||
@@ -33,10 +33,10 @@ class CallableReferenceResolutionCandidate(
val reflectionCandidateType: UnwrappedType, val reflectionCandidateType: UnwrappedType,
val callableReferenceAdaptation: CallableReferenceAdaptation?, val callableReferenceAdaptation: CallableReferenceAdaptation?,
val kotlinCall: CallableReferenceResolutionAtom, val kotlinCall: CallableReferenceResolutionAtom,
val expectedType: UnwrappedType?,
override val callComponents: KotlinCallComponents, override val callComponents: KotlinCallComponents,
override val scopeTower: ImplicitScopeTower, override val scopeTower: ImplicitScopeTower,
override val resolutionCallbacks: KotlinResolutionCallbacks, override val resolutionCallbacks: KotlinResolutionCallbacks,
val expectedType: UnwrappedType?,
override val baseSystem: ConstraintStorage? override val baseSystem: ConstraintStorage?
) : ResolutionCandidate() { ) : ResolutionCandidate() {
override val variableCandidateIfInvoke: ResolutionCandidate? = null override val variableCandidateIfInvoke: ResolutionCandidate? = null
@@ -20,30 +20,61 @@ import java.util.ArrayList
sealed class ResolutionCandidate : Candidate, KotlinDiagnosticsHolder { sealed class ResolutionCandidate : Candidate, KotlinDiagnosticsHolder {
abstract val resolvedCall: MutableResolvedCallAtom abstract val resolvedCall: MutableResolvedCallAtom
abstract val callComponents: KotlinCallComponents abstract val callComponents: KotlinCallComponents
abstract fun getSubResolvedAtoms(): List<ResolvedAtom>
abstract fun addResolvedKtPrimitive(resolvedAtom: ResolvedAtom)
abstract val variableCandidateIfInvoke: ResolutionCandidate? abstract val variableCandidateIfInvoke: ResolutionCandidate?
abstract val scopeTower: ImplicitScopeTower abstract val scopeTower: ImplicitScopeTower
abstract val knownTypeParametersResultingSubstitutor: TypeSubstitutor? abstract val knownTypeParametersResultingSubstitutor: TypeSubstitutor?
abstract val resolutionCallbacks: KotlinResolutionCallbacks 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 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) { override fun addDiagnostic(diagnostic: KotlinCallDiagnostic) {
mutableDiagnostics.add(diagnostic) mutableDiagnostics.add(diagnostic)
currentApplicability = minOf(diagnostic.candidateApplicability, currentApplicability) currentApplicability = minOf(diagnostic.candidateApplicability, currentApplicability)
} }
private val variableApplicability override fun addCompatibilityWarning(other: Candidate) {
get() = variableCandidateIfInvoke?.resultingApplicability ?: CandidateApplicability.RESOLVED if (other is ResolutionCandidate && this !== other && this::class == other::class) {
addDiagnostic(CompatibilityWarning(other.descriptor))
}
}
val descriptor: CallableDescriptor get() = resolvedCall.candidateDescriptor override fun toString(): String {
val descriptor = DescriptorRenderer.COMPACT.render(resolvedCall.candidateDescriptor)
protected val mutableDiagnostics: ArrayList<KotlinCallDiagnostic> = arrayListOf() val okOrFail = if (resultingApplicabilities.minOrNull()?.isSuccess != false) "OK" else "FAIL"
val step = "$step/$stepCount"
open val resolutionSequence: List<ResolutionPart> get() = resolvedCall.atom.callKind.resolutionSequence return "$okOrFail($step): $descriptor"
private var newSystem: NewConstraintSystemImpl? = null }
val diagnostics: List<KotlinCallDiagnostic> = mutableDiagnostics
fun getSystem(): NewConstraintSystem { fun getSystem(): NewConstraintSystem {
if (newSystem == null) { if (newSystem == null) {
@@ -57,9 +88,6 @@ sealed class ResolutionCandidate : Candidate, KotlinDiagnosticsHolder {
return newSystem!! return newSystem!!
} }
private val stepCount get() = resolutionSequence.sumOf { it.run { workCount() } }
private var step = 0
private fun processParts(stopOnFirstError: Boolean) { private fun processParts(stopOnFirstError: Boolean) {
if (stopOnFirstError && step > 0) return // error already happened if (stopOnFirstError && step > 0) return // error already happened
if (step == stepCount) return if (step == stepCount) return
@@ -99,34 +127,4 @@ sealed class ResolutionCandidate : Candidate, KotlinDiagnosticsHolder {
} }
return false return false
} }
}
protected var currentApplicability: CandidateApplicability = CandidateApplicability.RESOLVED
override val isSuccessful: Boolean
get() {
processParts(stopOnFirstError = true)
return resultingApplicabilities.minOrNull()!!.isSuccess && !getSystem().hasContradiction
}
val resultingApplicabilities: Array<CandidateApplicability>
get() = arrayOf(currentApplicability, getResultApplicability(getSystem().errors), variableApplicability)
override val resultingApplicability: CandidateApplicability
get() {
processParts(stopOnFirstError = false)
return resultingApplicabilities.minOrNull()!!
}
override fun addCompatibilityWarning(other: Candidate) {
if (other is ResolutionCandidate && this !== other && this::class == other::class) {
addDiagnostic(CompatibilityWarning(other.descriptor))
}
}
override fun toString(): String {
val descriptor = DescriptorRenderer.COMPACT.render(resolvedCall.candidateDescriptor)
val okOrFail = if (resultingApplicabilities.minOrNull()!!.isSuccess) "OK" else "FAIL"
val step = "$step/$stepCount"
return "$okOrFail($step): $descriptor"
}
}
@@ -25,8 +25,6 @@ open class SimpleResolutionCandidate(
override val resolvedCall: MutableResolvedCallAtom, override val resolvedCall: MutableResolvedCallAtom,
override val knownTypeParametersResultingSubstitutor: TypeSubstitutor? = null, override val knownTypeParametersResultingSubstitutor: TypeSubstitutor? = null,
) : ResolutionCandidate() { ) : ResolutionCandidate() {
private var subResolvedAtoms: MutableList<ResolvedAtom> = arrayListOf()
override val variableCandidateIfInvoke: ResolutionCandidate? override val variableCandidateIfInvoke: ResolutionCandidate?
get() = callComponents.statelessCallbacks.getVariableCandidateIfInvoke(resolvedCall.atom) get() = callComponents.statelessCallbacks.getVariableCandidateIfInvoke(resolvedCall.atom)
@@ -35,4 +33,6 @@ open class SimpleResolutionCandidate(
override fun addResolvedKtPrimitive(resolvedAtom: ResolvedAtom) { override fun addResolvedKtPrimitive(resolvedAtom: ResolvedAtom) {
subResolvedAtoms.add(resolvedAtom) subResolvedAtoms.add(resolvedAtom)
} }
private var subResolvedAtoms: MutableList<ResolvedAtom> = arrayListOf()
} }
@@ -35,6 +35,8 @@ val CallableDescriptor.returnTypeOrNothing: UnwrappedType
fun TypeSubstitutor.substitute(type: UnwrappedType): UnwrappedType = safeSubstitute(type, Variance.INVARIANT).unwrap() fun TypeSubstitutor.substitute(type: UnwrappedType): UnwrappedType = safeSubstitute(type, Variance.INVARIANT).unwrap()
fun CallableDescriptor.substitute(substitutor: NewTypeSubstitutor): CallableDescriptor { fun CallableDescriptor.substitute(substitutor: NewTypeSubstitutor): CallableDescriptor {
if (substitutor.isEmpty) return this
val wrappedSubstitution = object : TypeSubstitution() { val wrappedSubstitution = object : TypeSubstitution() {
override fun get(key: KotlinType): TypeProjection? = null override fun get(key: KotlinType): TypeProjection? = null
override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) = substitutor.safeSubstitute(topLevelType.unwrap()) override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) = substitutor.safeSubstitute(topLevelType.unwrap())
@@ -44,16 +46,20 @@ fun CallableDescriptor.substitute(substitutor: NewTypeSubstitutor): CallableDesc
fun CallableDescriptor.substituteAndApproximateTypes( fun CallableDescriptor.substituteAndApproximateTypes(
substitutor: NewTypeSubstitutor, substitutor: NewTypeSubstitutor,
typeApproximator: TypeApproximator? typeApproximator: TypeApproximator?,
positionDependentApproximation: Boolean = false
): CallableDescriptor { ): CallableDescriptor {
if (substitutor.isEmpty) return this
val wrappedSubstitution = object : TypeSubstitution() { val wrappedSubstitution = object : TypeSubstitution() {
override fun get(key: KotlinType): TypeProjection? = null override fun get(key: KotlinType): TypeProjection? = null
override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) = override fun prepareTopLevelType(topLevelType: KotlinType, position: Variance) =
substitutor.safeSubstitute(topLevelType.unwrap()).let { substitutedType -> substitutor.safeSubstitute(topLevelType.unwrap()).let { substitutedType ->
typeApproximator?.approximateToSuperType( typeApproximator?.approximateTo(
substitutedType, substitutedType,
TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference,
position != Variance.IN_VARIANCE || !positionDependentApproximation
) ?: substitutedType ) ?: substitutedType
} }
} }
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings 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.components.transformToResolvedLambda
import org.jetbrains.kotlin.resolve.calls.inference.model.* import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
@@ -286,7 +287,7 @@ class KotlinConstraintSystemCompleter(
diagnosticsHolder: KotlinDiagnosticsHolder, diagnosticsHolder: KotlinDiagnosticsHolder,
): ResolvedLambdaAtom { ): ResolvedLambdaAtom {
val returnVariable = TypeVariableForLambdaReturnType(candidate.callComponents.builtIns, "_R") val returnVariable = TypeVariableForLambdaReturnType(candidate.callComponents.builtIns, "_R")
val csBuilder = candidate.csBuilder val csBuilder = candidate.getSystem().getBuilder()
csBuilder.registerVariable(returnVariable) csBuilder.registerVariable(returnVariable)
val functionalType: KotlinType = csBuilder.buildCurrentSubstitutor().safeSubstitute(candidate.getSystem().asConstraintSystemCompleterContext(), atom.expectedType!!) as KotlinType val functionalType: KotlinType = csBuilder.buildCurrentSubstitutor().safeSubstitute(candidate.getSystem().asConstraintSystemCompleterContext(), atom.expectedType!!) as KotlinType
val expectedType = KotlinTypeFactory.simpleType( val expectedType = KotlinTypeFactory.simpleType(
@@ -34,6 +34,9 @@ class DeclaredUpperBoundConstraintPositionImpl(
class ArgumentConstraintPositionImpl(argument: KotlinCallArgument) : ArgumentConstraintPosition<KotlinCallArgument>(argument) class ArgumentConstraintPositionImpl(argument: KotlinCallArgument) : ArgumentConstraintPosition<KotlinCallArgument>(argument)
class CallableReferenceConstraintPositionImpl(val callableReferenceCall: CallableReferenceKotlinCall) :
CallableReferenceConstraintPosition<CallableReferenceResolutionAtom>(callableReferenceCall)
class ReceiverConstraintPositionImpl(argument: KotlinCallArgument) : ReceiverConstraintPosition<KotlinCallArgument>(argument) class ReceiverConstraintPositionImpl(argument: KotlinCallArgument) : ReceiverConstraintPosition<KotlinCallArgument>(argument)
class FixVariableConstraintPositionImpl( class FixVariableConstraintPositionImpl(
@@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.ReflectionTypes 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.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation import org.jetbrains.kotlin.resolve.calls.components.*
import org.jetbrains.kotlin.resolve.calls.model.* 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.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tower.* import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject
import org.jetbrains.kotlin.resolve.scopes.receivers.DetailedReceiver 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.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.expressions.CoercionStrategy import org.jetbrains.kotlin.types.expressions.CoercionStrategy
import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addIfNotNull
class CallableReferencesCandidateFactory( class CallableReferencesCandidateFactory(
val argument: CallableReferenceKotlinCallArgument, val kotlinCall: CallableReferenceResolutionAtom,
val callComponents: KotlinCallComponents, val callComponents: KotlinCallComponents,
val scopeTower: ImplicitScopeTower, val scopeTower: ImplicitScopeTower,
val compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit,
val expectedType: UnwrappedType?, val expectedType: UnwrappedType?,
private val csBuilder: ConstraintSystemOperation, private val baseSystem: ConstraintStorage?,
private val resolutionCallbacks: KotlinResolutionCallbacks private val resolutionCallbacks: KotlinResolutionCallbacks
) : CandidateFactory<CallableReferenceResolutionCandidate> { ) : CandidateFactory<CallableReferenceResolutionCandidate> {
// todo investigate similar code in CheckVisibility
private val CallableReceiver.asReceiverValueForVisibilityChecks: ReceiverValue
get() = receiver.receiverValue
fun createCallableProcessor(explicitReceiver: DetailedReceiver?) = override fun createErrorCandidate(): CallableReferenceResolutionCandidate {
createCallableReferenceProcessor(scopeTower, argument.rhsName, this, explicitReceiver) 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( override fun createCandidate(
towerCandidate: CandidateWithBoundDispatchReceiver, towerCandidate: CandidateWithBoundDispatchReceiver,
@@ -59,18 +77,20 @@ class CallableReferencesCandidateFactory(
dispatchCallableReceiver, dispatchCallableReceiver,
extensionCallableReceiver, extensionCallableReceiver,
expectedType, expectedType,
callComponents.builtIns callComponents.builtIns,
// conversions aren't needed for top-level callable references
buildTypeWithConversions = kotlinCall is CallableReferenceKotlinCallArgument
) )
fun createReferenceCandidate(): CallableReferenceResolutionCandidate = fun createCallableReferenceCallCandidate(diagnostics: List<KotlinCallDiagnostic>) = CallableReferenceResolutionCandidate(
CallableReferenceResolutionCandidate( candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver,
candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver, explicitReceiverKind, reflectionCandidateType, callableReferenceAdaptation,
explicitReceiverKind, reflectionCandidateType, callableReferenceAdaptation, diagnostics 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) diagnostics.add(HiddenDescriptor)
return createReferenceCandidate() return createCallableReferenceCallCandidate(diagnostics)
} }
if (needCompatibilityResolveForCallableReference(callableReferenceAdaptation, candidateDescriptor)) { if (needCompatibilityResolveForCallableReference(callableReferenceAdaptation, candidateDescriptor)) {
@@ -79,7 +99,7 @@ class CallableReferencesCandidateFactory(
if (callableReferenceAdaptation != null && expectedType != null && hasNonTrivialAdaptation(callableReferenceAdaptation)) { if (callableReferenceAdaptation != null && expectedType != null && hasNonTrivialAdaptation(callableReferenceAdaptation)) {
if (!expectedType.isFunctionType && !expectedType.isSuspendFunctionType) { // expectedType has some reflection type 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 && callableReferenceAdaptation.defaults != 0 &&
!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.FunctionReferenceWithDefaultValueAsOtherType) !callComponents.languageVersionSettings.supportsFeature(LanguageFeature.FunctionReferenceWithDefaultValueAsOtherType)
) { ) {
diagnostics.add(CallableReferencesDefaultArgumentUsed(argument, candidateDescriptor, callableReferenceAdaptation.defaults)) diagnostics.add(CallableReferencesDefaultArgumentUsed(kotlinCall, candidateDescriptor, callableReferenceAdaptation.defaults))
} }
if (candidateDescriptor !is CallableMemberDescriptor) { if (candidateDescriptor !is CallableMemberDescriptor) {
return CallableReferenceResolutionCandidate( return createCallableReferenceCallCandidate(listOf(NotCallableMemberReference(kotlinCall, candidateDescriptor)))
candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver,
explicitReceiverKind, reflectionCandidateType, callableReferenceAdaptation,
listOf(NotCallableMemberReference(argument, candidateDescriptor))
)
} }
diagnostics.addAll(towerCandidate.diagnostics) diagnostics.addAll(towerCandidate.diagnostics)
// todo smartcast on receiver diagnostic and CheckInstantiationOfAbstractClass // todo smartcast on receiver diagnostic and CheckInstantiationOfAbstractClass
compatibilityChecker { return createCallableReferenceCallCandidate(diagnostics)
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()
} }
fun createCallableProcessor(explicitReceiver: DetailedReceiver?) =
createCallableReferenceProcessor(scopeTower, kotlinCall.rhsName, this, explicitReceiver)
private fun needCompatibilityResolveForCallableReference( private fun needCompatibilityResolveForCallableReference(
callableReferenceAdaptation: CallableReferenceAdaptation?, callableReferenceAdaptation: CallableReferenceAdaptation?,
candidate: CallableDescriptor candidate: CallableDescriptor
): Boolean { ): Boolean {
// KT-13934: reference to companion object member via class name // 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 if (callableReferenceAdaptation == null) return false
@@ -142,19 +141,13 @@ class CallableReferencesCandidateFactory(
callableReferenceAdaptation.coercionStrategy != CoercionStrategy.NO_COERCION || callableReferenceAdaptation.coercionStrategy != CoercionStrategy.NO_COERCION ||
callableReferenceAdaptation.mappedArguments.values.any { it is ResolvedCallArgument.VarargArgument } callableReferenceAdaptation.mappedArguments.values.any { it is ResolvedCallArgument.VarargArgument }
private enum class VarargMappingState {
UNMAPPED, MAPPED_WITH_PLAIN_ARGS, MAPPED_WITH_ARRAY
}
private fun getCallableReferenceAdaptation( private fun getCallableReferenceAdaptation(
descriptor: FunctionDescriptor, descriptor: FunctionDescriptor,
expectedType: UnwrappedType?, expectedType: UnwrappedType?,
unboundReceiverCount: Int, unboundReceiverCount: Int,
builtins: KotlinBuiltIns builtins: KotlinBuiltIns
): CallableReferenceAdaptation? { ): CallableReferenceAdaptation? {
if (callComponents.languageVersionSettings.apiVersion < ApiVersion.KOTLIN_1_4) return null if (expectedType == null || TypeUtils.noExpectedType(expectedType)) return null
if (expectedType == null) return null
// Do not adapt references against KCallable type as it's impossible to map defaults/vararg to absent parameters of KCallable // 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 if (ReflectionTypes.hasKCallableTypeFqName(expectedType)) return null
@@ -302,7 +295,7 @@ class CallableReferencesCandidateFactory(
return when (varargMappingState) { return when (varargMappingState) {
VarargMappingState.UNMAPPED -> { VarargMappingState.UNMAPPED -> {
if (KotlinBuiltIns.isArrayOrPrimitiveArray(expectedParameterType) || if (KotlinBuiltIns.isArrayOrPrimitiveArray(expectedParameterType) ||
csBuilder.isTypeVariable(expectedParameterType) expectedParameterType.constructor is TypeVariableTypeConstructor
) { ) {
val arrayType = builtins.getPrimitiveArrayKotlinTypeByPrimitiveKotlinType(elementType) val arrayType = builtins.getPrimitiveArrayKotlinTypeByPrimitiveKotlinType(elementType)
?: builtins.getArrayType(Variance.OUT_VARIANCE, elementType) ?: builtins.getArrayType(Variance.OUT_VARIANCE, elementType)
@@ -327,7 +320,8 @@ class CallableReferencesCandidateFactory(
dispatchReceiver: CallableReceiver?, dispatchReceiver: CallableReceiver?,
extensionReceiver: CallableReceiver?, extensionReceiver: CallableReceiver?,
expectedType: UnwrappedType?, expectedType: UnwrappedType?,
builtins: KotlinBuiltIns builtins: KotlinBuiltIns,
buildTypeWithConversions: Boolean = true
): Pair<UnwrappedType, CallableReferenceAdaptation?> { ): Pair<UnwrappedType, CallableReferenceAdaptation?> {
val argumentsAndReceivers = ArrayList<KotlinType>(descriptor.valueParameters.size + 2) val argumentsAndReceivers = ArrayList<KotlinType>(descriptor.valueParameters.size + 2)
@@ -365,7 +359,7 @@ class CallableReferencesCandidateFactory(
builtins = builtins builtins = builtins
) )
val returnType = if (callableReferenceAdaptation == null) { val returnType = if (callableReferenceAdaptation == null || !buildTypeWithConversions) {
descriptor.valueParameters.mapTo(argumentsAndReceivers) { it.type } descriptor.valueParameters.mapTo(argumentsAndReceivers) { it.type }
descriptorReturnType descriptorReturnType
} else { } else {
@@ -380,7 +374,8 @@ class CallableReferencesCandidateFactory(
} }
val suspendConversionStrategy = callableReferenceAdaptation?.suspendConversionStrategy val suspendConversionStrategy = callableReferenceAdaptation?.suspendConversionStrategy
val isSuspend = descriptor.isSuspend || suspendConversionStrategy == SuspendConversionStrategy.SUSPEND_CONVERSION val isSuspend = descriptor.isSuspend ||
(suspendConversionStrategy == SuspendConversionStrategy.SUSPEND_CONVERSION && buildTypeWithConversions)
callComponents.reflectionTypes.getKFunctionType( callComponents.reflectionTypes.getKFunctionType(
Annotations.EMPTY, null, argumentsAndReceivers, null, Annotations.EMPTY, null, argumentsAndReceivers, null,
@@ -397,7 +392,7 @@ class CallableReferencesCandidateFactory(
private fun toCallableReceiver(receiver: ReceiverValueWithSmartCastInfo, isExplicit: Boolean): CallableReceiver { private fun toCallableReceiver(receiver: ReceiverValueWithSmartCastInfo, isExplicit: Boolean): CallableReceiver {
if (!isExplicit) return CallableReceiver.ScopeReceiver(receiver) 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.Expression -> CallableReceiver.ExplicitValueReceiver(receiver)
is LHSResult.Type -> { is LHSResult.Type -> {
if (lhsResult.qualifier?.classValueReceiver?.type == receiver.receiverValue.type) { if (lhsResult.qualifier?.classValueReceiver?.type == receiver.receiverValue.type) {
@@ -410,4 +405,8 @@ class CallableReferencesCandidateFactory(
else -> throw IllegalStateException("Unsupported kind of lhsResult: $lhsResult") 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") KotlinCallKind.UNSUPPORTED -> error("Call with UNSUPPORTED kind")
} }
} }
@@ -34,6 +34,18 @@ abstract class InapplicableArgumentDiagnostic : KotlinCallDiagnostic(INAPPLICABL
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this) 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 // ArgumentsToParameterMapper
class TooManyArguments(val argument: KotlinCallArgument, val descriptor: CallableDescriptor) : class TooManyArguments(val argument: KotlinCallArgument, val descriptor: CallableDescriptor) :
KotlinCallDiagnostic(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR) { KotlinCallDiagnostic(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR) {
@@ -99,38 +111,40 @@ class WrongCountOfTypeArguments(
// Callable reference resolution // Callable reference resolution
class CallableReferenceNotCompatible( class CallableReferenceNotCompatible(
override val argument: CallableReferenceKotlinCallArgument, argument: CallableReferenceResolutionAtom,
val candidate: CallableMemberDescriptor, val candidate: CallableMemberDescriptor,
val expectedType: UnwrappedType?, val expectedType: UnwrappedType?,
val callableReverenceType: UnwrappedType val callableReverenceType: UnwrappedType
) : InapplicableArgumentDiagnostic() ) : CallableReferenceInapplicableDiagnostic(argument)
// supported by FE but not supported by BE now // supported by FE but not supported by BE now
class CallableReferencesDefaultArgumentUsed( class CallableReferencesDefaultArgumentUsed(
val argument: CallableReferenceKotlinCallArgument, val argument: CallableReferenceResolutionAtom,
val candidate: CallableDescriptor, val candidate: CallableDescriptor,
val defaultsCount: Int val defaultsCount: Int
) : KotlinCallDiagnostic(IMPOSSIBLE_TO_GENERATE) { ) : CallableReferenceInapplicableDiagnostic(argument)
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this)
}
class NotCallableMemberReference( class NotCallableMemberReference(
override val argument: CallableReferenceKotlinCallArgument, val argument: CallableReferenceResolutionAtom,
val candidate: CallableDescriptor val candidate: CallableDescriptor
) : InapplicableArgumentDiagnostic() ) : CallableReferenceInapplicableDiagnostic(argument)
class NoneCallableReferenceCandidates(override val argument: CallableReferenceKotlinCallArgument) : InapplicableArgumentDiagnostic() class NoneCallableReferenceCallCandidates(val argument: CallableReferenceKotlinCallArgument) :
CallableReferenceInapplicableDiagnostic(argument)
class CallableReferenceCandidatesAmbiguity( class CallableReferenceCallCandidatesAmbiguity(
override val argument: CallableReferenceKotlinCallArgument, val argument: CallableReferenceKotlinCallArgument,
val candidates: Collection<CallableReferenceCandidate> val candidates: Collection<CallableReferenceResolutionCandidate>
) : InapplicableArgumentDiagnostic() ) : CallableReferenceInapplicableDiagnostic(argument)
class NotCallableExpectedType( class NotCallableExpectedType(
override val argument: CallableReferenceKotlinCallArgument, val argument: CallableReferenceKotlinCallArgument,
val expectedType: UnwrappedType, val expectedType: UnwrappedType,
val notCallableTypeConstructor: TypeConstructor val notCallableTypeConstructor: TypeConstructor
) : InapplicableArgumentDiagnostic() ) : CallableReferenceInapplicableDiagnostic(argument)
class AdaptedCallableReferenceIsUsedWithReflection(val argument: CallableReferenceResolutionAtom) :
CallableReferenceInapplicableDiagnostic(argument, RESOLVED_WITH_ERROR)
// SmartCasts // SmartCasts
class SmartCastDiagnostic( 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( class KotlinConstraintSystemDiagnostic(
val error: ConstraintSystemError val error: ConstraintSystemError
) : KotlinCallDiagnostic(error.applicability) { ) : KotlinCallDiagnostic(error.applicability) {
@@ -58,6 +58,16 @@ enum class KotlinCallKind(vararg resolutionPart: ResolutionPart) {
PostponedVariablesInitializerResolutionPart PostponedVariablesInitializerResolutionPart
), ),
INVOKE(*FUNCTION.resolutionSequence.toTypedArray()), INVOKE(*FUNCTION.resolutionSequence.toTypedArray()),
CALLABLE_REFERENCE(
CheckVisibility,
NoTypeArguments,
NoArguments,
CreateFreshVariablesSubstitutor,
CollectionTypeVariableUsagesInfo,
CheckReceivers,
CheckCallableReference,
CompatibilityOfTypeVariableAsIntersectionTypePart
),
UNSUPPORTED(); UNSUPPORTED();
val resolutionSequence = resolutionPart.asList() val resolutionSequence = resolutionPart.asList()
@@ -81,7 +81,9 @@ open class MutableResolvedCallAtom(
override val candidateDescriptor: CallableDescriptor, // original candidate descriptor override val candidateDescriptor: CallableDescriptor, // original candidate descriptor
override val explicitReceiverKind: ExplicitReceiverKind, override val explicitReceiverKind: ExplicitReceiverKind,
override val dispatchReceiverArgument: SimpleKotlinCallArgument?, override val dispatchReceiverArgument: SimpleKotlinCallArgument?,
override val extensionReceiverArgument: SimpleKotlinCallArgument? override val extensionReceiverArgument: SimpleKotlinCallArgument?,
open val reflectionCandidateType: UnwrappedType? = null,
open val candidate: CallableReferenceResolutionCandidate? = null
) : ResolvedCallAtom() { ) : ResolvedCallAtom() {
override lateinit var typeArgumentMappingByOriginal: TypeArgumentsToParametersMapper.TypeArgumentsMapping override lateinit var typeArgumentMappingByOriginal: TypeArgumentsToParametersMapper.TypeArgumentsMapping
override lateinit var argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument> override lateinit var argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
@@ -45,4 +45,7 @@ class TypeApproximator(
// resultType <: type // resultType <: type
fun approximateToSubType(type: UnwrappedType, conf: TypeApproximatorConfiguration): UnwrappedType? = fun approximateToSubType(type: UnwrappedType, conf: TypeApproximatorConfiguration): UnwrappedType? =
super.approximateToSubType(type, conf) as 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)
} }
@@ -19,8 +19,21 @@ val j1: J<String> = Impl("O")
// would produce an error. // would produce an error.
val x by j1::value val x by j1::value
@Target(AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.EXPRESSION, AnnotationTarget.FILE)
@Retention(AnnotationRetention.SOURCE)
annotation class Anno
fun box(): String { fun box(): String {
val j2: J<String> = Impl("K") val j2: J<String> = Impl("K")
val y by j2::value 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 return x + y
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS
fun box(): String { fun box(): String {
val z = "K" val z = "K"
open class A(val x: String) { open class A(val x: String) {
@@ -37,5 +37,5 @@ fun test() {
val r7 = c::foo val r7 = c::foo
checkSubtype<() -> String>(r7) checkSubtype<() -> String>(r7)
C::<!UNRESOLVED_REFERENCE!>bar<!> C::bar
} }
@@ -6,10 +6,10 @@ public interface J {
// FILE: test.kt // FILE: test.kt
fun f1(x: Int?): Any = x::<!UNSAFE_CALL!>hashCode<!> fun f1(x: Int?): Any = x::<!TYPE_MISMATCH, UNSAFE_CALL!>hashCode<!>
fun <T> f2(t: T): Any = t::<!UNSAFE_CALL!>hashCode<!> fun <T> f2(t: T): Any = t::<!TYPE_MISMATCH, UNSAFE_CALL!>hashCode<!>
fun <S : String?> f3(s: S): Any = s::<!UNSAFE_CALL!>hashCode<!> fun <S : String?> f3(s: S): Any = s::<!TYPE_MISMATCH, UNSAFE_CALL!>hashCode<!>
fun <U : Any> f4(u: U?): Any = u::<!UNSAFE_CALL!>hashCode<!> fun <U : Any> f4(u: U?): Any = u::<!TYPE_MISMATCH, UNSAFE_CALL!>hashCode<!>
fun f5(c: List<*>): Any = c[0]::<!UNSAFE_CALL!>hashCode<!> fun f5(c: List<*>): Any = c[0]::<!TYPE_MISMATCH, UNSAFE_CALL!>hashCode<!>
fun f6(j: J): Any = j.platformString()::hashCode fun f6(j: J): Any = j.platformString()::hashCode
@@ -18,9 +18,9 @@ class Test {
val <T> List<T>.b: Int? get() = size 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>.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>.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><!>::<!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><!>?::<!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>.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 fun <T> List<T>.testClassLiteral2() = <!EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS, RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS!>b<!>?::class
@@ -4,4 +4,4 @@ package test
fun nullableFun(): Int? = null fun nullableFun(): Int? = null
fun Int.foo() {} 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<!>
@@ -1,8 +1,11 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
fun <K> id(x: K) = x
class A1 { class A1 {
fun <T> a1(t: T): Unit {} fun <T> a1(t: T): Unit {}
fun test1(): (String) -> Unit = A1()::a1 fun test1(): (String) -> Unit = A1()::a1
fun test2(): (String) -> Unit = id(A1()::a1)
} }
class A2 { class A2 {
@@ -1,8 +1,11 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
fun <K> id(x: K) = x
class A1 { class A1 {
fun <T> a1(t: T): Unit {} fun <T> a1(t: T): Unit {}
fun test1(): (String) -> Unit = A1()::a1 fun test1(): (String) -> Unit = A1()::a1
fun test2(): (String) -> Unit = id(A1()::a1)
} }
class A2 { class A2 {
@@ -19,6 +22,6 @@ class A3<T> {
fun test2(): (T) -> Unit = A3<T>()::a3 fun test2(): (T) -> Unit = A3<T>()::a3
fun test3(): (Int) -> String = A3<Int>()::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 fun <R> test5(): (T) -> R = this::a3
} }
@@ -1,11 +1,14 @@
package package
public fun </*0*/ K> id(/*0*/ x: K): K
public final class A1 { public final class A1 {
public constructor A1() public constructor A1()
public final fun </*0*/ T> a1(/*0*/ t: T): kotlin.Unit 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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun test1(): (kotlin.String) -> kotlin.Unit 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 public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
@@ -5,5 +5,5 @@ class Foo {
} }
fun test() { 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)<!>
} }
@@ -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)
}
@@ -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<!>)
}
@@ -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 // It must be OK
val x18 = String?::hashCode <!USELESS_ELVIS!>?: ::foo<!> val x18 = String?::hashCode <!USELESS_ELVIS!>?: ::foo<!>
val x19 = String::hashCode <!USELESS_ELVIS!>?: ::foo<!> val x19 = String::hashCode <!USELESS_ELVIS!>?: ::foo<!>
val x20 = String?::<!UNSAFE_CALL!>hashCode<!>::hashCode val x20 = String?::hashCode::hashCode
val x21 = kotlin.String?::<!UNSAFE_CALL!>hashCode<!>::hashCode val x21 = kotlin.String?::hashCode::hashCode
} }
@@ -381,7 +381,7 @@ fun poll65(): Flow<String> {
fun poll66(): Flow<String> { fun poll66(): Flow<String> {
return flow { 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<!> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>inv<!>
} }
} }
@@ -383,7 +383,7 @@ fun poll65(): Flow<String> {
fun poll66(): Flow<String> { fun poll66(): Flow<String> {
return flow { 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<!> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>inv<!>
} }
} }
@@ -23,38 +23,57 @@ fun <T> Foo2<T>.setX(y: T): T {
fun Float.bar() {} fun Float.bar() {}
fun <K> id(x: K) = x
fun test1() { fun test1() {
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, CapturedType(*), CapturedType(*)>")!>Foo<*>::setX<!> 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) val foo = Foo<Float>(1f)
fooSetRef.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>1<!>) fooSetRef.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>1<!>)
fooSetRef2.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>1<!>)
foo.x.bar() foo.x.bar()
} }
fun test2() { fun test2() {
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, CapturedType(*), CapturedType(*)>")!>Foo<*>::setX1<!> 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) val foo = Foo<Float>(1f)
fooSetRef.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>1<!>) fooSetRef.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>1<!>)
fooSetRef2.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>1<!>)
foo.x.bar() foo.x.bar()
} }
fun test3() { fun test3() {
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, CapturedType(*), CapturedType(*)>")!>Foo2<*>::setX<!> 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) val foo = Foo2<Int>(1)
fooSetRef.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>""<!>) fooSetRef.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>""<!>)
fooSetRef2.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>""<!>)
foo.x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>bar<!>() foo.x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>bar<!>()
} }
fun test4() { fun test4() {
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, CapturedType(*), CapturedType(*)>")!>Foo2<*>::setX1<!> 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) val foo = Foo2<Int>(1)
fooSetRef.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>""<!>) fooSetRef.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>""<!>)
fooSetRef2.invoke(foo, <!ARGUMENT_TYPE_MISMATCH!>""<!>)
foo.x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>bar<!>() foo.x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>bar<!>()
} }
@@ -23,38 +23,57 @@ fun <T> Foo2<T>.setX(y: T): T {
fun Float.bar() {} fun Float.bar() {}
fun <K> id(x: K) = x
fun test1() { 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) val foo = Foo<Float>(1f)
fooSetRef.invoke(foo, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>) fooSetRef.invoke(foo, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
fooSetRef2.invoke(foo, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
foo.x.bar() foo.x.bar()
} }
fun test2() { fun test2() {
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo<*>, kotlin.Nothing, kotlin.Number>")!>Foo<*>::setX1<!> 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) val foo = Foo<Float>(1f)
fooSetRef.invoke(foo, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>) fooSetRef.invoke(foo, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
fooSetRef2.invoke(foo, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
foo.x.bar() foo.x.bar()
} }
fun test3() { 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) val foo = Foo2<Int>(1)
fooSetRef.invoke(foo, <!TYPE_MISMATCH!>""<!>) fooSetRef.invoke(foo, <!TYPE_MISMATCH!>""<!>)
fooSetRef2.invoke(foo, <!TYPE_MISMATCH!>""<!>)
foo.x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>bar<!>() foo.x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>bar<!>()
} }
fun test4() { fun test4() {
val fooSetRef = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<Foo2<*>, kotlin.Nothing, kotlin.Any?>")!>Foo2<*>::setX1<!> 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) val foo = Foo2<Int>(1)
fooSetRef.invoke(foo, <!TYPE_MISMATCH!>""<!>) fooSetRef.invoke(foo, <!TYPE_MISMATCH!>""<!>)
fooSetRef2.invoke(foo, <!TYPE_MISMATCH!>""<!>)
foo.x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>bar<!>() foo.x.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>bar<!>()
} }
@@ -1,5 +1,6 @@
package package
public fun </*0*/ K> id(/*0*/ x: K): K
public fun test1(): kotlin.Unit public fun test1(): kotlin.Unit
public fun test2(): kotlin.Unit public fun test2(): kotlin.Unit
public fun test3(): kotlin.Unit public fun test3(): kotlin.Unit
+4 -4
View File
@@ -114,14 +114,14 @@ fun <T : Foo, R: Number, D: Int> main() {
bar7(Foo::resolve) // OK bar7(Foo::resolve) // OK
// with LHS and sentension function expected type // 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>(Int::x1) // OK
bar10(Int::x1) // OK bar10(Int::x1) // OK
fun Int.ext() { fun Int.ext() {
// with LHS and sentension function expected type // with LHS and sentension function expected type
bar10<D>(::<!CALLABLE_REFERENCE_RESOLUTION_AMBIGUITY!>x1<!>) // ERROR before the fix in NI bar10<D>(<!TYPE_MISMATCH("KProperty1<TypeVariable(K), String>; KProperty0<String>")!>::x1<!>) // ERROR before the fix in NI
bar10<Int>(::<!CALLABLE_REFERENCE_RESOLUTION_AMBIGUITY!>x1<!>) // OK bar10<Int>(<!TYPE_MISMATCH("KProperty1<TypeVariable(K), String>; KProperty0<String>")!>::x1<!>) // OK
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>bar10<!>(::<!CALLABLE_REFERENCE_RESOLUTION_AMBIGUITY!>x1<!>) // OK bar10(<!TYPE_MISMATCH("KProperty1<TypeVariable(K), String>; KProperty0<String>")!>::x1<!>) // OK
} }
} }
@@ -9,8 +9,8 @@ class Foo7<T>
fun foo7() = null as Foo7<Int> fun foo7() = null as Foo7<Int>
fun poll17(flag: Boolean): Any? { fun poll17(flag: Boolean): Any? {
val inv = if (flag) { foo7() } else { <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>::Foo7<!> } val inv = if (flag) { <!IMPLICIT_CAST_TO_ANY!>foo7()<!> } else { <!IMPLICIT_CAST_TO_ANY!>::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Foo7<!><!> }
return <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>inv<!> return inv
} }
fun poll26(flag: Boolean): Any? { fun poll26(flag: Boolean): Any? {
@@ -24,6 +24,6 @@ fun poll36(flag: Boolean): Any? {
} }
fun poll56(): Any? { fun poll56(): Any? {
val inv = try { <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>::Foo7<!> } catch (e: Exception) { foo7() } finally { foo7() } val inv = try { ::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Foo7<!> } catch (e: Exception) { foo7() } finally { foo7() }
return <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>inv<!> return inv
} }
@@ -18,6 +18,11 @@ class Foo6
class Foo7<T> class Foo7<T>
fun foo7() = null as Foo7<Int> 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) { fun poll1(flag: Boolean) {
val inv = if (flag) { ::bar2 } else { ::foo2 } val inv = if (flag) { ::bar2 } else { ::foo2 }
inv() inv()
@@ -18,6 +18,11 @@ class Foo6
class Foo7<T> class Foo7<T>
fun foo7() = null as Foo7<Int> 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) { fun poll1(flag: Boolean) {
val inv = if (flag) { ::bar2 } else { ::foo2 } val inv = if (flag) { ::bar2 } else { ::foo2 }
inv() inv()
@@ -39,7 +44,7 @@ fun poll13(flag: Boolean) {
} }
fun poll14(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<!>() <!DEBUG_INFO_MISSING_UNRESOLVED!>inv<!>()
} }
@@ -54,8 +59,8 @@ fun poll16(flag: Boolean) {
} }
fun poll17(flag: Boolean) { fun poll17(flag: Boolean) {
val inv = if (flag) { foo7() } else { <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>::Foo7<!> } val inv = if (flag) { <!IMPLICIT_CAST_TO_ANY!>foo7()<!> } else { <!IMPLICIT_CAST_TO_ANY!>::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Foo7<!><!> }
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>inv<!> inv
} }
fun poll2(flag: Boolean) { fun poll2(flag: Boolean) {
@@ -144,7 +149,7 @@ fun poll42() {
} }
fun poll43() { 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<!>() <!DEBUG_INFO_MISSING_UNRESOLVED!>inv<!>()
} }
@@ -159,7 +164,7 @@ fun poll45() {
} }
fun poll46() { 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 inv
} }
@@ -179,7 +184,7 @@ fun poll52() {
} }
fun poll53() { 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<!>() <!DEBUG_INFO_MISSING_UNRESOLVED!>inv<!>()
} }
@@ -194,8 +199,8 @@ fun poll55() {
} }
fun poll56() { fun poll56() {
val inv = try { <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>::Foo7<!> } catch (e: Exception) { foo7() } finally { foo7() } val inv = try { ::<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Foo7<!> } catch (e: Exception) { foo7() } finally { foo7() }
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>inv<!> inv
} }
fun poll6() { fun poll6() {
@@ -214,7 +219,7 @@ fun poll62() {
} }
fun poll63() { 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<!> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>inv<!>
} }
@@ -229,7 +234,7 @@ fun poll65() {
} }
fun poll66() { 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<!> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>inv<!>
} }
@@ -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
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: -ProhibitVisibilityOfNestedClassifiersFromSupertypesOfCompanion // !LANGUAGE: -ProhibitVisibilityOfNestedClassifiersFromSupertypesOfCompanion
import A.Base.Companion.FromABaseCompanion import A.Base.Companion.FromABaseCompanion
@@ -53,7 +54,7 @@ object C {
} }
class Derived : Base() { class Derived : Base() {
val a = FromCBaseCompanion::<!UNRESOLVED_REFERENCE!>foo<!> val a = FromCBaseCompanion::foo
} }
} }
@@ -118,7 +118,7 @@ public object C {
public final class Derived : C.Base { public final class Derived : C.Base {
public constructor Derived() 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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
@@ -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
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: -ProhibitVisibilityOfNestedClassifiersFromSupertypesOfCompanion // !LANGUAGE: -ProhibitVisibilityOfNestedClassifiersFromSupertypesOfCompanion
// ===== Case 1: LHS is a class // ===== Case 1: LHS is a class
@@ -48,7 +49,7 @@ object C {
} }
class Derived : Base() { class Derived : Base() {
val a = C.Base.Companion.FromBaseCompanion::<!UNRESOLVED_REFERENCE!>foo<!> val a = C.Base.Companion.FromBaseCompanion::foo
} }
} }
@@ -118,7 +118,7 @@ public object C {
public final class Derived : C.Base { public final class Derived : C.Base {
public constructor Derived() 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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
@@ -48,7 +48,7 @@ object C {
} }
class Derived : Base() { class Derived : Base() {
val a = <!DEPRECATED_ACCESS_BY_SHORT_NAME!>FromBaseCompanion<!>::<!UNRESOLVED_REFERENCE!>foo<!> val a = <!DEPRECATED_ACCESS_BY_SHORT_NAME!>FromBaseCompanion<!>::foo
} }
} }
@@ -118,7 +118,7 @@ public object C {
public final class Derived : C.Base { public final class Derived : C.Base {
public constructor Derived() 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 equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
@@ -42,7 +42,7 @@ fun box() {
println(::<!CALL_TO_JS_MODULE_WITHOUT_MODULE_SYSTEM!>bar<!>.name) 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!>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<!>() B.<!CALL_TO_JS_MODULE_WITHOUT_MODULE_SYSTEM!>Nested<!>()
@@ -36,7 +36,7 @@ fun box() {
B.<!CALL_TO_JS_NON_MODULE_WITH_MODULE_SYSTEM!>Nested<!>() 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!>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) boo<<!CALL_TO_JS_NON_MODULE_WITH_MODULE_SYSTEM!>B?<!>>(null)
<!CALL_TO_JS_NON_MODULE_WITH_MODULE_SYSTEM!>boo<!>(null as B?) <!CALL_TO_JS_NON_MODULE_WITH_MODULE_SYSTEM!>boo<!>(null as B?)
@@ -1,10 +1,10 @@
fun f(x: Any): String { fun f(x: Any): String {
when { when {
x is A<*> -> { // BLOCK 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" return "OK"
} }
/*-> @FlexibleNullability I<@FlexibleNullability T?>? */) /*!! String */ /*-> @FlexibleNullability I<Nothing>? */) /*!! String */
} }
} }
return "Fail" 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>' 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 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 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> $this: TYPE_OP type=<root>.A<*> origin=IMPLICIT_CAST typeOperand=<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
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>?
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?>?
FUN_EXPR type=kotlin.Function1<kotlin.Any?, @[FlexibleNullability] kotlin.String?> origin=LAMBDA 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? 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? VALUE_PARAMETER name:y index:0 type:kotlin.Any?
@@ -8,7 +8,6 @@ class A {
Resolved call: Resolved call:
Candidate descriptor: constructor B(arg: String) defined in A.B
Resulting descriptor: constructor B(arg: String) defined in A.B Resulting descriptor: constructor B(arg: String) defined in A.B
Explicit receiver kind = DISPATCH_RECEIVER Explicit receiver kind = DISPATCH_RECEIVER
@@ -9,7 +9,6 @@ class A {
Resolved call: Resolved call:
Candidate descriptor: constructor B(x: String) defined in A.B
Resulting descriptor: constructor B(x: String) defined in A.B Resulting descriptor: constructor B(x: String) defined in A.B
Explicit receiver kind = DISPATCH_RECEIVER Explicit receiver kind = DISPATCH_RECEIVER
@@ -8,7 +8,6 @@ class A : B, C {
Resolved call: Resolved call:
Candidate descriptor: constructor B(x: Int) defined in B
Resulting descriptor: constructor B(x: Int) defined in B Resulting descriptor: constructor B(x: Int) defined in B
Explicit receiver kind = NO_EXPLICIT_RECEIVER Explicit receiver kind = NO_EXPLICIT_RECEIVER
@@ -8,7 +8,6 @@ class A : B, C {
Resolved call: Resolved call:
Candidate descriptor: constructor B() defined in B
Resulting descriptor: constructor B() defined in B Resulting descriptor: constructor B() defined in B
Explicit receiver kind = NO_EXPLICIT_RECEIVER Explicit receiver kind = NO_EXPLICIT_RECEIVER
@@ -8,7 +8,6 @@ class A : B, C {
Resolved call: Resolved call:
Candidate descriptor: constructor B() defined in B
Resulting descriptor: constructor B() defined in B Resulting descriptor: constructor B() defined in B
Explicit receiver kind = NO_EXPLICIT_RECEIVER Explicit receiver kind = NO_EXPLICIT_RECEIVER
@@ -10,7 +10,6 @@ class A : B, C {
Resolved call: Resolved call:
Candidate descriptor: constructor B(x: Int) defined in B
Resulting descriptor: constructor B(x: Int) defined in B Resulting descriptor: constructor B(x: Int) defined in B
Explicit receiver kind = NO_EXPLICIT_RECEIVER Explicit receiver kind = NO_EXPLICIT_RECEIVER
@@ -10,7 +10,6 @@ class A : B, C {
Resolved call: Resolved call:
Candidate descriptor: constructor B() defined in B
Resulting descriptor: constructor B() defined in B Resulting descriptor: constructor B() defined in B
Explicit receiver kind = NO_EXPLICIT_RECEIVER Explicit receiver kind = NO_EXPLICIT_RECEIVER
@@ -11,7 +11,6 @@ class A : B, C {
Resolved call: Resolved call:
Candidate descriptor: constructor B(x: String) defined in B
Resulting descriptor: constructor B(x: String) defined in B Resulting descriptor: constructor B(x: String) defined in B
Explicit receiver kind = NO_EXPLICIT_RECEIVER Explicit receiver kind = NO_EXPLICIT_RECEIVER
@@ -6,7 +6,6 @@ class A(x: Int) {
Resolved call: Resolved call:
Candidate descriptor: constructor A(x: Int) defined in A
Resulting descriptor: constructor A(x: Int) defined in A Resulting descriptor: constructor A(x: Int) defined in A
Explicit receiver kind = NO_EXPLICIT_RECEIVER Explicit receiver kind = NO_EXPLICIT_RECEIVER
@@ -7,7 +7,6 @@ class A {
Resolved call: Resolved call:
Candidate descriptor: constructor A(x: Int) defined in A
Resulting descriptor: constructor A(x: Int) defined in A Resulting descriptor: constructor A(x: Int) defined in A
Explicit receiver kind = NO_EXPLICIT_RECEIVER Explicit receiver kind = NO_EXPLICIT_RECEIVER
@@ -8,7 +8,6 @@ class A(x: Double) {
Resolved call: Resolved call:
Candidate descriptor: constructor A(x: String) defined in A
Resulting descriptor: constructor A(x: String) defined in A Resulting descriptor: constructor A(x: String) defined in A
Explicit receiver kind = NO_EXPLICIT_RECEIVER Explicit receiver kind = NO_EXPLICIT_RECEIVER
@@ -10,7 +10,6 @@ class A : B {
Resolved call: Resolved call:
Candidate descriptor: constructor B(vararg x: Int) defined in B
Resulting 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 Explicit receiver kind = NO_EXPLICIT_RECEIVER
@@ -7,7 +7,6 @@ fun test() {
Resolved call: 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 Resulting descriptor: fun foo(f: (Int) -> String): Unit defined in root package
Explicit receiver kind = NO_EXPLICIT_RECEIVER Explicit receiver kind = NO_EXPLICIT_RECEIVER
@@ -5,7 +5,6 @@ annotation class MyA(val i: Int)
Resolved call: Resolved call:
Candidate descriptor: constructor MyA(i: Int) defined in MyA
Resulting descriptor: constructor MyA(i: Int) defined in MyA Resulting descriptor: constructor MyA(i: Int) defined in MyA
Explicit receiver kind = NO_EXPLICIT_RECEIVER Explicit receiver kind = NO_EXPLICIT_RECEIVER
@@ -5,7 +5,6 @@ class B: <caret>A() {}
Resolved call: Resolved call:
Candidate descriptor: constructor A() defined in A
Resulting descriptor: constructor A() defined in A Resulting descriptor: constructor A() defined in A
Explicit receiver kind = NO_EXPLICIT_RECEIVER Explicit receiver kind = NO_EXPLICIT_RECEIVER
@@ -5,7 +5,6 @@ fun foo(array: Array<Int>) {
Resolved call: 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 Resulting descriptor: operator fun get(index: Int): Int defined in kotlin.Array
Explicit receiver kind = DISPATCH_RECEIVER Explicit receiver kind = DISPATCH_RECEIVER
@@ -6,7 +6,6 @@ fun bar(f: Int.()->Unit) {
Resolved call: Resolved call:
Candidate descriptor: operator fun Int.invoke(): Unit defined in kotlin.Function1
Resulting 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 Explicit receiver kind = BOTH_RECEIVERS
@@ -6,7 +6,6 @@ fun bar(f: ()->Unit) {
Resolved call: Resolved call:
Candidate descriptor: operator fun invoke(): Unit defined in kotlin.Function0
Resulting descriptor: operator fun invoke(): Unit defined in kotlin.Function0 Resulting descriptor: operator fun invoke(): Unit defined in kotlin.Function0
Explicit receiver kind = DISPATCH_RECEIVER Explicit receiver kind = DISPATCH_RECEIVER
@@ -10,7 +10,6 @@ interface A {
Resolved call: Resolved call:
Candidate descriptor: operator fun Int.invoke(): Unit defined in kotlin.Function1
Resulting 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 Explicit receiver kind = BOTH_RECEIVERS
@@ -9,7 +9,6 @@ fun test(a: A) {
Resolved call: Resolved call:
Candidate descriptor: operator fun invoke(Int): Int defined in kotlin.Function1
Resulting 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 Explicit receiver kind = DISPATCH_RECEIVER
@@ -6,7 +6,6 @@ fun bar(f: Int.() -> Unit) {
Resolved call: Resolved call:
Candidate descriptor: operator fun Int.invoke(): Unit defined in kotlin.Function1
Resulting 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 Explicit receiver kind = BOTH_RECEIVERS
@@ -8,7 +8,6 @@ fun bar(f: Int.() -> Unit, i: Int) {
Resolved call: Resolved call:
Candidate descriptor: operator fun Int.invoke(): Unit defined in kotlin.Function1
Resulting 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 Explicit receiver kind = DISPATCH_RECEIVER
@@ -9,7 +9,6 @@ fun test() = A<caret>(1)
Resolved call: Resolved call:
Candidate descriptor: fun invoke(i: Int): Int defined in A.Companion
Resulting 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 Explicit receiver kind = DISPATCH_RECEIVER
@@ -10,7 +10,6 @@ fun test() = A.ONE<caret>(1)
Resolved call: Resolved call:
Candidate descriptor: fun invoke(i: Int): Int defined in A
Resulting descriptor: fun invoke(i: Int): Int defined in A Resulting descriptor: fun invoke(i: Int): Int defined in A
Explicit receiver kind = DISPATCH_RECEIVER Explicit receiver kind = DISPATCH_RECEIVER

Some files were not shown because too many files have changed in this diff Show More