[CS] Handle packs in increaseScoreForGenericParamPointerConversion

Missed this in my original patch, handle pack parameters the same as
regular generic parameters, ensuring we don't prefer a pack overload
over a generic overload just because there are pointer conversions
involved. Note this doesn't fix the wider issue of rdar://122011759,
I'm planning on looking into that in a follow-up.
This commit is contained in:
Hamish Knight
2025-11-10 14:26:25 +00:00
parent 1066c8252a
commit ded97baea1
2 changed files with 44 additions and 1 deletions

View File

@@ -15421,7 +15421,23 @@ static void increaseScoreForGenericParamPointerConversion(
return;
// Check to see if the parameter is a generic parameter, or dependent member.
auto paramTy = param->getInterfaceType()->lookThroughAllOptionalTypes();
// Look though optionals and pack expansions.
auto paramTy = param->getInterfaceType();
while (true) {
paramTy = paramTy->lookThroughAllOptionalTypes();
if (auto packExpansion = paramTy->getAs<PackExpansionType>()) {
paramTy = packExpansion->getPatternType();
continue;
}
// Also look through "vanishing" tuples.
if (auto *tupleTy = paramTy->getAs<TupleType>()) {
if (tupleTy->getNumElements() == 1 && !tupleTy->getElement(0).hasName()) {
paramTy = tupleTy->getElement(0).getType();
continue;
}
}
break;
}
if (!paramTy->isTypeParameter())
return;

View File

@@ -116,3 +116,30 @@ func testGenericPointerConversions(
// Make sure this is ambiguous.
ptr.foo(chars) // expected-error {{ambiguous use of 'foo'}}
}
// Make sure we prefer non-pack overloads when pointer conversions are involved.
func testOverloadedPackPointerConversions() {
func takesPtr(_ ptr: UnsafePointer<CChar>) {}
// Deprecation does not impact solution score, so we can use it to ensure
// we don't pick it.
@available(*, deprecated, message: "shouldn't have picked this overload")
func packOverloaded1<each T, R>(_ xs: repeat each T, fn: (repeat each T) -> R?) {}
func packOverloaded1<T, R>(_ x: T, fn: (T) -> R?) {}
packOverloaded1("") { takesPtr($0) }
@available(*, deprecated, message: "shouldn't have picked this overload")
func packOverloaded2<each T, R>(_ xs: (repeat each T)?, fn: (repeat each T) -> R?) {}
func packOverloaded2<T, R>(_ x: T?, fn: (T) -> R?) {}
packOverloaded2("") { takesPtr($0) }
@available(*, deprecated, message: "shouldn't have picked this overload")
func packOverloaded3<each T, R>(_ xs: repeat (each T)?, fn: (repeat each T) -> R?) {}
func packOverloaded3<T, R>(_ x: T?, fn: (T) -> R?) {}
packOverloaded3("") { takesPtr($0) }
@available(*, deprecated, message: "shouldn't have picked this overload")
func packOverloaded4<each T, R>(_ xs: (repeat (each T)?)?, fn: (repeat each T) -> R?) {}
func packOverloaded4<T, R>(_ x: T??, fn: (T) -> R?) {}
packOverloaded4("") { takesPtr($0) }
}