From 5ad0e4e9b85c0bb3054a97c90b63c8e05eeba645 Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Tue, 23 Aug 2016 17:55:39 +0300 Subject: [PATCH] Refactoring. Support in OverloadingConflictResolver any kind of ResolvedCalls. --- .../resolve/calls/results/FlatSignature.kt | 34 +--- .../calls/results/FlatSignatureSpecificity.kt | 51 +++++ .../results/OverloadingConflictResolver.kt | 177 ++++++++++++------ .../results/ResolutionResultsHandler.java | 98 ++-------- 4 files changed, 187 insertions(+), 173 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignature.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignature.kt index 0aadc2647f0..d877ad645c1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignature.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignature.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. @@ -19,12 +19,8 @@ package org.jetbrains.kotlin.resolve.calls.results import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor -import org.jetbrains.kotlin.psi.ValueArgument -import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.utils.singletonOrEmptyList -import java.util.* class FlatSignature( val origin: T, @@ -37,34 +33,6 @@ class FlatSignature( val isGeneric = typeParameters.isNotEmpty() companion object { - fun > createFromResolvedCall(resolvedCall: RC): FlatSignature { - val originalDescriptor = resolvedCall.candidateDescriptor.original - val originalValueParameters = originalDescriptor.valueParameters - - var numDefaults = 0 - val valueArgumentToParameterType = HashMap() - for ((valueParameter, resolvedValueArgument) in resolvedCall.valueArguments.entries) { - if (resolvedValueArgument is DefaultValueArgument) { - numDefaults++ - } - else { - val originalValueParameter = originalValueParameters[valueParameter.index] - val parameterType = originalValueParameter.argumentValueType - for (valueArgument in resolvedValueArgument.arguments) { - valueArgumentToParameterType[valueArgument] = parameterType - } - } - } - - return FlatSignature(resolvedCall, - originalDescriptor.typeParameters, - valueParameterTypes = originalDescriptor.extensionReceiverTypeOrEmpty() + - resolvedCall.call.valueArguments.map { valueArgumentToParameterType[it] }, - hasExtensionReceiver = originalDescriptor.extensionReceiverParameter != null, - hasVarargs = originalDescriptor.valueParameters.any { it.varargElementType != null }, - numDefaults = numDefaults) - } - fun createFromCallableDescriptor(descriptor: D): FlatSignature = FlatSignature(descriptor, descriptor.typeParameters, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignatureSpecificity.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignatureSpecificity.kt index d4a92ec3a21..d983477120b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignatureSpecificity.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignatureSpecificity.kt @@ -16,14 +16,24 @@ package org.jetbrains.kotlin.resolve.calls.results +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.psi.ValueArgument +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.calls.inference.CallHandle import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.valueParameterPosition +import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument +import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCallImpl +import org.jetbrains.kotlin.resolve.calls.results.FlatSignature.Companion.argumentValueType +import org.jetbrains.kotlin.resolve.calls.results.FlatSignature.Companion.extensionReceiverTypeOrEmpty import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.checker.KotlinTypeChecker +import java.util.* interface SpecificityComparisonCallbacks { fun isNonSubtypeNotLessSpecific(specific: KotlinType, general: KotlinType): Boolean @@ -76,3 +86,44 @@ fun isSignatureNotLessSpecific( val constraintSystem = constraintSystemBuilder.build() return !constraintSystem.status.hasContradiction() } + + +fun > RC.createFlatSignature(): FlatSignature { + val originalDescriptor = candidateDescriptor.original + val originalValueParameters = originalDescriptor.valueParameters + + var numDefaults = 0 + val valueArgumentToParameterType = HashMap() + for ((valueParameter, resolvedValueArgument) in valueArguments.entries) { + if (resolvedValueArgument is DefaultValueArgument) { + numDefaults++ + } + else { + val originalValueParameter = originalValueParameters[valueParameter.index] + val parameterType = originalValueParameter.argumentValueType + for (valueArgument in resolvedValueArgument.arguments) { + valueArgumentToParameterType[valueArgument] = parameterType + } + } + } + + return FlatSignature(this, + originalDescriptor.typeParameters, + valueParameterTypes = originalDescriptor.extensionReceiverTypeOrEmpty() + + call.valueArguments.map { valueArgumentToParameterType[it] }, + hasExtensionReceiver = originalDescriptor.extensionReceiverParameter != null, + hasVarargs = originalDescriptor.valueParameters.any { it.varargElementType != null }, + numDefaults = numDefaults) +} + +fun createOverloadingConflictResolver( + builtIns: KotlinBuiltIns, + specificityComparator: TypeSpecificityComparator +) = OverloadingConflictResolver( + builtIns, + specificityComparator, + MutableResolvedCall<*>::getResultingDescriptor, + MutableResolvedCall<*>::createFlatSignature, + { (it as? VariableAsFunctionResolvedCallImpl)?.variableCall }, + { DescriptorToSourceUtils.descriptorToDeclaration(it) != null} +) \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt index 0cfd6a33baa..f7f01ebb36f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt @@ -21,28 +21,105 @@ import gnu.trove.TObjectHashingStrategy import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ScriptDescriptor -import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.resolve.DescriptorEquivalenceForOverrides +import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode -import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionMutableResolvedCall -import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.kotlin.resolve.descriptorUtil.varargParameterPosition import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils +import java.util.* -class OverloadingConflictResolver( +class OverloadingConflictResolver( private val builtIns: KotlinBuiltIns, - private val specificityComparator: TypeSpecificityComparator + private val specificityComparator: TypeSpecificityComparator, + private val getResultingDescriptor: (C) -> CallableDescriptor, + private val createFlatSignature: (C) -> FlatSignature, + private val getVariableCandidates: (C) -> C?, // vor variable WithInvoke + private val isFromSources: (CallableDescriptor) -> Boolean ) { - fun findMaximallySpecific( - candidates: Set>, + private val resolvedCallHashingStrategy = object : TObjectHashingStrategy { + override fun equals(call1: C?, call2: C?): Boolean = + if (call1 != null && call2 != null) + call1.resultingDescriptor == call2.resultingDescriptor + else + call1 == call2 + + override fun computeHashCode(call: C?): Int = + call?.resultingDescriptor?.hashCode() ?: 0 + } + + private val C.resultingDescriptor: CallableDescriptor get() = getResultingDescriptor(this) + + // if result contains only one element -- it is maximally specific; otherwise we have ambiguity + fun chooseMaximallySpecificCandidates( + candidates: Set, checkArgumentsMode: CheckArgumentTypesMode, discriminateGenerics: Boolean, isDebuggerContext: Boolean - ): MutableResolvedCall? = + ): Set { + if (candidates.size == 1) return candidates + + val fixedCandidates = if (getVariableCandidates(candidates.first()) != null) { + findMaximallySpecificVariableAsFunctionCalls(candidates) ?: return candidates + } + else { + candidates + } + + val noEquivalentCalls = filterOutEquivalentCalls(fixedCandidates) + val noOverrides = OverridingUtil.filterOverrides(noEquivalentCalls) { it.resultingDescriptor } + if (noOverrides.size == 1) { + return noOverrides + } + + val maximallySpecific = findMaximallySpecific(noOverrides, checkArgumentsMode, false, isDebuggerContext) + if (maximallySpecific != null) { + return setOf(maximallySpecific) + } + + if (discriminateGenerics) { + val maximallySpecificGenericsDiscriminated = findMaximallySpecific(noOverrides, checkArgumentsMode, true, isDebuggerContext) + if (maximallySpecificGenericsDiscriminated != null) { + return setOf(maximallySpecificGenericsDiscriminated) + } + } + + return noOverrides + } + + // Sometimes we should compare "copies" from sources and from binary files. + // But we cannot compare return types for such copies, because it may lead us to recursive problem (see KT-11995). + // Because of this we compare them without return type and choose descriptor from source if we found duplicate. + private fun filterOutEquivalentCalls( + candidates: Set): Set { + if (candidates.size <= 1) return candidates + + val fromSourcesGoesFirst = candidates.sortedBy { if (isFromSources(it.resultingDescriptor)) 0 else 1 } + + val result = LinkedHashSet() + outerLoop@ for (meD in fromSourcesGoesFirst) { + for (otherD in result) { + val me = meD.resultingDescriptor + val other = otherD.resultingDescriptor + val ignoreReturnType = isFromSources(me) != isFromSources(other) + if (DescriptorEquivalenceForOverrides.areCallableDescriptorsEquivalent(me, other, ignoreReturnType)) { + continue@outerLoop + } + } + result.add(meD) + } + + return result + } + + private fun findMaximallySpecific( + candidates: Set, + checkArgumentsMode: CheckArgumentTypesMode, + discriminateGenerics: Boolean, + isDebuggerContext: Boolean + ): C? = if (candidates.size <= 1) candidates.firstOrNull() else when (checkArgumentsMode) { @@ -58,33 +135,31 @@ class OverloadingConflictResolver( findMaximallySpecificCall(candidates, discriminateGenerics, isDebuggerContext) } - fun findMaximallySpecificVariableAsFunctionCalls(candidates: Set>): Set> { - val variableCalls = candidates.mapTo(newResolvedCallSet>(candidates.size)) { - if (it is VariableAsFunctionMutableResolvedCall) - it.variableCall - else - throw AssertionError("Regular call among variable-as-function calls: $it") + // null means ambiguity between variables + private fun findMaximallySpecificVariableAsFunctionCalls(candidates: Set): Set? { + val variableCalls = candidates.mapTo(newResolvedCallSet(candidates.size)) { + getVariableCandidates(it) ?: throw AssertionError("Regular call among variable-as-function calls: $it") } - val maxSpecificVariableCall = findMaximallySpecificCall(variableCalls, false, false) ?: return emptySet() + val maxSpecificVariableCall = findMaximallySpecificCall(variableCalls, false, false) ?: return null - return candidates.filterTo(newResolvedCallSet>(2)) { - it.resultingVariableDescriptor == maxSpecificVariableCall.resultingDescriptor + return candidates.filterTo(newResolvedCallSet(2)) { + getVariableCandidates(it)!!.resultingDescriptor == maxSpecificVariableCall.resultingDescriptor } } - private fun findMaximallySpecificCall( - candidates: Set>, + private fun findMaximallySpecificCall( + candidates: Set, discriminateGenerics: Boolean, isDebuggerContext: Boolean - ): MutableResolvedCall? { + ): C? { val filteredCandidates = uniquifyCandidatesSet(candidates) if (filteredCandidates.size <= 1) return filteredCandidates.singleOrNull() val conflictingCandidates = filteredCandidates.map { candidateCall -> - FlatSignature.createFromResolvedCall(candidateCall) + createFlatSignature(candidateCall) } val bestCandidatesByParameterTypes = conflictingCandidates.filter { @@ -132,9 +207,9 @@ class OverloadingConflictResolver( /** * `call1` is not less specific than `call2` */ - private fun isNotLessSpecificCallWithArgumentMapping( - call1: FlatSignature>, - call2: FlatSignature>, + private fun isNotLessSpecificCallWithArgumentMapping( + call1: FlatSignature, + call2: FlatSignature, discriminateGenerics: Boolean ): Boolean { return tryCompareDescriptorsFromScripts(call1.candidateDescriptor(), call2.candidateDescriptor()) ?: @@ -145,9 +220,9 @@ class OverloadingConflictResolver( * Returns `true` if `d1` is definitely not less specific than `d2`, * `false` otherwise. */ - private fun compareCallsByUsedArguments( - call1: FlatSignature>, - call2: FlatSignature>, + private fun compareCallsByUsedArguments( + call1: FlatSignature, + call2: FlatSignature, discriminateGenerics: Boolean ): Boolean { if (discriminateGenerics) { @@ -188,9 +263,9 @@ class OverloadingConflictResolver( } } - private fun isOfNotLessSpecificShape( - call1: FlatSignature>, - call2: FlatSignature> + private fun isOfNotLessSpecificShape( + call1: FlatSignature, + call2: FlatSignature ): Boolean { val hasVarargs1 = call1.hasVarargs val hasVarargs2 = call2.hasVarargs @@ -204,9 +279,9 @@ class OverloadingConflictResolver( return true } - private fun isOfNotLessSpecificVisibilityForDebugger( - call1: FlatSignature>, - call2: FlatSignature>, + private fun isOfNotLessSpecificVisibilityForDebugger( + call1: FlatSignature, + call2: FlatSignature, isDebuggerContext: Boolean ): Boolean { if (isDebuggerContext) { @@ -254,34 +329,16 @@ class OverloadingConflictResolver( tryCompareDescriptorsFromScripts(f, g) ?: isNotLessSpecificCallableReferenceDescriptor(f, g) - // Different smartcasts may lead to the same candidate descriptor wrapped into different ResolvedCallImpl objects - private fun uniquifyCandidatesSet(candidates: Collection>): Set> = - THashSet>(candidates.size, getCallHashingStrategy>()).apply { addAll(candidates) } + // Different smart casts may lead to the same candidate descriptor wrapped into different ResolvedCallImpl objects + private fun uniquifyCandidatesSet(candidates: Collection): Set = + THashSet(candidates.size, resolvedCallHashingStrategy).apply { addAll(candidates) } - private fun newResolvedCallSet(expectedSize: Int): MutableSet = - THashSet(expectedSize, getCallHashingStrategy()) + private fun newResolvedCallSet(expectedSize: Int): MutableSet = + THashSet(expectedSize, resolvedCallHashingStrategy) - private object ResolvedCallHashingStrategy : TObjectHashingStrategy> { - override fun equals(call1: ResolvedCall<*>?, call2: ResolvedCall<*>?): Boolean = - if (call1 != null && call2 != null) - call1.resultingDescriptor == call2.resultingDescriptor - else - call1 == call2 - - override fun computeHashCode(call: ResolvedCall<*>?): Int = - call?.resultingDescriptor?.hashCode() ?: 0 - } - - private val MutableResolvedCall<*>.resultingVariableDescriptor: VariableDescriptor - get() = (this as VariableAsFunctionResolvedCall).variableCall.resultingDescriptor - - @Suppress("UNCHECKED_CAST") - private fun getCallHashingStrategy() = - ResolvedCallHashingStrategy as TObjectHashingStrategy - - private fun FlatSignature>.candidateDescriptor() = + private fun FlatSignature.candidateDescriptor() = origin.resultingDescriptor.original - private fun FlatSignature>.descriptorVisibility() = + private fun FlatSignature.descriptorVisibility() = candidateDescriptor().visibility } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionResultsHandler.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionResultsHandler.java index 62c50766f19..f2d854f5f6a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionResultsHandler.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionResultsHandler.java @@ -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. @@ -17,46 +17,31 @@ package org.jetbrains.kotlin.resolve.calls.results; import com.google.common.collect.Sets; -import kotlin.collections.CollectionsKt; -import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.CallableDescriptor; import org.jetbrains.kotlin.resolve.BindingTrace; -import org.jetbrains.kotlin.resolve.DescriptorEquivalenceForOverrides; -import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; -import org.jetbrains.kotlin.resolve.OverridingUtil; import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt; import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext; import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode; import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall; -import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall; import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy; -import java.util.*; +import java.util.Collection; +import java.util.EnumSet; +import java.util.Set; import static org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.*; public class ResolutionResultsHandler { - private static final Function1, CallableDescriptor> MAP_RESOLVED_CALL_TO_RESULTING_DESCRIPTOR = - new Function1, CallableDescriptor>() { - @Override - public CallableDescriptor invoke(MutableResolvedCall resolvedCall) { - return resolvedCall.getResultingDescriptor(); - } - }; - private static final Function1, Integer> MAP_RESOLVED_CALL_TO_SOURCE_PRESENCE = - new Function1, Integer>() { - @Override - public Integer invoke(MutableResolvedCall resolvedCall) { - return DescriptorToSourceUtils.descriptorToDeclaration(resolvedCall.getResultingDescriptor()) != null ? 0 : 1; - } - }; + private final OverloadingConflictResolver> overloadingConflictResolver; - private final OverloadingConflictResolver overloadingConflictResolver; - - public ResolutionResultsHandler(@NotNull OverloadingConflictResolver overloadingConflictResolver) { - this.overloadingConflictResolver = overloadingConflictResolver; + public ResolutionResultsHandler( + @NotNull KotlinBuiltIns builtIns, + @NotNull TypeSpecificityComparator specificityComparator + ) { + overloadingConflictResolver = FlatSignatureSpecificityKt.createOverloadingConflictResolver(builtIns, specificityComparator); } @NotNull @@ -195,35 +180,6 @@ public class ResolutionResultsHandler { return true; } - // Sometimes we should compare "copies" from sources and from binary files. - // But we cannot compare return types for such copies, because it may lead us to recursive problem (see KT-11995). - // Because of this we compare them without return type and choose descriptor from source if we found duplicate. - @NotNull - private static Set> filterOutEquivalentCalls( - @NotNull Set> candidates - ) { - if (candidates.size() <= 1) return candidates; - - List> fromSourcesGoesFirst = CollectionsKt.sortedBy(candidates, MAP_RESOLVED_CALL_TO_SOURCE_PRESENCE); - - Set> result = new LinkedHashSet>(); - outerLoop: - for (MutableResolvedCall meD : fromSourcesGoesFirst) { - for (MutableResolvedCall otherD : result) { - D me = meD.getResultingDescriptor(); - D other = otherD.getResultingDescriptor(); - boolean ignoreReturnType = (DescriptorToSourceUtils.descriptorToDeclaration(me) == null) != - (DescriptorToSourceUtils.descriptorToDeclaration(other) == null); - if (DescriptorEquivalenceForOverrides.INSTANCE.areCallableDescriptorsEquivalent(me, other, ignoreReturnType)) { - continue outerLoop; - } - } - result.add(meD); - } - - return result; - } - @NotNull private OverloadResolutionResultsImpl chooseAndReportMaximallySpecific( @NotNull Set> candidates, @@ -231,34 +187,16 @@ public class ResolutionResultsHandler { boolean isDebuggerContext, @NotNull CheckArgumentTypesMode checkArgumentsMode ) { - if (candidates.size() == 1) { - return OverloadResolutionResultsImpl.success(candidates.iterator().next()); - } + OverloadingConflictResolver> myResolver = (OverloadingConflictResolver) overloadingConflictResolver; - if (candidates.iterator().next() instanceof VariableAsFunctionResolvedCall) { - candidates = overloadingConflictResolver.findMaximallySpecificVariableAsFunctionCalls(candidates); - } + Set> specificCalls = + myResolver.chooseMaximallySpecificCandidates(candidates, checkArgumentsMode, discriminateGenerics, isDebuggerContext); - Set> noEquivalentCalls = filterOutEquivalentCalls(candidates); - Set> noOverrides = - OverridingUtil.filterOverrides(noEquivalentCalls, MAP_RESOLVED_CALL_TO_RESULTING_DESCRIPTOR); - if (noOverrides.size() == 1) { - return OverloadResolutionResultsImpl.success(noOverrides.iterator().next()); + if (specificCalls.size() == 1) { + return OverloadResolutionResultsImpl.success(specificCalls.iterator().next()); } - - MutableResolvedCall maximallySpecific = overloadingConflictResolver.findMaximallySpecific(noOverrides, checkArgumentsMode, false, isDebuggerContext); - if (maximallySpecific != null) { - return OverloadResolutionResultsImpl.success(maximallySpecific); + else { + return OverloadResolutionResultsImpl.ambiguity(specificCalls); } - - if (discriminateGenerics) { - MutableResolvedCall maximallySpecificGenericsDiscriminated = overloadingConflictResolver.findMaximallySpecific( - noOverrides, checkArgumentsMode, true, isDebuggerContext); - if (maximallySpecificGenericsDiscriminated != null) { - return OverloadResolutionResultsImpl.success(maximallySpecificGenericsDiscriminated); - } - } - - return OverloadResolutionResultsImpl.ambiguity(noOverrides); } }