Skip to content

Commit 736fc8b

Browse files
authored
Merge pull request #64608 from xedin/pack-expansion-param-in-init
[ConstraintSystem] Fix support for a single pack expansion parameter …
2 parents d9c8dca + 24625bb commit 736fc8b

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
@@ -4279,21 +4279,37 @@ ConstraintSystem::matchTypesBindTypeVar(
42794279
return getTypeMatchFailure(locator);
42804280
}
42814281

4282-
// Binding to a pack expansion type is always an error. This indicates
4283-
// that a pack expansion expression was used in a context that doesn't
4284-
// support it.
4282+
// Binding to a pack expansion type is always an error in Swift 6 mode.
4283+
// This indicates that a pack expansion expression was used in a context
4284+
// that doesn't support it.
4285+
//
4286+
// In Swift 5 and earlier initializer references are handled in a special
4287+
// way that uses a type variable to represent a type of the parameter
4288+
// list. Such type variables should be allowed to bind to a pack expansion
4289+
// type to support cases where initializer has a single unlabeled variadic
4290+
// generic parameter - `init(_ data: repeat each T)`.
4291+
//
4292+
// See BindTupleOfFunctionParams constraint for more details.
42854293
if (type->is<PackExpansionType>()) {
4286-
if (!shouldAttemptFixes())
4287-
return getTypeMatchFailure(locator);
4294+
bool representsParameterList =
4295+
typeVar->getImpl()
4296+
.getLocator()
4297+
->isLastElement<LocatorPathElt::ApplyArgument>();
42884298

4289-
auto *fix =
4290-
AllowInvalidPackExpansion::create(*this, getConstraintLocator(locator));
4291-
if (recordFix(fix))
4292-
return getTypeMatchFailure(locator);
4299+
if (!(typeVar->getImpl().canBindToPack() && representsParameterList) ||
4300+
getASTContext().isSwiftVersionAtLeast(6)) {
4301+
if (!shouldAttemptFixes())
4302+
return getTypeMatchFailure(locator);
42934303

4294-
// Don't allow the pack expansion type to propagate to other
4295-
// bindings.
4296-
type = PlaceholderType::get(typeVar->getASTContext(), typeVar);
4304+
auto *fix = AllowInvalidPackExpansion::create(
4305+
*this, getConstraintLocator(locator));
4306+
if (recordFix(fix))
4307+
return getTypeMatchFailure(locator);
4308+
4309+
// Don't allow the pack expansion type to propagate to other
4310+
// bindings.
4311+
type = PlaceholderType::get(typeVar->getASTContext(), typeVar);
4312+
}
42974313
}
42984314

42994315
// We do not allow keypaths to go through AnyObject. Let's create a fix
@@ -7828,7 +7844,8 @@ ConstraintSystem::simplifyConstructionConstraint(
78287844
if (!getASTContext().isSwiftVersionAtLeast(6)) {
78297845
auto paramTypeVar = createTypeVariable(
78307846
getConstraintLocator(locator, ConstraintLocator::ApplyArgument),
7831-
TVO_CanBindToLValue | TVO_CanBindToInOut | TVO_CanBindToNoEscape);
7847+
TVO_CanBindToLValue | TVO_CanBindToInOut | TVO_CanBindToNoEscape |
7848+
TVO_CanBindToPack);
78327849
addConstraint(ConstraintKind::BindTupleOfFunctionParams, memberType,
78337850
paramTypeVar, locator);
78347851
}

test/Constraints/pack-expansion-expressions.swift

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

300+
// Make sure that single parameter initializers are handled correctly because
301+
// the have special type-checking rules in Swift < 6.
302+
func test_init_refs_with_single_pack_expansion_param() {
303+
struct Data<each V> {
304+
init(_: repeat each V) {}
305+
}
306+
307+
_ = Data() // Ok
308+
_ = Data(42) // Ok
309+
_ = Data(42, "") // Ok
310+
311+
struct EmptyAmbiguous<each V> {
312+
init(_: repeat each V) {} // expected-note {{found this candidate}}
313+
init(x: repeat each V) {} // expected-note {{found this candidate}}
314+
}
315+
316+
_ = EmptyAmbiguous() // expected-error {{ambiguous use of 'init'}}
317+
_ = EmptyAmbiguous(x: 42)
318+
_ = EmptyAmbiguous(x: (42, "")) // Ok
319+
}
320+
300321
func test_pack_expansions_with_closures() {
301322
func takesVariadicFunction<each T>(function: (repeat each T) -> Int) {}
302323

0 commit comments

Comments
 (0)