From acdd807e91204eb131acc106881937bdbc1e5f3d Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Wed, 17 Feb 2016 15:45:20 +0300 Subject: [PATCH] Support "given candidates" mode in new resolution algorithm. --- .../kotlin/resolve/calls/CallResolver.java | 7 ++- .../calls/tower/NewResolveOldInference.kt | 52 +++++++++++++++---- .../resolve/calls/tower/TowerResolver.kt | 40 ++++++-------- .../tests/j+k/samInConstructorWithGenerics.kt | 2 + .../j+k/samInConstructorWithGenerics.txt | 7 +++ 5 files changed, 73 insertions(+), 35 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java index 6e5e24d745c..5478c91b006 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java @@ -648,13 +648,16 @@ public class CallResolver { } } - if (contextForMigration.resolveKind != ResolveKind.GIVEN_CANDIDATES && useNewResolve) { + if (contextForMigration.resolveKind != ResolveKind.GIVEN_CANDIDATES) { assert contextForMigration.name != null; return (OverloadResolutionResultsImpl) newCallResolver.runResolve(context, contextForMigration.name, contextForMigration.resolveKind, tracing); } + else { + return (OverloadResolutionResultsImpl) newCallResolver.runResolveForGivenCandidates(context, tracing, contextForMigration.givenCandidates); + } - return doResolveCall(context, contextForMigration.lazyTasks.invoke(), contextForMigration.callTransformer, tracing); + //return doResolveCall(context, contextForMigration.lazyTasks.invoke(), contextForMigration.callTransformer, tracing); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt index 66ea19d5b2d..cc7e817fdd0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 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. @@ -39,10 +39,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallImpl import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCallImpl import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl import org.jetbrains.kotlin.resolve.calls.results.ResolutionResultsHandler -import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallableDescriptors -import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind -import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy -import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategyForInvoke +import org.jetbrains.kotlin.resolve.calls.tasks.* import org.jetbrains.kotlin.resolve.isHiddenInResolution import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes import org.jetbrains.kotlin.resolve.scopes.receivers.* @@ -77,10 +74,7 @@ class NewResolveOldInference( var processor = createResolveProcessor(kind, explicitReceiver, context, baseContext) if (context.collectAllCandidates) { - val allCandidates = towerResolver.collectAllCandidates(baseContext, processor) - val result = OverloadResolutionResultsImpl.nameNotFound() - result.allCandidates = allCandidates.map { it.resolvedCall as MutableResolvedCall } - return result + return allCandidatesResult(towerResolver.collectAllCandidates(baseContext, processor)) } // Temporary fix for code migration (unaryPlus()/unaryMinus()) val unaryConventionName = getUnaryPlusOrMinusOperatorFunctionName(context.call) @@ -97,6 +91,46 @@ class NewResolveOldInference( return convertToOverloadResults(candidates, tracing, context) } + fun runResolveForGivenCandidates( + basicCallContext: BasicCallResolutionContext, + tracing: TracingStrategy, + candidates: Collection> + ): OverloadResolutionResultsImpl { + val resolvedCandidates = candidates.mapNotNull { candidate -> + val candidateTrace = TemporaryBindingTrace.create(basicCallContext.trace, "Context for resolve candidate") + val resolvedCall = ResolvedCallImpl.create(candidate, candidateTrace, tracing, basicCallContext.dataFlowInfoForArguments) + + if (candidate.descriptor.isHiddenInResolution()) { + return@mapNotNull Candidate(ResolutionCandidateStatus(listOf(HiddenDescriptor)), resolvedCall) + } + + val callCandidateResolutionContext = CallCandidateResolutionContext.create( + resolvedCall, basicCallContext, candidateTrace, tracing, basicCallContext.call, + null, CandidateResolveMode.FULLY // todo + ) + candidateResolver.performResolutionForCandidateCall(callCandidateResolutionContext, basicCallContext.checkArguments) // todo + + val diagnostics = listOfNotNull(SynthesizedDescriptorDiagnostic.check { candidate.descriptor.isSynthesized }, + createPreviousResolveError(resolvedCall.status)) + Candidate(ResolutionCandidateStatus(diagnostics), resolvedCall) + } + if (basicCallContext.collectAllCandidates) { + val allCandidates = towerResolver.run(listOf(TowerData.Empty), KnownResultProcessor(resolvedCandidates), + TowerResolver.AllCandidatesCollector { it.candidateStatus }, useOrder = false) + return allCandidatesResult(allCandidates) as OverloadResolutionResultsImpl + } + + val processedCandidates = towerResolver.run(listOf(TowerData.Empty), KnownResultProcessor(resolvedCandidates), + TowerResolver.SuccessfulResultCollector { it.candidateStatus }, useOrder = true) + + return convertToOverloadResults(processedCandidates, tracing, basicCallContext) as OverloadResolutionResultsImpl + } + + private fun allCandidatesResult(allCandidates: Collection) + = OverloadResolutionResultsImpl.nameNotFound().apply { + this.allCandidates = allCandidates.map { it.resolvedCall as MutableResolvedCall } + } + private fun createResolveProcessor( kind: CallResolver.ResolveKind, explicitReceiver : Receiver?, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt index 7c0d1a111c0..e38c0e1d7e9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 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. @@ -64,18 +64,11 @@ class TowerResolver { internal fun runResolve( context: TowerContext, processor: ScopeTowerProcessor, - useOrder: Boolean = true - ): Collection { - return run(context, processor, useOrder, SuccessfulResultCollector(context)) - } + useOrder: Boolean + ): Collection = run(context.scopeTower.createTowerDataList(), processor, SuccessfulResultCollector { context.getStatus(it) }, useOrder) - internal fun collectAllCandidates(context: TowerContext, processor: ScopeTowerProcessor): Collection { - return run(context, processor, false, AllCandidatesCollector(context)) - } - - private fun ScopeTower.createLocalLevels() = lexicalScope.parentsWithSelf. - filterIsInstance().filter { it.kind.withLocalDescriptors }. - map { ScopeBasedTowerLevel(this, it) } + internal fun collectAllCandidates(context: TowerContext, processor: ScopeTowerProcessor): Collection + = run(context.scopeTower.createTowerDataList(), processor, AllCandidatesCollector { context.getStatus(it) }, false) private fun ScopeTower.createNonLocalLevels(): List { val result = ArrayList() @@ -160,14 +153,14 @@ class TowerResolver { return result } - private fun run( - context: TowerContext, + internal fun run( + towerDataList: List, processor: ScopeTowerProcessor, - useOrder: Boolean, - resultCollector: ResultCollector + resultCollector: ResultCollector, + useOrder: Boolean ): Collection { - for (towerData in context.scopeTower.createTowerDataList()) { + for (towerData in towerDataList) { ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() val candidatesGroups = if (useOrder) { @@ -187,14 +180,14 @@ class TowerResolver { } - internal abstract class ResultCollector(val context: TowerContext) { + internal abstract class ResultCollector(protected val getStatus: (C) -> ResolutionCandidateStatus) { abstract fun getSuccessfulCandidates(): Collection? abstract fun getFinalCandidates(): Collection fun pushCandidates(candidates: Collection) { val filteredCandidates = candidates.filter { - context.getStatus(it).resultingApplicability != ResolutionCandidateApplicability.HIDDEN + getStatus(it).resultingApplicability != ResolutionCandidateApplicability.HIDDEN } if (filteredCandidates.isNotEmpty()) addCandidates(filteredCandidates) } @@ -202,7 +195,7 @@ class TowerResolver { protected abstract fun addCandidates(candidates: Collection) } - internal class AllCandidatesCollector(context: TowerContext): ResultCollector(context) { + internal class AllCandidatesCollector(getStatus: (C) -> ResolutionCandidateStatus): ResultCollector(getStatus) { private val allCandidates = ArrayList() override fun getSuccessfulCandidates(): Collection? = null @@ -212,10 +205,9 @@ class TowerResolver { override fun addCandidates(candidates: Collection) { allCandidates.addAll(candidates) } - } - internal class SuccessfulResultCollector(context: TowerContext): ResultCollector(context) { + internal class SuccessfulResultCollector(getStatus: (C) -> ResolutionCandidateStatus): ResultCollector(getStatus) { private var currentCandidates: Collection = emptyList() private var currentLevel: ResolutionCandidateApplicability? = null @@ -234,10 +226,10 @@ class TowerResolver { override fun getFinalCandidates() = getResolved() ?: getResolvedSynthetic() ?: getResolvedLowPriority() ?: getErrors() ?: emptyList() override fun addCandidates(candidates: Collection) { - val minimalLevel = candidates.map { context.getStatus(it).resultingApplicability }.min()!! + val minimalLevel = candidates.map { getStatus(it).resultingApplicability }.min()!! if (currentLevel == null || currentLevel!! > minimalLevel) { currentLevel = minimalLevel - currentCandidates = candidates.filter { context.getStatus(it).resultingApplicability == minimalLevel } + currentCandidates = candidates.filter { getStatus(it).resultingApplicability == minimalLevel } } } } diff --git a/compiler/testData/diagnostics/tests/j+k/samInConstructorWithGenerics.kt b/compiler/testData/diagnostics/tests/j+k/samInConstructorWithGenerics.kt index 23923ac11d8..b8695fc6aaa 100644 --- a/compiler/testData/diagnostics/tests/j+k/samInConstructorWithGenerics.kt +++ b/compiler/testData/diagnostics/tests/j+k/samInConstructorWithGenerics.kt @@ -19,3 +19,5 @@ public class Observable { import j.* class K : Observable({}) + +class J : Observable(null) diff --git a/compiler/testData/diagnostics/tests/j+k/samInConstructorWithGenerics.txt b/compiler/testData/diagnostics/tests/j+k/samInConstructorWithGenerics.txt index ea31940397a..1ae9bc51425 100644 --- a/compiler/testData/diagnostics/tests/j+k/samInConstructorWithGenerics.txt +++ b/compiler/testData/diagnostics/tests/j+k/samInConstructorWithGenerics.txt @@ -1,5 +1,12 @@ package +public final class J : j.Observable { + public constructor J() + 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 +} + public final class K : j.Observable { public constructor K() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean