Skip to content

Commit 15ea972

Browse files
authored
Merge pull request #64672 from xedin/pack-expansion-param-in-init-5.9
[5.9][ConstraintSystem] Fix support for a single pack expansion parameter …
2 parents e15998e + d4b545a commit 15ea972

File tree

3 files changed

+53
-14
lines changed

3 files changed

+53
-14
lines changed

lib/Sema/CSGen.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1699,7 +1699,8 @@ namespace {
16991699
if (!CS.getASTContext().isSwiftVersionAtLeast(6)) {
17001700
auto paramTypeVar = CS.createTypeVariable(
17011701
CS.getConstraintLocator(expr, ConstraintLocator::ApplyArgument),
1702-
TVO_CanBindToLValue | TVO_CanBindToInOut | TVO_CanBindToNoEscape);
1702+
TVO_CanBindToLValue | TVO_CanBindToInOut | TVO_CanBindToNoEscape |
1703+
TVO_CanBindToPack);
17031704
CS.addConstraint(ConstraintKind::BindTupleOfFunctionParams, methodTy,
17041705
paramTypeVar, CS.getConstraintLocator(expr));
17051706
}

lib/Sema/CSSimplify.cpp

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4318,21 +4318,37 @@ ConstraintSystem::matchTypesBindTypeVar(
43184318
return getTypeMatchFailure(locator);
43194319
}
43204320

4321-
// Binding to a pack expansion type is always an error. This indicates
4322-
// that a pack expansion expression was used in a context that doesn't
4323-
// support it.
4321+
// Binding to a pack expansion type is always an error in Swift 6 mode.
4322+
// This indicates that a pack expansion expression was used in a context
4323+
// that doesn't support it.
4324+
//
4325+
// In Swift 5 and earlier initializer references are handled in a special
4326+
// way that uses a type variable to represent a type of the parameter
4327+
// list. Such type variables should be allowed to bind to a pack expansion
4328+
// type to support cases where initializer has a single unlabeled variadic
4329+
// generic parameter - `init(_ data: repeat each T)`.
4330+
//
4331+
// See BindTupleOfFunctionParams constraint for more details.
43244332
if (type->is<PackExpansionType>()) {
4325-
if (!shouldAttemptFixes())
4326-
return getTypeMatchFailure(locator);
4333+
bool representsParameterList =
4334+
typeVar->getImpl()
4335+
.getLocator()
4336+
->isLastElement<LocatorPathElt::ApplyArgument>();
43274337

4328-
auto *fix =
4329-
AllowInvalidPackExpansion::create(*this, getConstraintLocator(locator));
4330-
if (recordFix(fix))
4331-
return getTypeMatchFailure(locator);
4338+
if (!(typeVar->getImpl().canBindToPack() && representsParameterList) ||
4339+
getASTContext().isSwiftVersionAtLeast(6)) {
4340+
if (!shouldAttemptFixes())
4341+
return getTypeMatchFailure(locator);
43324342

4333-
// Don't allow the pack expansion type to propagate to other
4334-
// bindings.
4335-
type = PlaceholderType::get(typeVar->getASTContext(), typeVar);
4343+
auto *fix = AllowInvalidPackExpansion::create(
4344+
*this, getConstraintLocator(locator));
4345+
if (recordFix(fix))
4346+
return getTypeMatchFailure(locator);
4347+
4348+
// Don't allow the pack expansion type to propagate to other
4349+
// bindings.
4350+
type = PlaceholderType::get(typeVar->getASTContext(), typeVar);
4351+
}
43364352
}
43374353

43384354
// We do not allow keypaths to go through AnyObject. Let's create a fix
@@ -7867,7 +7883,8 @@ ConstraintSystem::simplifyConstructionConstraint(
78677883
if (!getASTContext().isSwiftVersionAtLeast(6)) {
78687884
auto paramTypeVar = createTypeVariable(
78697885
getConstraintLocator(locator, ConstraintLocator::ApplyArgument),
7870-
TVO_CanBindToLValue | TVO_CanBindToInOut | TVO_CanBindToNoEscape);
7886+
TVO_CanBindToLValue | TVO_CanBindToInOut | TVO_CanBindToNoEscape |
7887+
TVO_CanBindToPack);
78717888
addConstraint(ConstraintKind::BindTupleOfFunctionParams, memberType,
78727889
paramTypeVar, locator);
78737890
}

test/Constraints/pack-expansion-expressions.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,27 @@ func invalidRepeat<each T>(t: repeat each T) {
262262
// expected-error@-1 {{value pack expansion can only appear inside a function argument list or tuple element}}
263263
}
264264

265+
// Make sure that single parameter initializers are handled correctly because
266+
// the have special type-checking rules in Swift < 6.
267+
func test_init_refs_with_single_pack_expansion_param() {
268+
struct Data<each V> {
269+
init(_: repeat each V) {}
270+
}
271+
272+
_ = Data() // Ok
273+
_ = Data(42) // Ok
274+
_ = Data(42, "") // Ok
275+
276+
struct EmptyAmbiguous<each V> {
277+
init(_: repeat each V) {} // expected-note {{found this candidate}}
278+
init(x: repeat each V) {} // expected-note {{found this candidate}}
279+
}
280+
281+
_ = EmptyAmbiguous() // expected-error {{ambiguous use of 'init'}}
282+
_ = EmptyAmbiguous(x: 42)
283+
_ = EmptyAmbiguous(x: (42, "")) // Ok
284+
}
285+
265286
func test_pack_expansions_with_closures() {
266287
func takesVariadicFunction<each T>(function: (repeat each T) -> Int) {}
267288

0 commit comments

Comments
 (0)