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 69fd0ec1f14..d19d2916a94 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 @@ -14,102 +14,82 @@ * limitations under the License. */ -package org.jetbrains.kotlin.resolve.calls.results; +package org.jetbrains.kotlin.resolve.calls.results -import gnu.trove.THashSet; -import gnu.trove.TObjectHashingStrategy; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.builtins.KotlinBuiltIns; -import org.jetbrains.kotlin.descriptors.*; -import org.jetbrains.kotlin.resolve.OverrideResolver; -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.VariableAsFunctionResolvedCall; -import org.jetbrains.kotlin.types.*; -import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; +import gnu.trove.THashSet +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.ValueParameterDescriptor +import org.jetbrains.kotlin.resolve.OverrideResolver +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.types.* +import org.jetbrains.kotlin.types.checker.KotlinTypeChecker -import java.util.List; -import java.util.Set; +class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) { -public class OverloadingConflictResolver { - - private final KotlinBuiltIns builtIns; - - public OverloadingConflictResolver(@NotNull KotlinBuiltIns builtIns) { - this.builtIns = builtIns; - } - - @Nullable - public MutableResolvedCall findMaximallySpecific( - @NotNull Set> candidates, - boolean discriminateGenericDescriptors, - @NotNull CheckArgumentTypesMode checkArgumentsMode - ) { + fun findMaximallySpecific( + candidates: Set>, + discriminateGenericDescriptors: Boolean, + checkArgumentsMode: CheckArgumentTypesMode + ): MutableResolvedCall? { // Different smartcasts may lead to the same candidate descriptor wrapped into different ResolvedCallImpl objects - Set> maximallySpecific = new THashSet>(new TObjectHashingStrategy>() { - @Override - public boolean equals(MutableResolvedCall o1, MutableResolvedCall o2) { - return o1 == null ? o2 == null : o1.getResultingDescriptor().equals(o2.getResultingDescriptor()); - } + + val maximallySpecific = THashSet(object : TObjectHashingStrategy> { + override fun equals(call1: MutableResolvedCall?, call2: MutableResolvedCall?): Boolean = + if (call1 == null) call2 == null + else call1.resultingDescriptor == call2!!.resultingDescriptor - @Override - public int computeHashCode(MutableResolvedCall object) { - return object == null ? 0 : object.getResultingDescriptor().hashCode(); - } - }); - for (MutableResolvedCall candidateCall : candidates) { - if (isMaximallySpecific(candidateCall, candidates, discriminateGenericDescriptors, checkArgumentsMode)) { - maximallySpecific.add(candidateCall); - } + override fun computeHashCode(call: MutableResolvedCall?): Int = + call?.resultingDescriptor?.hashCode() ?: 0 + }) + + candidates.filterTo(maximallySpecific) { + isMaximallySpecific(it, candidates, discriminateGenericDescriptors, checkArgumentsMode) } - return maximallySpecific.size() == 1 ? maximallySpecific.iterator().next() : null; + + return if (maximallySpecific.size == 1) maximallySpecific.first() else null } - private boolean isMaximallySpecific( - @NotNull MutableResolvedCall candidateCall, - @NotNull Set> candidates, - boolean discriminateGenericDescriptors, - @NotNull CheckArgumentTypesMode checkArgumentsMode - ) { - D me = candidateCall.getResultingDescriptor(); + private fun isMaximallySpecific( + candidateCall: MutableResolvedCall, + candidates: Set>, + discriminateGenericDescriptors: Boolean, + checkArgumentsMode: CheckArgumentTypesMode): Boolean { + val me = candidateCall.resultingDescriptor - boolean isInvoke = candidateCall instanceof VariableAsFunctionResolvedCall; - VariableDescriptor variable; - if (isInvoke) { - variable = ((VariableAsFunctionResolvedCall) candidateCall).getVariableCall().getResultingDescriptor(); - } - else { - variable = null; - } + val isInvoke = candidateCall is VariableAsFunctionResolvedCall + val variable = (candidateCall as? VariableAsFunctionResolvedCall)?.variableCall?.resultingDescriptor - for (MutableResolvedCall otherCall : candidates) { - D other = otherCall.getResultingDescriptor(); - if (other == me) continue; + for (otherCall in candidates) { + val other = otherCall.resultingDescriptor + if (other === me) continue if (definitelyNotMaximallySpecific(me, other, discriminateGenericDescriptors, checkArgumentsMode)) { + if (!isInvoke) return false - if (!isInvoke) return false; + assert(otherCall is VariableAsFunctionResolvedCall) { "'invoke' candidate goes with usual one: " + candidateCall + otherCall } - assert otherCall instanceof VariableAsFunctionResolvedCall : "'invoke' candidate goes with usual one: " + candidateCall + otherCall; - ResolvedCall otherVariableCall = ((VariableAsFunctionResolvedCall) otherCall).getVariableCall(); - if (definitelyNotMaximallySpecific(variable, otherVariableCall.getResultingDescriptor(), discriminateGenericDescriptors, checkArgumentsMode)) { - return false; + val otherVariableCall = (otherCall as VariableAsFunctionResolvedCall).variableCall + if (definitelyNotMaximallySpecific(variable!!, otherVariableCall.resultingDescriptor, discriminateGenericDescriptors, checkArgumentsMode)) { + return false } } } - return true; + + return true } - private boolean definitelyNotMaximallySpecific( - D me, - D other, - boolean discriminateGenericDescriptors, - @NotNull CheckArgumentTypesMode checkArgumentsMode - ) { + private fun definitelyNotMaximallySpecific( + me: D, + other: D, + discriminateGenericDescriptors: Boolean, + checkArgumentsMode: CheckArgumentTypesMode): Boolean { return !moreSpecific(me, other, discriminateGenericDescriptors, checkArgumentsMode) || - moreSpecific(other, me, discriminateGenericDescriptors, checkArgumentsMode); + moreSpecific(other, me, discriminateGenericDescriptors, checkArgumentsMode) } /** @@ -119,85 +99,86 @@ public class OverloadingConflictResolver { * Int < Long * Int < Short < Byte */ - private boolean moreSpecific( - Descriptor f, - Descriptor g, - boolean discriminateGenericDescriptors, - @NotNull CheckArgumentTypesMode checkArgumentsMode - ) { - boolean resolvingCallableReference = checkArgumentsMode == CheckArgumentTypesMode.CHECK_CALLABLE_TYPE; + private fun moreSpecific( + f: Descriptor, + g: Descriptor, + discriminateGenericDescriptors: Boolean, + checkArgumentsMode: CheckArgumentTypesMode): Boolean { + val resolvingCallableReference = checkArgumentsMode == CheckArgumentTypesMode.CHECK_CALLABLE_TYPE - if (f.getContainingDeclaration() instanceof ScriptDescriptor && g.getContainingDeclaration() instanceof ScriptDescriptor) { - ScriptDescriptor fs = (ScriptDescriptor) f.getContainingDeclaration(); - ScriptDescriptor gs = (ScriptDescriptor) g.getContainingDeclaration(); + if (f.containingDeclaration is ScriptDescriptor && g.containingDeclaration is ScriptDescriptor) { + val fs = f.containingDeclaration as ScriptDescriptor + val gs = g.containingDeclaration as ScriptDescriptor - if (fs.getPriority() != gs.getPriority()) { - return fs.getPriority() > gs.getPriority(); + if (fs.priority != gs.priority) { + return fs.priority > gs.priority } } - boolean isGenericF = isGeneric(f); - boolean isGenericG = isGeneric(g); + val isGenericF = isGeneric(f) + val isGenericG = isGeneric(g) if (discriminateGenericDescriptors) { - if (!isGenericF && isGenericG) return true; - if (isGenericF && !isGenericG) return false; + if (!isGenericF && isGenericG) return true + if (isGenericF && !isGenericG) return false if (isGenericF && isGenericG) { - return moreSpecific(BoundsSubstitutor.substituteBounds(f), BoundsSubstitutor.substituteBounds(g), false, checkArgumentsMode); + return moreSpecific(BoundsSubstitutor.substituteBounds(f), + BoundsSubstitutor.substituteBounds(g), + false, checkArgumentsMode) } } - if (OverrideResolver.overrides(f, g)) return true; - if (OverrideResolver.overrides(g, f)) return false; + if (OverrideResolver.overrides(f, g)) return true + if (OverrideResolver.overrides(g, f)) return false - ReceiverParameterDescriptor receiverOfF = f.getExtensionReceiverParameter(); - ReceiverParameterDescriptor receiverOfG = g.getExtensionReceiverParameter(); + val receiverOfF = f.extensionReceiverParameter + val receiverOfG = g.extensionReceiverParameter if (receiverOfF != null && receiverOfG != null) { - if (!typeMoreSpecific(receiverOfF.getType(), receiverOfG.getType())) return false; + if (!typeMoreSpecific(receiverOfF.type, receiverOfG.type)) return false } - List fParams = f.getValueParameters(); - List gParams = g.getValueParameters(); + val fParams = f.valueParameters + val gParams = g.valueParameters - int fSize = fParams.size(); - int gSize = gParams.size(); + val fSize = fParams.size + val gSize = gParams.size - boolean fIsVararg = isVariableArity(fParams); - boolean gIsVararg = isVariableArity(gParams); + val fIsVararg = isVariableArity(fParams) + val gIsVararg = isVariableArity(gParams) - if (resolvingCallableReference && fIsVararg != gIsVararg) return false; - if (!fIsVararg && gIsVararg) return true; - if (fIsVararg && !gIsVararg) return false; + if (resolvingCallableReference && fIsVararg != gIsVararg) return false + if (!fIsVararg && gIsVararg) return true + if (fIsVararg && !gIsVararg) return false if (!fIsVararg && !gIsVararg) { - if (resolvingCallableReference && fSize != gSize) return false; - if (!resolvingCallableReference && fSize > gSize) return false; + if (resolvingCallableReference && fSize != gSize) return false + if (!resolvingCallableReference && fSize > gSize) return false - for (int i = 0; i < fSize; i++) { - ValueParameterDescriptor fParam = fParams.get(i); - ValueParameterDescriptor gParam = gParams.get(i); + for (i in 0..fSize - 1) { + val fParam = fParams[i] + val gParam = gParams[i] - KotlinType fParamType = fParam.getType(); - KotlinType gParamType = gParam.getType(); + val fParamType = fParam.type + val gParamType = gParam.type if (!typeMoreSpecific(fParamType, gParamType)) { - return false; + return false } } } if (fIsVararg && gIsVararg) { // Check matching parameters - int minSize = Math.min(fSize, gSize); - for (int i = 0; i < minSize - 1; i++) { - ValueParameterDescriptor fParam = fParams.get(i); - ValueParameterDescriptor gParam = gParams.get(i); + val minSize = Math.min(fSize, gSize) + for (i in 0..minSize - 1 - 1) { + val fParam = fParams[i] + val gParam = gParams[i] - KotlinType fParamType = fParam.getType(); - KotlinType gParamType = gParam.getType(); + val fParamType = fParam.type + val gParamType = gParam.type if (!typeMoreSpecific(fParamType, gParamType)) { - return false; + return false } } @@ -207,81 +188,77 @@ public class OverloadingConflictResolver { // g(a : A, vararg vg : T) // here we check that typeOf(a) < elementTypeOf(vf) and elementTypeOf(vg) < elementTypeOf(vf) if (fSize < gSize) { - ValueParameterDescriptor fParam = fParams.get(fSize - 1); - KotlinType fParamType = fParam.getVarargElementType(); - assert fParamType != null : "fIsVararg guarantees this"; - for (int i = fSize - 1; i < gSize; i++) { - ValueParameterDescriptor gParam = gParams.get(i); - if (!typeMoreSpecific(fParamType, getVarargElementTypeOrType(gParam))) { - return false; + val fParam = fParams[fSize - 1] + val fParamType = fParam.varargElementType + assert(fParamType != null) { "fIsVararg guarantees this" } + for (i in fSize - 1..gSize - 1) { + val gParam = gParams[i] + if (!typeMoreSpecific(fParamType!!, getVarargElementTypeOrType(gParam))) { + return false } } } else { - ValueParameterDescriptor gParam = gParams.get(gSize - 1); - KotlinType gParamType = gParam.getVarargElementType(); - assert gParamType != null : "gIsVararg guarantees this"; - for (int i = gSize - 1; i < fSize; i++) { - ValueParameterDescriptor fParam = fParams.get(i); - if (!typeMoreSpecific(getVarargElementTypeOrType(fParam), gParamType)) { - return false; + val gParam = gParams[gSize - 1] + val gParamType = gParam.varargElementType + assert(gParamType != null) { "gIsVararg guarantees this" } + for (i in gSize - 1..fSize - 1) { + val fParam = fParams[i] + if (!typeMoreSpecific(getVarargElementTypeOrType(fParam), gParamType!!)) { + return false } } } } - return true; + return true } - @NotNull - private static KotlinType getVarargElementTypeOrType(@NotNull ValueParameterDescriptor parameterDescriptor) { - KotlinType varargElementType = parameterDescriptor.getVarargElementType(); - if (varargElementType != null) { - return varargElementType; - } - return parameterDescriptor.getType(); - } + private fun getVarargElementTypeOrType(parameterDescriptor: ValueParameterDescriptor): KotlinType = + parameterDescriptor.varargElementType ?: parameterDescriptor.type - private static boolean isVariableArity(List fParams) { - int fSize = fParams.size(); - return fSize > 0 && fParams.get(fSize - 1).getVarargElementType() != null; - } + private fun isVariableArity(fParams: List): Boolean = + fParams.lastOrNull()?.varargElementType != null - private static boolean isGeneric(CallableDescriptor f) { - return !f.getOriginal().getTypeParameters().isEmpty(); - } + private fun isGeneric(f: CallableDescriptor): Boolean = + f.original.typeParameters.isNotEmpty() - private boolean typeMoreSpecific(@NotNull KotlinType specific, @NotNull KotlinType general) { - boolean isSubtype = KotlinTypeChecker.DEFAULT.isSubtypeOf(specific, general) || - numericTypeMoreSpecific(specific, general); + private fun typeMoreSpecific(specific: KotlinType, general: KotlinType): Boolean { + val isSubtype = KotlinTypeChecker.DEFAULT.isSubtypeOf(specific, general) || numericTypeMoreSpecific(specific, general) - if (!isSubtype) return false; + if (!isSubtype) return false - Specificity.Relation sThanG = TypeCapabilitiesKt.getSpecificityRelationTo(specific, general); - Specificity.Relation gThanS = TypeCapabilitiesKt.getSpecificityRelationTo(general, specific); - if (sThanG == Specificity.Relation.LESS_SPECIFIC && gThanS != Specificity.Relation.LESS_SPECIFIC) { - return false; + val sThanG = specific.getSpecificityRelationTo(general) + val gThanS = general.getSpecificityRelationTo(specific) + if (sThanG === Specificity.Relation.LESS_SPECIFIC && + gThanS !== Specificity.Relation.LESS_SPECIFIC) { + return false } - return true; + return true } - private boolean numericTypeMoreSpecific(@NotNull KotlinType specific, @NotNull KotlinType general) { - KotlinType _double = builtIns.getDoubleType(); - KotlinType _float = builtIns.getFloatType(); - KotlinType _long = builtIns.getLongType(); - KotlinType _int = builtIns.getIntType(); - KotlinType _byte = builtIns.getByteType(); - KotlinType _short = builtIns.getShortType(); + private fun numericTypeMoreSpecific(specific: KotlinType, general: KotlinType): Boolean { + val _double = builtIns.doubleType + val _float = builtIns.floatType + val _long = builtIns.longType + val _int = builtIns.intType + val _byte = builtIns.byteType + val _short = builtIns.shortType - if (TypeUtils.equalTypes(specific, _double) && TypeUtils.equalTypes(general, _float)) return true; - if (TypeUtils.equalTypes(specific, _int)) { - if (TypeUtils.equalTypes(general, _long)) return true; - if (TypeUtils.equalTypes(general, _byte)) return true; - if (TypeUtils.equalTypes(general, _short)) return true; + when { + TypeUtils.equalTypes(specific, _double) && TypeUtils.equalTypes(general, _float) -> return true + TypeUtils.equalTypes(specific, _int) -> { + when { + TypeUtils.equalTypes(general, _long) -> return true + TypeUtils.equalTypes(general, _byte) -> return true + TypeUtils.equalTypes(general, _short) -> return true + } + } + TypeUtils.equalTypes(specific, _short) && TypeUtils.equalTypes(general, _byte) -> return true } - if (TypeUtils.equalTypes(specific, _short) && TypeUtils.equalTypes(general, _byte)) return true; - return false; + + return false } }