diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java index 9031b90f05a..899ac428396 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java @@ -1,17 +1,6 @@ /* - * 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. + * Copyright 2000-2018 JetBrains s.r.o. 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; @@ -33,7 +22,7 @@ import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqNameUnsafe; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter; -import org.jetbrains.kotlin.resolve.calls.model.CallResolutionResult; +import org.jetbrains.kotlin.resolve.calls.model.PartialCallResolutionResult; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue; @@ -128,7 +117,7 @@ public interface BindingContext { new BasicWritableSlice<>(DO_NOTHING); WritableSlice> RESOLVED_CALL = new BasicWritableSlice<>(DO_NOTHING); - WritableSlice ONLY_RESOLVED_CALL = new BasicWritableSlice<>(DO_NOTHING); + WritableSlice ONLY_RESOLVED_CALL = new BasicWritableSlice<>(DO_NOTHING); WritableSlice DELEGATE_EXPRESSION_TO_PROVIDE_DELEGATE_CALL = new BasicWritableSlice<>(DO_NOTHING); WritableSlice TAIL_RECURSION_CALL = Slices.createSimpleSlice(); WritableSlice CONSTRAINT_SYSTEM_COMPLETER = new BasicWritableSlice<>(DO_NOTHING); 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 c9408a80a94..8e6687c20cd 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 @@ -73,9 +73,10 @@ class KotlinToResolvedCallTransformer( baseResolvedCall: CallResolutionResult, context: BasicCallResolutionContext ): ResolvedCall { - val candidate = baseResolvedCall.resultCallAtom!! - when (baseResolvedCall.type) { - CallResolutionResult.Type.PARTIAL -> { + return when (baseResolvedCall) { + is PartialCallResolutionResult -> { + val candidate = baseResolvedCall.resultCallAtom + val psiKotlinCall = candidate.atom.psiKotlinCall val psiCall = if (psiKotlinCall is PSIKotlinCallForInvoke) psiKotlinCall.baseCall.psiCall @@ -85,9 +86,12 @@ class KotlinToResolvedCallTransformer( context.trace.record(BindingContext.ONLY_RESOLVED_CALL, psiCall, baseResolvedCall) context.inferenceSession.addPartiallyResolvedCall(baseResolvedCall) - return createStubResolvedCallAndWriteItToTrace(candidate, context.trace, baseResolvedCall.diagnostics) + createStubResolvedCallAndWriteItToTrace(candidate, context.trace, baseResolvedCall.diagnostics) } - CallResolutionResult.Type.ERROR, CallResolutionResult.Type.COMPLETED -> { + + is CompletedCallResolutionResult, is ErrorCallResolutionResult -> { + val candidate = (baseResolvedCall as SingleCallResolutionResult).resultCallAtom + val resultSubstitutor = baseResolvedCall.constraintSystem.buildResultingSubstitutor() val ktPrimitiveCompleter = ResolvedAtomCompleter( resultSubstitutor, context.trace, context, this, expressionTypingServices, argumentTypeResolver, @@ -98,9 +102,11 @@ class KotlinToResolvedCallTransformer( ktPrimitiveCompleter.completeAll(subKtPrimitive) } - return ktPrimitiveCompleter.completeResolvedCall(candidate, baseResolvedCall.diagnostics) as ResolvedCall + ktPrimitiveCompleter.completeResolvedCall(candidate, baseResolvedCall.diagnostics) as ResolvedCall } - CallResolutionResult.Type.ALL_CANDIDATES -> error("Cannot transform result for ALL_CANDIDATES mode") + + is SingleCallResolutionResult -> error("Call resolution result for one candidate didn't transformed: $baseResolvedCall") + is AllCandidatesResolutionResult -> error("Cannot transform result for ALL_CANDIDATES mode") } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt index dc44ccd80f1..e225cfd5dd1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt @@ -1,17 +1,6 @@ /* - * 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. + * Copyright 2000-2018 JetBrains s.r.o. 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.tower @@ -157,7 +146,7 @@ class SubKotlinCallArgumentImpl( override val dataFlowInfoBeforeThisArgument: DataFlowInfo, override val dataFlowInfoAfterThisArgument: DataFlowInfo, override val receiver: ReceiverValueWithSmartCastInfo, - override val callResult: CallResolutionResult + override val callResult: PartialCallResolutionResult ) : SimplePSIKotlinCallArgument(), SubKotlinCallArgument { override val isSpread: Boolean get() = valueArgument.getSpreadElement() != null override val argumentName: Name? get() = valueArgument.getArgumentName()?.asName 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 0a3892519a1..5638148e4bd 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 @@ -174,13 +174,13 @@ class PSICallResolver( result: CallResolutionResult, tracingStrategy: TracingStrategy ): OverloadResolutionResults { - if (result.type == CallResolutionResult.Type.ALL_CANDIDATES) { - val resolvedCalls = result.allCandidates?.map { + if (result is AllCandidatesResolutionResult) { + val resolvedCalls = result.allCandidates.map { val resultingSubstitutor = it.getSystem().asReadOnlyStorage().buildResultingSubstitutor() kotlinToResolvedCallTransformer.transformToResolvedCall(it.resolvedCall, null, resultingSubstitutor, result.diagnostics) } - return AllCandidates(resolvedCalls ?: emptyList()) + return AllCandidates(resolvedCalls) } val trace = context.trace @@ -198,7 +198,7 @@ class PSICallResolver( getResultApplicability(result.diagnostics) == ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER val resolvedCall = if (isInapplicableReceiver) { - val singleCandidate = result.resultCallAtom ?: error("Should be not null for result: $result") + val singleCandidate = result.resultCallAtom() ?: error("Should be not null for result: $result") kotlinToResolvedCallTransformer.onlyTransform(singleCandidate, result.diagnostics).also { tracingStrategy.unresolvedReferenceWrongReceiver(trace, listOf(it)) } @@ -398,12 +398,8 @@ class PSICallResolver( val psiKotlinCall = variable.resolvedCall.atom.psiKotlinCall - val variableResult = CallResolutionResult( - CallResolutionResult.Type.PARTIAL, - variable.resolvedCall, - listOf(), - variable.getSystem().asReadOnlyStorage() - ) + val variableResult = PartialCallResolutionResult(variable.resolvedCall, listOf(), variable.getSystem().asReadOnlyStorage()) + return SubKotlinCallArgumentImpl( CallMaker.makeExternalValueArgument((variableReceiver.receiverValue as ExpressionReceiver).expression), psiKotlinCall.resultDataFlowInfo, psiKotlinCall.resultDataFlowInfo, variableReceiver, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt index 2f673b0453f..e2065484948 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt @@ -56,11 +56,7 @@ class ResolvedAtomCompleter( is ResolvedCallableReferenceAtom -> completeCallableReference(resolvedAtom) is ResolvedLambdaAtom -> completeLambda(resolvedAtom) is ResolvedCallAtom -> completeResolvedCall(resolvedAtom, emptyList()) - is CallResolutionResult -> { - if (resolvedAtom.type == CallResolutionResult.Type.PARTIAL) { - resolvedAtom.resultCallAtom?.let { completeResolvedCall(it, resolvedAtom.diagnostics) } - } - } + is PartialCallResolutionResult -> completeResolvedCall(resolvedAtom.resultCallAtom, resolvedAtom.diagnostics) } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt index ebd0e6300f0..a95feaa1f88 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.resolve.calls.components import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode -import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.tower.forceResolution @@ -41,7 +40,7 @@ class KotlinCallCompleter( return if (resolutionCallbacks.inferenceSession.shouldFixTypeVariables()) candidate.runCompletion(completionType, diagnosticHolder, resolutionCallbacks) else - candidate.asCallResolutionResult(CallResolutionResult.Type.PARTIAL, diagnosticHolder) + candidate.asCallResolutionResult(ConstraintSystemCompletionMode.PARTIAL, diagnosticHolder) } fun createAllCandidatesResult( @@ -61,7 +60,7 @@ class KotlinCallCompleter( collectAllCandidatesMode = true ) } - return CallResolutionResult(CallResolutionResult.Type.ALL_CANDIDATES, null, emptyList(), ConstraintStorage.Empty, candidates) + return AllCandidatesResolutionResult(candidates) } private fun KotlinResolutionCandidate.runCompletion( @@ -71,17 +70,12 @@ class KotlinCallCompleter( ): CallResolutionResult { if (ErrorUtils.isError(resolvedCall.candidateDescriptor) || csBuilder.hasContradiction) { runCompletion(resolvedCall, ConstraintSystemCompletionMode.FULL, diagnosticHolder, getSystem(), resolutionCallbacks) - return asCallResolutionResult(CallResolutionResult.Type.ERROR, diagnosticHolder) + return asCallResolutionResult(completionType, diagnosticHolder, isError = true) } runCompletion(resolvedCall, completionType, diagnosticHolder, getSystem(), resolutionCallbacks) - val callResolutionType = if (completionType == ConstraintSystemCompletionMode.FULL) - CallResolutionResult.Type.COMPLETED - else - CallResolutionResult.Type.PARTIAL - - return asCallResolutionResult(callResolutionType, diagnosticHolder) + return asCallResolutionResult(completionType, diagnosticHolder) } private fun runCompletion( @@ -161,18 +155,22 @@ class KotlinCallCompleter( return resolutionCallbacks.createReceiverWithSmartCastInfo(resolvedCall)?.stableType ?: returnType } - private fun KotlinResolutionCandidate?.asCallResolutionResult( - type: CallResolutionResult.Type, - diagnosticsHolder: KotlinDiagnosticsHolder.SimpleHolder + private fun KotlinResolutionCandidate.asCallResolutionResult( + type: ConstraintSystemCompletionMode, + diagnosticsHolder: KotlinDiagnosticsHolder.SimpleHolder, + isError: Boolean = false ): CallResolutionResult { - val diagnosticsFromResolutionParts = this?.diagnosticsFromResolutionParts ?: emptyList() - val systemStorage = this?.getSystem()?.asReadOnlyStorage() ?: ConstraintStorage.Empty + val systemStorage = getSystem().asReadOnlyStorage() + val allDiagnostics = diagnosticsHolder.getDiagnostics() + this.diagnosticsFromResolutionParts - return CallResolutionResult( - type, - this?.resolvedCall, - diagnosticsHolder.getDiagnostics() + diagnosticsFromResolutionParts, - systemStorage - ) + if (isError) { + return ErrorCallResolutionResult(resolvedCall, allDiagnostics, systemStorage) + } + + return if (type == ConstraintSystemCompletionMode.FULL) { + CompletedCallResolutionResult(resolvedCall, allDiagnostics, systemStorage) + } else { + PartialCallResolutionResult(resolvedCall, allDiagnostics, systemStorage) + } } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCall.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCall.kt index 6ae426dadd2..ce3bd5bcde0 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCall.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCall.kt @@ -1,17 +1,6 @@ /* - * 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. + * Copyright 2000-2018 JetBrains s.r.o. 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.model @@ -44,18 +33,6 @@ private fun SimpleKotlinCallArgument.checkReceiverInvariants() { assert(argumentName == null) { "Argument name should be null for receiver: $this, but it is $argumentName" } - checkArgumentInvariants() -} - -private fun KotlinCallArgument.checkArgumentInvariants() { - if (this is SubKotlinCallArgument) { - assert(callResult.type == CallResolutionResult.Type.PARTIAL) { - "SubCall should has type PARTIAL: $callResult" - } - assert(callResult.resultCallAtom != null) { - "SubCall should has resultCallAtom: $callResult" - } - } } fun KotlinCall.checkCallInvariants() { @@ -65,8 +42,6 @@ fun KotlinCall.checkCallInvariants() { explicitReceiver.safeAs()?.checkReceiverInvariants() dispatchReceiverForInvokeExtension.safeAs()?.checkReceiverInvariants() - argumentsInParenthesis.forEach(KotlinCallArgument::checkArgumentInvariants) - externalArgument?.checkArgumentInvariants() if (callKind != KotlinCallKind.FUNCTION) { assert(externalArgument == null) { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallArguments.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallArguments.kt index f148647668c..974283e9a45 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallArguments.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallArguments.kt @@ -1,17 +1,6 @@ /* - * 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. + * Copyright 2000-2018 JetBrains s.r.o. 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.model @@ -55,7 +44,7 @@ interface SimpleKotlinCallArgument : KotlinCallArgument, ReceiverKotlinCallArgum interface ExpressionKotlinCallArgument : SimpleKotlinCallArgument, ResolutionAtom interface SubKotlinCallArgument : SimpleKotlinCallArgument { - val callResult: CallResolutionResult + val callResult: PartialCallResolutionResult } interface LambdaKotlinCallArgument : PostponableKotlinCallArgument { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt index 6b1fb3d6e71..180e34a8e70 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt @@ -148,29 +148,55 @@ class ResolvedCollectionLiteralAtom( } } -class CallResolutionResult( - val type: Type, - val resultCallAtom: ResolvedCallAtom?, +sealed class CallResolutionResult( + resultCallAtom: ResolvedCallAtom?, val diagnostics: List, - val constraintSystem: ConstraintStorage, - val allCandidates: Collection? = null + val constraintSystem: ConstraintStorage ) : ResolvedAtom() { - override val atom: ResolutionAtom? get() = null - - enum class Type { - COMPLETED, // resultSubstitutor possible create use constraintSystem - PARTIAL, - ERROR, // if resultCallAtom == null it means that there is errors NoneCandidates or ManyCandidates - ALL_CANDIDATES // allCandidates != null - } - init { setAnalyzedResults(listOfNotNull(resultCallAtom)) } - override fun toString() = "$type, resultCallAtom = $resultCallAtom, (${diagnostics.joinToString()})" + final override fun setAnalyzedResults(subResolvedAtoms: List) { + super.setAnalyzedResults(subResolvedAtoms) + } + + override val atom: ResolutionAtom? get() = null + + override fun toString() = "diagnostics: (${diagnostics.joinToString()})" } +open class SingleCallResolutionResult( + val resultCallAtom: ResolvedCallAtom, + diagnostics: List, + constraintSystem: ConstraintStorage +) : CallResolutionResult(resultCallAtom, diagnostics, constraintSystem) + +class PartialCallResolutionResult( + resultCallAtom: ResolvedCallAtom, + diagnostics: List, + constraintSystem: ConstraintStorage +) : SingleCallResolutionResult(resultCallAtom, diagnostics, constraintSystem) + +class CompletedCallResolutionResult( + resultCallAtom: ResolvedCallAtom, + diagnostics: List, + constraintSystem: ConstraintStorage +) : SingleCallResolutionResult(resultCallAtom, diagnostics, constraintSystem) + +class ErrorCallResolutionResult( + resultCallAtom: ResolvedCallAtom, + diagnostics: List, + constraintSystem: ConstraintStorage +) : SingleCallResolutionResult(resultCallAtom, diagnostics, constraintSystem) + +class AllCandidatesResolutionResult( + val allCandidates: Collection +) : CallResolutionResult(null, emptyList(), ConstraintStorage.Empty) + +fun CallResolutionResult.resultCallAtom(): ResolvedCallAtom? = + if (this is SingleCallResolutionResult) resultCallAtom else null + val ResolvedCallAtom.freshReturnType: UnwrappedType? get() { val returnType = candidateDescriptor.returnType ?: return null