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

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