Drop "substitute with upper bounds" mode for calls with mapped arguments
(we don't need it since we build constraint system for generic types). Cleanup tests.
This commit is contained in:
+4
-17
@@ -49,29 +49,16 @@ class CandidateCallWithArgumentMapping<D : CallableDescriptor, K> private constr
|
|||||||
|
|
||||||
val isGeneric: Boolean = resolvedCall.resultingDescriptor.original.typeParameters.isNotEmpty()
|
val isGeneric: Boolean = resolvedCall.resultingDescriptor.original.typeParameters.isNotEmpty()
|
||||||
|
|
||||||
private val upperBoundsSubstitutor =
|
val extensionReceiverType: KotlinType?
|
||||||
BoundsSubstitutor.createUpperBoundsSubstitutor(resolvedCall.resultingDescriptor)
|
get() = resultingDescriptor.extensionReceiverParameter?.type
|
||||||
|
|
||||||
fun getExtensionReceiverType(substituteUpperBounds: Boolean): KotlinType? =
|
|
||||||
resultingDescriptor.extensionReceiverParameter?.type?.let {
|
|
||||||
extensionReceiverType ->
|
|
||||||
if (substituteUpperBounds)
|
|
||||||
upperBoundsSubstitutor.substitute(extensionReceiverType, Variance.INVARIANT)
|
|
||||||
else
|
|
||||||
extensionReceiverType
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the type of a value that can be used in place of the corresponding parameter.
|
* Returns the type of a value that can be used in place of the corresponding parameter.
|
||||||
*/
|
*/
|
||||||
fun getValueParameterType(argumentKey: K, substituteUpperBounds: Boolean): KotlinType? =
|
fun getValueParameterType(argumentKey: K): KotlinType? =
|
||||||
argumentsToParameters[argumentKey]?.let {
|
argumentsToParameters[argumentKey]?.let {
|
||||||
valueParameterDescriptor ->
|
valueParameterDescriptor ->
|
||||||
val valueParameterType = valueParameterDescriptor.varargElementType ?: valueParameterDescriptor.type
|
valueParameterDescriptor.varargElementType ?: valueParameterDescriptor.type
|
||||||
if (substituteUpperBounds)
|
|
||||||
upperBoundsSubstitutor.substitute(valueParameterType, Variance.INVARIANT)
|
|
||||||
else
|
|
||||||
valueParameterType
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+11
-7
@@ -74,7 +74,10 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <D : CallableDescriptor> findMaximallySpecificCall(candidates: Set<MutableResolvedCall<D>>, discriminateGenerics: Boolean): MutableResolvedCall<D>? {
|
private fun <D : CallableDescriptor> findMaximallySpecificCall(
|
||||||
|
candidates: Set<MutableResolvedCall<D>>,
|
||||||
|
discriminateGenerics: Boolean
|
||||||
|
): MutableResolvedCall<D>? {
|
||||||
val filteredCandidates = uniquifyCandidatesSet(candidates)
|
val filteredCandidates = uniquifyCandidatesSet(candidates)
|
||||||
|
|
||||||
if (filteredCandidates.size <= 1) return filteredCandidates.singleOrNull()
|
if (filteredCandidates.size <= 1) return filteredCandidates.singleOrNull()
|
||||||
@@ -180,8 +183,8 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
val extensionReceiverType1 = call1.getExtensionReceiverType(false)
|
val extensionReceiverType1 = call1.extensionReceiverType
|
||||||
val extensionReceiverType2 = call2.getExtensionReceiverType(false)
|
val extensionReceiverType2 = call2.extensionReceiverType
|
||||||
if (!compareTypesAndUpdateConstraints(extensionReceiverType1, extensionReceiverType2, RECEIVER_POSITION.position())) {
|
if (!compareTypesAndUpdateConstraints(extensionReceiverType1, extensionReceiverType2, RECEIVER_POSITION.position())) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -190,12 +193,13 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
|||||||
"$call1 and $call2 have different number of explicit arguments"
|
"$call1 and $call2 have different number of explicit arguments"
|
||||||
}
|
}
|
||||||
|
|
||||||
var index = 0
|
|
||||||
for (argumentKey in call1.argumentKeys) {
|
for (argumentKey in call1.argumentKeys) {
|
||||||
val type1 = call1.getValueParameterType(argumentKey, false)
|
val type1 = call1.getValueParameterType(argumentKey)
|
||||||
val type2 = call2.getValueParameterType(argumentKey, false)
|
val type2 = call2.getValueParameterType(argumentKey)
|
||||||
|
|
||||||
if (!compareTypesAndUpdateConstraints(type1, type2, VALUE_PARAMETER_POSITION.position(index++))) {
|
// We use this constraint system for subtyping relation check only,
|
||||||
|
// so exact value parameter position doesn't matter.
|
||||||
|
if (!compareTypesAndUpdateConstraints(type1, type2, VALUE_PARAMETER_POSITION.position(0))) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ fun discriminateGeneric(a: Int, b: String = "") = ""
|
|||||||
fun <T: CharSequence> withDefaultGeneric(t: T, d: T? = null) = 1
|
fun <T: CharSequence> withDefaultGeneric(t: T, d: T? = null) = 1
|
||||||
fun <T: Any> withDefaultGeneric(t: T, d: T? = null, a: Int = 1) = ""
|
fun <T: Any> withDefaultGeneric(t: T, d: T? = null, a: Int = 1) = ""
|
||||||
|
|
||||||
fun wrongTwoDefault(a: Any = 2) = 1
|
fun withDefaults(a: Any = 2) = 1
|
||||||
fun wrongTwoDefault(a: Int = 2, b: String = "") = ""
|
fun withDefaults(a: Int = 2, b: String = "") = ""
|
||||||
|
|
||||||
fun <T: Any> wrongWithDefaultGeneric(t: T, d: T? = null) = 1
|
fun <T: Any> withGenericDefaults(t: T, d: T? = null) = 1
|
||||||
fun <T: CharSequence> wrongWithDefaultGeneric(t: T, d: T? = null, a: Int = 1) = ""
|
fun <T: CharSequence> withGenericDefaults(t: T, d: T? = null, a: Int = 1) = ""
|
||||||
|
|
||||||
fun wrong(a: Int = 1) {}
|
fun wrong(a: Int = 1) {}
|
||||||
fun wrong(a: String = "", b: Int = 1) {}
|
fun wrong(a: String = "", b: Int = 1) {}
|
||||||
@@ -50,10 +50,9 @@ fun test() {
|
|||||||
val h = withDefaultGeneric("")
|
val h = withDefaultGeneric("")
|
||||||
h checkType { _<Int>() }
|
h checkType { _<Int>() }
|
||||||
|
|
||||||
|
withDefaults(1)
|
||||||
|
|
||||||
wrongTwoDefault(1)
|
withGenericDefaults("")
|
||||||
|
|
||||||
wrongWithDefaultGeneric("")
|
|
||||||
|
|
||||||
<!UNREACHABLE_CODE!><!OVERLOAD_RESOLUTION_AMBIGUITY!>wrong<!>(<!>null!!<!UNREACHABLE_CODE!>)<!>
|
<!UNREACHABLE_CODE!><!OVERLOAD_RESOLUTION_AMBIGUITY!>wrong<!>(<!>null!!<!UNREACHABLE_CODE!>)<!>
|
||||||
}
|
}
|
||||||
@@ -9,11 +9,11 @@ public fun twoDefault(/*0*/ a: kotlin.Any = ..., /*1*/ b: kotlin.String = ...):
|
|||||||
public fun twoDefault(/*0*/ a: kotlin.Int = ...): kotlin.Int
|
public fun twoDefault(/*0*/ a: kotlin.Int = ...): kotlin.Int
|
||||||
public fun </*0*/ T : kotlin.CharSequence> withDefaultGeneric(/*0*/ t: T, /*1*/ d: T? = ...): kotlin.Int
|
public fun </*0*/ T : kotlin.CharSequence> withDefaultGeneric(/*0*/ t: T, /*1*/ d: T? = ...): kotlin.Int
|
||||||
public fun </*0*/ T : kotlin.Any> withDefaultGeneric(/*0*/ t: T, /*1*/ d: T? = ..., /*2*/ a: kotlin.Int = ...): kotlin.String
|
public fun </*0*/ T : kotlin.Any> withDefaultGeneric(/*0*/ t: T, /*1*/ d: T? = ..., /*2*/ a: kotlin.Int = ...): kotlin.String
|
||||||
|
public fun withDefaults(/*0*/ a: kotlin.Any = ...): kotlin.Int
|
||||||
|
public fun withDefaults(/*0*/ a: kotlin.Int = ..., /*1*/ b: kotlin.String = ...): kotlin.String
|
||||||
public fun </*0*/ T> withGeneric(/*0*/ a: T): kotlin.Int
|
public fun </*0*/ T> withGeneric(/*0*/ a: T): kotlin.Int
|
||||||
public fun </*0*/ T> withGeneric(/*0*/ a: T, /*1*/ b: kotlin.Int = ...): kotlin.String
|
public fun </*0*/ T> withGeneric(/*0*/ a: T, /*1*/ b: kotlin.Int = ...): kotlin.String
|
||||||
|
public fun </*0*/ T : kotlin.Any> withGenericDefaults(/*0*/ t: T, /*1*/ d: T? = ...): kotlin.Int
|
||||||
|
public fun </*0*/ T : kotlin.CharSequence> withGenericDefaults(/*0*/ t: T, /*1*/ d: T? = ..., /*2*/ a: kotlin.Int = ...): kotlin.String
|
||||||
public fun wrong(/*0*/ a: kotlin.Int = ...): kotlin.Unit
|
public fun wrong(/*0*/ a: kotlin.Int = ...): kotlin.Unit
|
||||||
public fun wrong(/*0*/ a: kotlin.String = ..., /*1*/ b: kotlin.Int = ...): kotlin.Unit
|
public fun wrong(/*0*/ a: kotlin.String = ..., /*1*/ b: kotlin.Int = ...): kotlin.Unit
|
||||||
public fun wrongTwoDefault(/*0*/ a: kotlin.Any = ...): kotlin.Int
|
|
||||||
public fun wrongTwoDefault(/*0*/ a: kotlin.Int = ..., /*1*/ b: kotlin.String = ...): kotlin.String
|
|
||||||
public fun </*0*/ T : kotlin.Any> wrongWithDefaultGeneric(/*0*/ t: T, /*1*/ d: T? = ...): kotlin.Int
|
|
||||||
public fun </*0*/ T : kotlin.CharSequence> wrongWithDefaultGeneric(/*0*/ t: T, /*1*/ d: T? = ..., /*2*/ a: kotlin.Int = ...): kotlin.String
|
|
||||||
|
|||||||
+1
-1
@@ -6,4 +6,4 @@ class A<T>
|
|||||||
fun <T1> A<T1>.foo() = X1
|
fun <T1> A<T1>.foo() = X1
|
||||||
fun <T2> A<out T2>.foo() = X2
|
fun <T2> A<out T2>.foo() = X2
|
||||||
|
|
||||||
fun <T> A<out T>.test() = <!CANNOT_COMPLETE_RESOLVE!>foo<!>()
|
fun <T> A<out T>.test() = <!CANNOT_COMPLETE_RESOLVE!>foo<!>() // TODO fix constraint system
|
||||||
Reference in New Issue
Block a user