From ded97baea1e20945486abf298450418ff78aed11 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Mon, 10 Nov 2025 14:26:25 +0000 Subject: [PATCH] [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. --- lib/Sema/CSSimplify.cpp | 18 ++++++++++++- .../valid_pointer_conversions.swift | 27 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index fa0c5405d83d6..cd5a402ba2b7a 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -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()) { + paramTy = packExpansion->getPatternType(); + continue; + } + // Also look through "vanishing" tuples. + if (auto *tupleTy = paramTy->getAs()) { + if (tupleTy->getNumElements() == 1 && !tupleTy->getElement(0).hasName()) { + paramTy = tupleTy->getElement(0).getType(); + continue; + } + } + break; + } if (!paramTy->isTypeParameter()) return; diff --git a/test/Constraints/valid_pointer_conversions.swift b/test/Constraints/valid_pointer_conversions.swift index 8e5ed0b07b067..5d99e7451f648 100644 --- a/test/Constraints/valid_pointer_conversions.swift +++ b/test/Constraints/valid_pointer_conversions.swift @@ -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) {} + + // 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(_ xs: repeat each T, fn: (repeat each T) -> R?) {} + func packOverloaded1(_ x: T, fn: (T) -> R?) {} + packOverloaded1("") { takesPtr($0) } + + @available(*, deprecated, message: "shouldn't have picked this overload") + func packOverloaded2(_ xs: (repeat each T)?, fn: (repeat each T) -> R?) {} + func packOverloaded2(_ x: T?, fn: (T) -> R?) {} + packOverloaded2("") { takesPtr($0) } + + @available(*, deprecated, message: "shouldn't have picked this overload") + func packOverloaded3(_ xs: repeat (each T)?, fn: (repeat each T) -> R?) {} + func packOverloaded3(_ x: T?, fn: (T) -> R?) {} + packOverloaded3("") { takesPtr($0) } + + @available(*, deprecated, message: "shouldn't have picked this overload") + func packOverloaded4(_ xs: (repeat (each T)?)?, fn: (repeat each T) -> R?) {} + func packOverloaded4(_ x: T??, fn: (T) -> R?) {} + packOverloaded4("") { takesPtr($0) } +}