Generalize signature comparison: checking for conflicting overloads.
Also, vararg parameter no longer conflicts with Array<out T> (CONFLICTING_JVM_DECLARATIONS is reported, can be avoided using @JvmName).
This commit is contained in:
@@ -21,15 +21,14 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.INCOMPATIBLE
|
import org.jetbrains.kotlin.resolve.calls.results.FlatSignature
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.CallHandle
|
import org.jetbrains.kotlin.resolve.calls.results.SpecificityComparisonCallbacks
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
import org.jetbrains.kotlin.resolve.calls.results.isSignatureNotLessSpecific
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl
|
import org.jetbrains.kotlin.resolve.calls.results.varargParameterPosition
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
||||||
|
|
||||||
object OverloadUtil {
|
object OverloadUtil {
|
||||||
@@ -46,52 +45,29 @@ object OverloadUtil {
|
|||||||
return checkOverloadability(a, b)
|
return checkOverloadability(a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object OverloadabilitySpecificityCallbacks : SpecificityComparisonCallbacks {
|
||||||
|
override fun isNonSubtypeNotLessSpecific(specific: KotlinType, general: KotlinType): Boolean =
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
private fun checkOverloadability(a: CallableDescriptor, b: CallableDescriptor): Boolean {
|
private fun checkOverloadability(a: CallableDescriptor, b: CallableDescriptor): Boolean {
|
||||||
if (a.hasLowPriorityInOverloadResolution() != b.hasLowPriorityInOverloadResolution()) return true
|
if (a.hasLowPriorityInOverloadResolution() != b.hasLowPriorityInOverloadResolution()) return true
|
||||||
|
|
||||||
|
// NB this makes generic and non-generic declarations with equivalent signatures non-conflicting
|
||||||
|
// E.g., 'fun <T> foo()' and 'fun foo()'.
|
||||||
|
// They can be disambiguated by providing explicit type parameters.
|
||||||
if (a.typeParameters.isEmpty() != b.typeParameters.isEmpty()) return true
|
if (a.typeParameters.isEmpty() != b.typeParameters.isEmpty()) return true
|
||||||
|
|
||||||
OverridingUtil.checkReceiverAndParameterCount(a, b)?.let { return it.result == INCOMPATIBLE }
|
if (ErrorUtils.containsErrorType(a) || ErrorUtils.containsErrorType(b)) return true
|
||||||
|
if (a.varargParameterPosition() != b.varargParameterPosition()) return true
|
||||||
|
|
||||||
val aValueParameters = OverridingUtil.compiledValueParameters(a)
|
val aSignature = FlatSignature.createFromCallableDescriptor(a)
|
||||||
val bValueParameters = OverridingUtil.compiledValueParameters(b)
|
val bSignature = FlatSignature.createFromCallableDescriptor(b)
|
||||||
|
|
||||||
val aTypeParameters = a.typeParameters
|
val aIsNotLessSpecificThanB = isSignatureNotLessSpecific(aSignature, bSignature, OverloadabilitySpecificityCallbacks)
|
||||||
val bTypeParameters = b.typeParameters
|
val bIsNotLessSpecificThanA = isSignatureNotLessSpecific(bSignature, aSignature, OverloadabilitySpecificityCallbacks)
|
||||||
|
|
||||||
val avsbConstraintsBuilder: ConstraintSystem.Builder = ConstraintSystemBuilderImpl()
|
return !(aIsNotLessSpecificThanB && bIsNotLessSpecificThanA)
|
||||||
val avsbTypeSubstitutor = avsbConstraintsBuilder.registerTypeVariables(CallHandle.NONE, aTypeParameters)
|
|
||||||
val bvsaConstraintsBuilder: ConstraintSystem.Builder = ConstraintSystemBuilderImpl()
|
|
||||||
val bvsaTypeSubstitutor = bvsaConstraintsBuilder.registerTypeVariables(CallHandle.NONE, bTypeParameters)
|
|
||||||
|
|
||||||
var constraintIndex = 0
|
|
||||||
|
|
||||||
for ((aType, bType) in aValueParameters.zip(bValueParameters)) {
|
|
||||||
if (aType.isError || bType.isError) return true
|
|
||||||
|
|
||||||
if (oneMoreSpecificThanAnother(bType, aType)) return true
|
|
||||||
|
|
||||||
if (!TypeUtils.dependsOnTypeParameters(aType, aTypeParameters)
|
|
||||||
&& !TypeUtils.dependsOnTypeParameters(bType, bTypeParameters)
|
|
||||||
&& !KotlinTypeChecker.DEFAULT.equalTypes(aType, bType)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
constraintIndex++
|
|
||||||
val aTypeSubstituted = avsbTypeSubstitutor.safeSubstitute(aType, Variance.INVARIANT)
|
|
||||||
val bTypeSubstituted = bvsaTypeSubstitutor.safeSubstitute(bType, Variance.INVARIANT)
|
|
||||||
avsbConstraintsBuilder.addSubtypeConstraint(bType, aTypeSubstituted,
|
|
||||||
VALUE_PARAMETER_POSITION.position(constraintIndex))
|
|
||||||
bvsaConstraintsBuilder.addSubtypeConstraint(aType, bTypeSubstituted,
|
|
||||||
VALUE_PARAMETER_POSITION.position(constraintIndex))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (constraintIndex == 0) return false
|
|
||||||
|
|
||||||
avsbConstraintsBuilder.fixVariables()
|
|
||||||
bvsaConstraintsBuilder.fixVariables()
|
|
||||||
|
|
||||||
return avsbConstraintsBuilder.build().status.hasContradiction()
|
|
||||||
|| bvsaConstraintsBuilder.build().status.hasContradiction()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum class DeclarationCategory {
|
private enum class DeclarationCategory {
|
||||||
|
|||||||
@@ -30,49 +30,50 @@ class FlatSignature<out T>(
|
|||||||
val origin: T,
|
val origin: T,
|
||||||
val typeParameters: Collection<TypeParameterDescriptor>,
|
val typeParameters: Collection<TypeParameterDescriptor>,
|
||||||
val valueParameterTypes: List<KotlinType?>,
|
val valueParameterTypes: List<KotlinType?>,
|
||||||
|
val hasExtensionReceiver: Boolean,
|
||||||
val hasVarargs: Boolean,
|
val hasVarargs: Boolean,
|
||||||
val numDefaults: Int
|
val numDefaults: Int
|
||||||
) {
|
) {
|
||||||
val isGeneric = typeParameters.isNotEmpty()
|
val isGeneric = typeParameters.isNotEmpty()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun <D : CallableDescriptor, RC : ResolvedCall<D>> createFromResolvedCall(call: RC): FlatSignature<RC> {
|
fun <D : CallableDescriptor, RC : ResolvedCall<D>> createFromResolvedCall(resolvedCall: RC): FlatSignature<RC> {
|
||||||
val originalDescriptor = call.candidateDescriptor.original
|
val originalDescriptor = resolvedCall.candidateDescriptor.original
|
||||||
val originalValueParameters = originalDescriptor.valueParameters
|
val originalValueParameters = originalDescriptor.valueParameters
|
||||||
val originalTypeParameters = originalDescriptor.typeParameters
|
|
||||||
|
|
||||||
var numDefaults = 0
|
var numDefaults = 0
|
||||||
val valueArgumentToParameterType = HashMap<ValueArgument, KotlinType>()
|
val valueArgumentToParameterType = HashMap<ValueArgument, KotlinType>()
|
||||||
for ((valueParameter, resolvedValueArgument) in call.valueArguments.entries) {
|
for ((valueParameter, resolvedValueArgument) in resolvedCall.valueArguments.entries) {
|
||||||
if (resolvedValueArgument is DefaultValueArgument) {
|
if (resolvedValueArgument is DefaultValueArgument) {
|
||||||
numDefaults++
|
numDefaults++
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val originalValueParameter = originalValueParameters[valueParameter.index]
|
val originalValueParameter = originalValueParameters[valueParameter.index]
|
||||||
val parameterType = originalValueParameter.flatType
|
val parameterType = originalValueParameter.argumentValueType
|
||||||
for (valueArgument in resolvedValueArgument.arguments) {
|
for (valueArgument in resolvedValueArgument.arguments) {
|
||||||
if (valueArgument.getArgumentExpression() == null) continue
|
|
||||||
valueArgumentToParameterType[valueArgument] = parameterType
|
valueArgumentToParameterType[valueArgument] = parameterType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val valueArgumentParameterTypes = call.call.valueArguments.map { valueArgumentToParameterType[it] }
|
return FlatSignature(resolvedCall,
|
||||||
val valueParameterTypes = originalDescriptor.extensionReceiverTypeOrEmpty() + valueArgumentParameterTypes
|
originalDescriptor.typeParameters,
|
||||||
|
valueParameterTypes = originalDescriptor.extensionReceiverTypeOrEmpty() +
|
||||||
val hasVarargs = originalDescriptor.valueParameters.any { it.varargElementType != null }
|
resolvedCall.call.valueArguments.map { valueArgumentToParameterType[it] },
|
||||||
|
hasExtensionReceiver = originalDescriptor.extensionReceiverParameter != null,
|
||||||
return FlatSignature(call, originalTypeParameters, valueParameterTypes, hasVarargs, numDefaults)
|
hasVarargs = originalDescriptor.valueParameters.any { it.varargElementType != null },
|
||||||
|
numDefaults = numDefaults)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <D : CallableDescriptor> createFromCallableDescriptor(descriptor: D): FlatSignature<D> =
|
fun <D : CallableDescriptor> createFromCallableDescriptor(descriptor: D): FlatSignature<D> =
|
||||||
FlatSignature(descriptor,
|
FlatSignature(descriptor,
|
||||||
descriptor.typeParameters,
|
descriptor.typeParameters,
|
||||||
valueParameterTypes = descriptor.extensionReceiverTypeOrEmpty() + descriptor.valueParameters.map { it.flatType },
|
valueParameterTypes = descriptor.extensionReceiverTypeOrEmpty() + descriptor.valueParameters.map { it.argumentValueType },
|
||||||
|
hasExtensionReceiver = descriptor.extensionReceiverParameter != null,
|
||||||
hasVarargs = descriptor.valueParameters.any { it.varargElementType != null },
|
hasVarargs = descriptor.valueParameters.any { it.varargElementType != null },
|
||||||
numDefaults = 0)
|
numDefaults = 0)
|
||||||
|
|
||||||
val ValueParameterDescriptor.flatType: KotlinType
|
val ValueParameterDescriptor.argumentValueType: KotlinType
|
||||||
get() = varargElementType ?: type
|
get() = varargElementType ?: type
|
||||||
|
|
||||||
fun CallableDescriptor.extensionReceiverTypeOrEmpty() =
|
fun CallableDescriptor.extensionReceiverTypeOrEmpty() =
|
||||||
|
|||||||
+23
-28
@@ -23,52 +23,47 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.valuePara
|
|||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
|
|
||||||
interface SpecificityComparisonCallbacks<T> {
|
interface SpecificityComparisonCallbacks {
|
||||||
fun isNotLessSpecificSignature(signature1: FlatSignature<T>, signature2: FlatSignature<T>): Boolean?
|
fun isNonSubtypeNotLessSpecific(specific: KotlinType, general: KotlinType): Boolean
|
||||||
fun isTypeNotLessSpecific(type1: KotlinType, type2: KotlinType): Boolean?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> isSignatureNotLessSpecific(
|
fun <T> isSignatureNotLessSpecific(
|
||||||
signature1: FlatSignature<T>,
|
specific: FlatSignature<T>,
|
||||||
signature2: FlatSignature<T>,
|
general: FlatSignature<T>,
|
||||||
callHandle: CallHandle,
|
callbacks: SpecificityComparisonCallbacks,
|
||||||
callbacks: SpecificityComparisonCallbacks<T>
|
callHandle: CallHandle = CallHandle.NONE
|
||||||
): Boolean {
|
): Boolean {
|
||||||
callbacks.isNotLessSpecificSignature(signature1, signature2)?.let { return it }
|
if (specific.hasExtensionReceiver != general.hasExtensionReceiver) return false
|
||||||
|
if (specific.valueParameterTypes.size != general.valueParameterTypes.size) return false
|
||||||
|
|
||||||
val typeParameters = signature2.typeParameters
|
val typeParameters = general.typeParameters
|
||||||
val constraintSystemBuilder: ConstraintSystem.Builder = ConstraintSystemBuilderImpl()
|
val constraintSystemBuilder: ConstraintSystem.Builder = ConstraintSystemBuilderImpl()
|
||||||
var numConstraints = 0
|
|
||||||
val typeSubstitutor = constraintSystemBuilder.registerTypeVariables(callHandle, typeParameters)
|
val typeSubstitutor = constraintSystemBuilder.registerTypeVariables(callHandle, typeParameters)
|
||||||
|
|
||||||
for ((type1, type2) in signature1.valueParameterTypes.zip(signature2.valueParameterTypes)) {
|
var numConstraints = 0
|
||||||
if (type1 == null || type2 == null) continue
|
for ((specificType, generalType) in specific.valueParameterTypes.zip(general.valueParameterTypes)) {
|
||||||
|
if (specificType == null || generalType == null) continue
|
||||||
|
|
||||||
if (isDefinitelyLessSpecificByTypeSpecificity(type1, type2)) {
|
if (isDefinitelyLessSpecificByTypeSpecificity(specificType, generalType)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeParameters.isEmpty() || !TypeUtils.dependsOnTypeParameters(type2, typeParameters)) {
|
if (typeParameters.isEmpty() || !TypeUtils.dependsOnTypeParameters(generalType, typeParameters)) {
|
||||||
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(type1, type2)) {
|
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(specificType, generalType)) {
|
||||||
callbacks.isTypeNotLessSpecific(type1, type2)?.let { if (!it) return false }
|
if (!callbacks.isNonSubtypeNotLessSpecific(specificType, generalType)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val constraintPosition = valueParameterPosition(numConstraints++)
|
val substitutedGeneralType = typeSubstitutor.safeSubstitute(generalType, Variance.INVARIANT)
|
||||||
val substitutedType2 = typeSubstitutor.safeSubstitute(type2, Variance.INVARIANT)
|
constraintSystemBuilder.addSubtypeConstraint(specificType, substitutedGeneralType, valueParameterPosition(numConstraints++))
|
||||||
constraintSystemBuilder.addSubtypeConstraint(type1, substitutedType2, constraintPosition)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numConstraints > 0) {
|
constraintSystemBuilder.fixVariables()
|
||||||
constraintSystemBuilder.fixVariables()
|
val constraintSystem = constraintSystemBuilder.build()
|
||||||
val constraintSystem = constraintSystemBuilder.build()
|
return !constraintSystem.status.hasContradiction()
|
||||||
if (constraintSystem.status.hasContradiction()) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isDefinitelyLessSpecificByTypeSpecificity(specific: KotlinType, general: KotlinType): Boolean {
|
private fun isDefinitelyLessSpecificByTypeSpecificity(specific: KotlinType, general: KotlinType): Boolean {
|
||||||
|
|||||||
+25
-42
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.CallHandle
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.toHandle
|
import org.jetbrains.kotlin.resolve.calls.inference.toHandle
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
@@ -147,18 +146,22 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
|||||||
call1: FlatSignature<MutableResolvedCall<D>>,
|
call1: FlatSignature<MutableResolvedCall<D>>,
|
||||||
call2: FlatSignature<MutableResolvedCall<D>>,
|
call2: FlatSignature<MutableResolvedCall<D>>,
|
||||||
discriminateGenerics: Boolean
|
discriminateGenerics: Boolean
|
||||||
): Boolean =
|
): Boolean {
|
||||||
isSignatureNotLessSpecific(call1, call2, call1.callHandle(),
|
if (discriminateGenerics) {
|
||||||
if (discriminateGenerics)
|
val isGeneric1 = call1.isGeneric
|
||||||
SpecificityComparisonDiscriminatingGenerics
|
val isGeneric2 = call2.isGeneric
|
||||||
else
|
// generic loses to non-generic
|
||||||
DefaultCallSpecificityComparison)
|
if (isGeneric1 && !isGeneric2) return false
|
||||||
|
if (!isGeneric1 && isGeneric2) return true
|
||||||
|
// two generics are non-comparable
|
||||||
|
if (isGeneric1 && isGeneric2) return false
|
||||||
|
}
|
||||||
|
|
||||||
private abstract inner class SpecificityComparisonWithNumerics<T> : SpecificityComparisonCallbacks<T> {
|
return isSignatureNotLessSpecific(call1, call2, SpecificityComparisonWithNumerics, call1.callHandle())
|
||||||
override fun isNotLessSpecificSignature(signature1: FlatSignature<T>, signature2: FlatSignature<T>): Boolean?
|
}
|
||||||
= null
|
|
||||||
|
|
||||||
override fun isTypeNotLessSpecific(type1: KotlinType, type2: KotlinType): Boolean? {
|
private val SpecificityComparisonWithNumerics = object : SpecificityComparisonCallbacks {
|
||||||
|
override fun isNonSubtypeNotLessSpecific(specific: KotlinType, general: KotlinType): Boolean {
|
||||||
val _double = builtIns.doubleType
|
val _double = builtIns.doubleType
|
||||||
val _float = builtIns.floatType
|
val _float = builtIns.floatType
|
||||||
val _long = builtIns.longType
|
val _long = builtIns.longType
|
||||||
@@ -167,41 +170,21 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
|||||||
val _short = builtIns.shortType
|
val _short = builtIns.shortType
|
||||||
|
|
||||||
when {
|
when {
|
||||||
TypeUtils.equalTypes(type1, _double) && TypeUtils.equalTypes(type2, _float) -> return true
|
TypeUtils.equalTypes(specific, _double) && TypeUtils.equalTypes(general, _float) -> return true
|
||||||
TypeUtils.equalTypes(type1, _int) -> {
|
TypeUtils.equalTypes(specific, _int) -> {
|
||||||
when {
|
when {
|
||||||
TypeUtils.equalTypes(type2, _long) -> return true
|
TypeUtils.equalTypes(general, _long) -> return true
|
||||||
TypeUtils.equalTypes(type2, _byte) -> return true
|
TypeUtils.equalTypes(general, _byte) -> return true
|
||||||
TypeUtils.equalTypes(type2, _short) -> return true
|
TypeUtils.equalTypes(general, _short) -> return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TypeUtils.equalTypes(type1, _short) && TypeUtils.equalTypes(type2, _byte) -> return true
|
TypeUtils.equalTypes(specific, _short) && TypeUtils.equalTypes(general, _byte) -> return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val DefaultCallSpecificityComparison = object : SpecificityComparisonWithNumerics<MutableResolvedCall<*>>() {}
|
|
||||||
private val DefaultDescriptorSpecificityComparison = object : SpecificityComparisonWithNumerics<CallableDescriptor>() {}
|
|
||||||
|
|
||||||
private val SpecificityComparisonDiscriminatingGenerics = object : SpecificityComparisonWithNumerics<MutableResolvedCall<*>>() {
|
|
||||||
override fun isNotLessSpecificSignature(
|
|
||||||
signature1: FlatSignature<MutableResolvedCall<*>>,
|
|
||||||
signature2: FlatSignature<MutableResolvedCall<*>>
|
|
||||||
): Boolean? {
|
|
||||||
val isGeneric1 = signature1.isGeneric
|
|
||||||
val isGeneric2 = signature2.isGeneric
|
|
||||||
// generic loses to non-generic
|
|
||||||
if (isGeneric1 && !isGeneric2) return false
|
|
||||||
if (!isGeneric1 && isGeneric2) return true
|
|
||||||
// two generics are non-comparable
|
|
||||||
if (isGeneric1 && isGeneric2) return false
|
|
||||||
// otherwise continue comparing signatures
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <D: CallableDescriptor> isOfNotLessSpecificShape(
|
private fun <D: CallableDescriptor> isOfNotLessSpecificShape(
|
||||||
call1: FlatSignature<MutableResolvedCall<D>>,
|
call1: FlatSignature<MutableResolvedCall<D>>,
|
||||||
call2: FlatSignature<MutableResolvedCall<D>>
|
call2: FlatSignature<MutableResolvedCall<D>>
|
||||||
@@ -250,23 +233,23 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns `true` if `d1` is definitely not less specific than `d2`,
|
* Returns `true` if `f` is definitely not less specific than `g`,
|
||||||
* `false` if `d1` is definitely less specific than `d2`,
|
* `false` if `f` is definitely less specific than `g`,
|
||||||
* `null` if undecided.
|
* `null` if undecided.
|
||||||
*/
|
*/
|
||||||
private fun compareFunctionParameterTypes(f: CallableDescriptor, g: CallableDescriptor): Boolean {
|
private fun isNotLessSpecificCallableReferenceDescriptor(f: CallableDescriptor, g: CallableDescriptor): Boolean {
|
||||||
if (f.valueParameters.size != g.valueParameters.size) return false
|
if (f.valueParameters.size != g.valueParameters.size) return false
|
||||||
if (f.varargParameterPosition() != g.varargParameterPosition()) return false
|
if (f.varargParameterPosition() != g.varargParameterPosition()) return false
|
||||||
|
|
||||||
val fSignature = FlatSignature.createFromCallableDescriptor(f)
|
val fSignature = FlatSignature.createFromCallableDescriptor(f)
|
||||||
val gSignature = FlatSignature.createFromCallableDescriptor(g)
|
val gSignature = FlatSignature.createFromCallableDescriptor(g)
|
||||||
return isSignatureNotLessSpecific(fSignature, gSignature, CallHandle.NONE, DefaultDescriptorSpecificityComparison)
|
return isSignatureNotLessSpecific(fSignature, gSignature, SpecificityComparisonWithNumerics)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isNotLessSpecificCallableReference(f: CallableDescriptor, g: CallableDescriptor): Boolean =
|
private fun isNotLessSpecificCallableReference(f: CallableDescriptor, g: CallableDescriptor): Boolean =
|
||||||
// TODO should we "discriminate generic descriptors" for callable references?
|
// TODO should we "discriminate generic descriptors" for callable references?
|
||||||
tryCompareDescriptorsFromScripts(f, g) ?:
|
tryCompareDescriptorsFromScripts(f, g) ?:
|
||||||
compareFunctionParameterTypes(f, g)
|
isNotLessSpecificCallableReferenceDescriptor(f, g)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// Different smartcasts may lead to the same candidate descriptor wrapped into different ResolvedCallImpl objects
|
// Different smartcasts may lead to the same candidate descriptor wrapped into different ResolvedCallImpl objects
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
<!CONFLICTING_OVERLOADS!>fun foo(vararg <!UNUSED_PARAMETER!>x<!>: Int)<!> {}
|
<!CONFLICTING_JVM_DECLARATIONS!>fun foo(vararg <!UNUSED_PARAMETER!>x<!>: Int)<!> {}
|
||||||
<!CONFLICTING_OVERLOADS!>fun foo(<!UNUSED_PARAMETER!>x<!>: IntArray)<!> {}
|
<!CONFLICTING_JVM_DECLARATIONS!>fun foo(<!UNUSED_PARAMETER!>x<!>: IntArray)<!> {}
|
||||||
|
|
||||||
<!CONFLICTING_JVM_DECLARATIONS!>fun foo(vararg <!UNUSED_PARAMETER!>x<!>: Int?)<!> {}
|
<!CONFLICTING_JVM_DECLARATIONS!>fun foo(vararg <!UNUSED_PARAMETER!>x<!>: Int?)<!> {}
|
||||||
<!CONFLICTING_JVM_DECLARATIONS!>fun foo(<!UNUSED_PARAMETER!>x<!>: Array<Int>)<!> {}
|
<!CONFLICTING_JVM_DECLARATIONS!>fun foo(<!UNUSED_PARAMETER!>x<!>: Array<Int>)<!> {}
|
||||||
|
|
||||||
|
<!CONFLICTING_JVM_DECLARATIONS!>fun foo(vararg <!UNUSED_PARAMETER!>nn<!>: Number)<!> {}
|
||||||
|
<!CONFLICTING_JVM_DECLARATIONS!>fun foo(<!UNUSED_PARAMETER!>nn<!>: Array<out Number>)<!> {}
|
||||||
@@ -2,5 +2,7 @@ package
|
|||||||
|
|
||||||
public fun foo(/*0*/ x: kotlin.Array<kotlin.Int>): kotlin.Unit
|
public fun foo(/*0*/ x: kotlin.Array<kotlin.Int>): kotlin.Unit
|
||||||
public fun foo(/*0*/ vararg x: kotlin.Int? /*kotlin.Array<out kotlin.Int?>*/): kotlin.Unit
|
public fun foo(/*0*/ vararg x: kotlin.Int? /*kotlin.Array<out kotlin.Int?>*/): kotlin.Unit
|
||||||
|
public fun foo(/*0*/ nn: kotlin.Array<out kotlin.Number>): kotlin.Unit
|
||||||
|
public fun foo(/*0*/ vararg nn: kotlin.Number /*kotlin.Array<out kotlin.Number>*/): kotlin.Unit
|
||||||
public fun foo(/*0*/ vararg x: kotlin.Int /*kotlin.IntArray*/): kotlin.Unit
|
public fun foo(/*0*/ vararg x: kotlin.Int /*kotlin.IntArray*/): kotlin.Unit
|
||||||
public fun foo(/*0*/ x: kotlin.IntArray): kotlin.Unit
|
public fun foo(/*0*/ x: kotlin.IntArray): kotlin.Unit
|
||||||
|
|||||||
@@ -136,6 +136,15 @@ public class ErrorUtils {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean containsErrorType(@NotNull CallableDescriptor callableDescriptor) {
|
||||||
|
if (callableDescriptor instanceof FunctionDescriptor) {
|
||||||
|
return containsErrorType((FunctionDescriptor) callableDescriptor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return containsErrorType(callableDescriptor.getReturnType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean containsErrorType(@NotNull FunctionDescriptor function) {
|
public static boolean containsErrorType(@NotNull FunctionDescriptor function) {
|
||||||
if (containsErrorType(function.getReturnType())) {
|
if (containsErrorType(function.getReturnType())) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user