diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.kt index fd1be9f2175..5905a3151fd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.kt @@ -27,8 +27,12 @@ import org.jetbrains.kotlin.diagnostics.Errors.* import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.BindingContext.* +import org.jetbrains.kotlin.resolve.calls.USE_NEW_INFERENCE +import org.jetbrains.kotlin.resolve.calls.callUtil.getCall import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.checkers.OperatorCallChecker +import org.jetbrains.kotlin.resolve.calls.context.ContextDependency import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.FROM_COMPLETER @@ -47,6 +51,7 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.createFakeExpressionOfType import org.jetbrains.kotlin.types.expressions.FakeCallResolver +import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo import org.jetbrains.kotlin.util.OperatorNameConventions //TODO: check for 'operator' modifier! @@ -310,8 +315,16 @@ class DelegatedPropertyResolver( initializerScope: LexicalScope, dataFlowInfo: DataFlowInfo ): OverloadResolutionResults { - val expectedType = TypeUtils.NO_EXPECTED_TYPE - val context = ExpressionTypingContext.newContext(trace, initializerScope, dataFlowInfo, expectedType) + val context = ExpressionTypingContext.newContext(trace, initializerScope, dataFlowInfo, NO_EXPECTED_TYPE) + return getProvideDelegateMethod(propertyDescriptor, delegateExpression, delegateExpressionType, context) + } + + private fun getProvideDelegateMethod( + propertyDescriptor: VariableDescriptorWithAccessors, + delegateExpression: KtExpression, + delegateExpressionType: KotlinType, + context: ExpressionTypingContext + ): OverloadResolutionResults { val propertyHasReceiver = propertyDescriptor.dispatchReceiverParameter != null val arguments = KtPsiFactory(delegateExpression, markGenerated = false).run { listOf( @@ -320,11 +333,11 @@ class DelegatedPropertyResolver( ) } val functionName = OperatorNameConventions.PROVIDE_DELEGATE - val receiver = ExpressionReceiver.create(delegateExpression, delegateExpressionType, trace.bindingContext) + val receiver = ExpressionReceiver.create(delegateExpression, delegateExpressionType, context.trace.bindingContext) val (provideDelegateCall, provideDelegateResults) = fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments, functionName, delegateExpression) - trace.record(BindingContext.PROVIDE_DELEGATE_CALL, propertyDescriptor, provideDelegateCall) + context.trace.record(BindingContext.PROVIDE_DELEGATE_CALL, propertyDescriptor, provideDelegateCall) return provideDelegateResults } @@ -362,7 +375,8 @@ class DelegatedPropertyResolver( traceToResolveDelegatedProperty.record(CONSTRAINT_SYSTEM_COMPLETER, it, completer) } - val delegateType = expressionTypingServices.safeGetType(scopeForDelegate, delegateExpression, NO_EXPECTED_TYPE, dataFlowInfo, traceToResolveDelegatedProperty) + val expectedTypeByNewInference = completer.resolveViaNewInference(delegateExpression, variableDescriptor, scopeForDelegate, trace, dataFlowInfo) + val delegateType = expressionTypingServices.safeGetType(scopeForDelegate, delegateExpression, expectedTypeByNewInference ?: NO_EXPECTED_TYPE, dataFlowInfo, traceToResolveDelegatedProperty) traceToResolveDelegatedProperty.commit({ slice, _ -> slice !== CONSTRAINT_SYSTEM_COMPLETER }, true) @@ -479,5 +493,45 @@ class DelegatedPropertyResolver( FROM_COMPLETER.position() ) } + + fun resolveViaNewInference( + delegateExpression: KtExpression, + variableDescriptor: VariableDescriptorWithAccessors, + scopeForDelegate: LexicalScope, + trace: BindingTrace, + dataFlowInfo: DataFlowInfo + ): KotlinType? { + if (!USE_NEW_INFERENCE) return null + + val traceToResolveConventionMethods = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods") + + val delegateType = expressionTypingServices.getTypeInfo(scopeForDelegate, delegateExpression, NO_EXPECTED_TYPE, dataFlowInfo, + traceToResolveConventionMethods, false, delegateExpression, ContextDependency.DEPENDENT) + + val contextForProvideDelegate = ExpressionTypingContext.newContext(traceToResolveConventionMethods, scopeForDelegate, delegateType.dataFlowInfo, + NO_EXPECTED_TYPE, ContextDependency.DEPENDENT, StatementFilter.NONE) + + val provideDelegateResults = getProvideDelegateMethod( + variableDescriptor, delegateExpression, delegateType.type ?: return null, contextForProvideDelegate + ) + + var typeInfoForGetValueReceiver = delegateType + if (conventionMethodFound(provideDelegateResults)) { + val provideDelegateDescriptor = provideDelegateResults.resultingDescriptor + if (provideDelegateDescriptor.isOperator) { + typeInfoForGetValueReceiver = KotlinTypeInfo(provideDelegateDescriptor.returnType, + provideDelegateResults.resultingCall.dataFlowInfoForArguments.resultInfo) + } + } + + getGetSetValueMethod( + variableDescriptor, delegateExpression, typeInfoForGetValueReceiver.type ?: return null, + traceToResolveConventionMethods, scopeForDelegate, typeInfoForGetValueReceiver.dataFlowInfo, + isGet = true, isComplete = true + ) + + val call = delegateExpression.getCall(traceToResolveConventionMethods.bindingContext) + return call.getResolvedCall(traceToResolveConventionMethods.bindingContext)?.resultingDescriptor?.returnType + } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt index 0d60fed2207..0bb48127aa7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt @@ -426,7 +426,7 @@ class StubOnlyResolvedCall(val candidate: SimpleKotlinRe override fun getStatus() = ResolutionStatus.UNKNOWN_STATUS override fun getCandidateDescriptor(): D = candidate.candidateDescriptor as D - override fun getResultingDescriptor(): D = candidateDescriptor + override fun getResultingDescriptor(): D = candidate.descriptorWithFreshTypes as D override fun getExtensionReceiver() = candidate.extensionReceiver?.receiver?.receiverValue override fun getDispatchReceiver() = candidate.dispatchReceiverArgument?.receiver?.receiverValue override fun getExplicitReceiverKind() = candidate.explicitReceiverKind diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index f6478a0c71b..204cd438b6c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.resolve.TypeResolver import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver import org.jetbrains.kotlin.resolve.calls.KotlinCallResolver import org.jetbrains.kotlin.resolve.calls.callUtil.createLookupLocation +import org.jetbrains.kotlin.resolve.calls.callUtil.getCall import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall import org.jetbrains.kotlin.resolve.calls.components.ArgumentsToParametersMapper @@ -50,6 +51,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallableDescriptors import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy +import org.jetbrains.kotlin.resolve.calls.util.CallMaker import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil import org.jetbrains.kotlin.resolve.scopes.LexicalScope @@ -378,7 +380,22 @@ class PSICallResolver( is QualifierReceiver -> QualifierReceiverKotlinCallArgument(oldReceiver) // todo report warning if isSafeCall is ReceiverValue -> { val detailedReceiver = context.transformToReceiverWithSmartCastInfo(oldReceiver) - ReceiverExpressionKotlinCallArgument(detailedReceiver, isSafeCall) + + var subCallArgument: ReceiverKotlinCallArgument? = null + if (oldReceiver is ExpressionReceiver) { + val ktExpression = KtPsiUtil.getLastElementDeparenthesized(oldReceiver.expression, context.statementFilter) + + val onlyResolvedCall = ktExpression?.getCall(context.trace.bindingContext)?.let { + context.trace.get(BindingContext.ONLY_RESOLVED_CALL, it) + } + if (onlyResolvedCall != null) { + subCallArgument = SubKotlinCallArgumentImpl(CallMaker.makeExternalValueArgument(oldReceiver.expression), + context.dataFlowInfo, context.dataFlowInfo, detailedReceiver, onlyResolvedCall) + + } + } + + subCallArgument ?: ReceiverExpressionKotlinCallArgument(detailedReceiver, isSafeCall) } else -> error("Incorrect receiver: $oldReceiver") } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/TypeVariable.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/TypeVariable.kt index 3bec778dc42..68dab00c121 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/TypeVariable.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/TypeVariable.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.resolve.calls.model.KotlinCall import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor @@ -41,9 +42,11 @@ class TypeVariableTypeConstructor(private val builtIns: KotlinBuiltIns, val debu sealed class NewTypeVariable(builtIns: KotlinBuiltIns, name: String) { val freshTypeConstructor: TypeConstructor = TypeVariableTypeConstructor(builtIns, name) + // member scope is used if we have receiver with type TypeVariable(T) + // todo add to member scope methods from supertypes for type variable val defaultType: SimpleType = KotlinTypeFactory.simpleType( Annotations.EMPTY, freshTypeConstructor, arguments = emptyList(), - nullable = false, memberScope = ErrorUtils.createErrorScope("Type variable", true)) + nullable = false, memberScope = builtIns.any.unsubstitutedMemberScope) override fun toString() = freshTypeConstructor.toString() }