Do not discriminate synthesized candidates.

#KT-9965 Fixed
This commit is contained in:
Stanislav Erokhin
2015-12-18 01:35:43 +03:00
parent 1b6f96ac2b
commit 8b5a194dd6
14 changed files with 166 additions and 17 deletions
@@ -74,7 +74,8 @@ data class ResolutionCandidateStatus(val diagnostics: List<ResolutionDiagnostic>
enum class ResolutionCandidateApplicability {
RESOLVED, // call success or has uncompleted inference or in other words possible successful candidate
RESOLVED_SYNTHESIZED,
RESOLVED_SYNTHESIZED, // todo remove it (need for SAM adapters which created inside some MemberScope)
RESOLVED_LOW_PRIORITY,
CONVENTION_ERROR, // missing infix, operator etc
MAY_THROW_RUNTIME_ERROR, // unsafe call or unstable smart cast
RUNTIME_ERROR, // problems with visibility
@@ -94,8 +95,9 @@ class UnsupportedInnerClassCall(val message: String): ResolutionDiagnostic(Resol
class UsedSmartCastForDispatchReceiver(val smartCastType: KotlinType): ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED)
object ErrorDescriptorDiagnostic : ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED) // todo discuss and change to INAPPLICABLE
object SynthesizedDescriptorDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED)
object DynamicDescriptorDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED)
object LowPriorityDescriptorDiagnostic : ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY)
object SynthesizedDescriptorDiagnostic : ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED)
object DynamicDescriptorDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY)
object UnstableSmartCastDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.MAY_THROW_RUNTIME_ERROR)
object ExtensionWithStaticTypeWithDynamicReceiver: ResolutionDiagnostic(ResolutionCandidateApplicability.HIDDEN)
object HiddenDescriptor: ResolutionDiagnostic(ResolutionCandidateApplicability.HIDDEN)
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassValueDescriptor
import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.ResolutionScope
@@ -55,6 +56,7 @@ internal abstract class AbstractScopeTowerLevel(
diagnostics.add(ErrorDescriptorDiagnostic)
}
else {
if (descriptor.hasLowPriorityInOverloadResolution()) diagnostics.add(LowPriorityDescriptorDiagnostic)
if (descriptor.isSynthesized) diagnostics.add(SynthesizedDescriptorDiagnostic)
if (dispatchReceiverSmartCastType != null) diagnostics.add(UsedSmartCastForDispatchReceiver(dispatchReceiverSmartCastType))
@@ -85,7 +85,7 @@ class TowerResolver {
for (candidatesGroup in candidatesGroups) {
resultCollector.pushCandidates(candidatesGroup)
resultCollector.getResolved()?.let { return it }
resultCollector.getSuccessfulCandidates()?.let { return it }
}
return null
}
@@ -108,7 +108,7 @@ class TowerResolver {
internal abstract class ResultCollector<C>(val context: TowerContext<C>) {
abstract fun getResolved(): Collection<C>?
abstract fun getSuccessfulCandidates(): Collection<C>?
abstract fun getFinalCandidates(): Collection<C>
@@ -125,7 +125,7 @@ class TowerResolver {
internal class AllCandidatesCollector<C>(context: TowerContext<C>): ResultCollector<C>(context) {
private val allCandidates = ArrayList<C>()
override fun getResolved(): Collection<C>? = null
override fun getSuccessfulCandidates(): Collection<C>? = null
override fun getFinalCandidates(): Collection<C> = allCandidates
@@ -139,15 +139,19 @@ class TowerResolver {
private var currentCandidates: Collection<C> = emptyList()
private var currentLevel: ResolutionCandidateApplicability? = null
override fun getResolved() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED }
override fun getSuccessfulCandidates(): Collection<C>? = getResolved() ?: getResolvedSynthetic()
fun getSyntheticResolved() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED }
fun getResolved() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED }
fun getResolvedSynthetic() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED }
fun getResolvedLowPriority() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY }
fun getErrors() = currentCandidates.check {
currentLevel == null || currentLevel!! > ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED
currentLevel == null || currentLevel!! > ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY
}
override fun getFinalCandidates() = getResolved() ?: getSyntheticResolved() ?: getErrors() ?: emptyList()
override fun getFinalCandidates() = getResolved() ?: getResolvedSynthetic() ?: getResolvedLowPriority() ?: getErrors() ?: emptyList()
override fun addCandidates(candidates: Collection<C>) {
val minimalLevel = candidates.map { context.getStatus(it).resultingApplicability }.min()!!
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
@Deprecated("Temporary error")
@@ -37,11 +36,10 @@ internal fun createPreviousResolveError(status: ResolutionStatus): PreviousResol
}
internal val ResolutionCandidateApplicability.isSuccess: Boolean
get() = this == ResolutionCandidateApplicability.RESOLVED || this == ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED
get() = this <= ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY
internal val CallableDescriptor.isSynthesized: Boolean // todo dynamics calls
get() = (this is CallableMemberDescriptor && isOrOverridesSynthesized(this))
|| hasLowPriorityInOverloadResolution()
internal val CallableDescriptor.isSynthesized: Boolean
get() = (this is CallableMemberDescriptor && kind == CallableMemberDescriptor.Kind.SYNTHESIZED)
internal val CandidateWithBoundDispatchReceiver<*>.requiresExtensionReceiver: Boolean
get() = descriptor.extensionReceiverParameter != null