From 65cfef655542184996b6d8bbec44941b63a48546 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 23 Mar 2023 17:23:34 -0700 Subject: [PATCH] [CSSimplify] Account for the fact that variadic generic parameters could be specialized If generic parameter comes from a variadic type declaration it's possible that it got specialized early and is no longer represented by a pack expansion type. For example, consider expression - `Test(42)` where `Test` and the initializer is declared as `init(_: repeat each T)`. Although declaration based information reports parameter at index 0 as variadic generic the call site specializes it to `Int`. Resolves: rdar://107151854 --- lib/Sema/CSSimplify.cpp | 29 ++++++++++++------- .../pack-expansion-expressions.swift | 12 ++++++++ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index d9f1d46a238df..62c8cea74d9a4 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -1742,21 +1742,28 @@ static ConstraintSystem::TypeMatchResult matchCallArguments( // inout and @autoclosure. if (cs.getASTContext().LangOpts.hasFeature(Feature::VariadicGenerics) && paramInfo.isVariadicGenericParameter(paramIdx)) { - auto *paramPackExpansion = paramTy->castTo(); - - SmallVector argTypes; - for (auto argIdx : parameterBindings[paramIdx]) { - auto argType = argsWithLabels[argIdx].getPlainType(); - argTypes.push_back(argType); - } + // If generic parameter comes from a variadic type declaration it's + // possible that it got specialized early and is no longer represented + // by a pack expansion type. For example, consider expression - + // `Test(42)` where `Test` and the initializer + // is declared as `init(_: repeat each T)`. Although declaration + // based information reports parameter at index 0 as variadic generic + // the call site specializes it to `Int`. + if (auto *paramPackExpansion = paramTy->getAs()) { + SmallVector argTypes; + for (auto argIdx : parameterBindings[paramIdx]) { + auto argType = argsWithLabels[argIdx].getPlainType(); + argTypes.push_back(argType); + } - auto *argPack = PackType::get(cs.getASTContext(), argTypes); - auto *argPackExpansion = PackExpansionType::get(argPack, argPack); + auto *argPack = PackType::get(cs.getASTContext(), argTypes); + auto *argPackExpansion = PackExpansionType::get(argPack, argPack); - cs.addConstraint( + cs.addConstraint( subKind, argPackExpansion, paramPackExpansion, loc, /*isFavored=*/false); - continue; + continue; + } } // If type inference from default arguments is enabled, let's diff --git a/test/Constraints/pack-expansion-expressions.swift b/test/Constraints/pack-expansion-expressions.swift index af71c93c095db..7f82b2e1968be 100644 --- a/test/Constraints/pack-expansion-expressions.swift +++ b/test/Constraints/pack-expansion-expressions.swift @@ -271,3 +271,15 @@ func test_pack_expansions_with_closures() { takesVariadicFunction { y, z in fn(y, z) } // Ok } } + +// rdar://107151854 - crash on invalid due to specialized pack expansion +func test_pack_expansion_specialization() { + struct Data { + init(_: repeat each T) {} // expected-note {{'init(_:)' declared here}} + } + + _ = Data() // expected-error {{missing argument for parameter #1 in call}} + _ = Data(0) // Ok + _ = Data(42, "") // Ok + _ = Data(42, "") // expected-error {{extra argument in call}} +}