Skip to content

Commit 194c13c

Browse files
authored
Merge pull request #70797 from slavapestov/parameter-pack-open-type-5.10
Sema: Fix openType() handling of parameter packs [5.10]
2 parents 5134c21 + cfb9e5e commit 194c13c

File tree

10 files changed

+205
-80
lines changed

10 files changed

+205
-80
lines changed

lib/AST/ParameterPack.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,8 +453,11 @@ PackType::getExpandedGenericArgs(ArrayRef<GenericTypeParamType *> params,
453453
}
454454

455455
PackType *PackType::getSingletonPackExpansion(Type param) {
456-
assert(param->isParameterPack() || param->is<PackArchetypeType>());
457-
return get(param->getASTContext(), {PackExpansionType::get(param, param)});
456+
SmallVector<Type, 2> rootParameterPacks;
457+
param->getTypeParameterPacks(rootParameterPacks);
458+
assert(rootParameterPacks.size() >= 1);
459+
auto count = rootParameterPacks[0];
460+
return get(param->getASTContext(), {PackExpansionType::get(param, count)});
458461
}
459462

460463
CanPackType CanPackType::getSingletonPackExpansion(CanType param) {

lib/Sema/CSDiagnostics.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,9 @@ class SameShapeExpansionFailure final : public FailureDiagnostic {
449449
public:
450450
SameShapeExpansionFailure(const Solution &solution, Type lhs, Type rhs,
451451
ConstraintLocator *locator)
452-
: FailureDiagnostic(solution, locator), lhs(lhs), rhs(rhs) {}
452+
: FailureDiagnostic(solution, locator),
453+
lhs(resolveType(lhs)),
454+
rhs(resolveType(rhs)) {}
453455

454456
bool diagnoseAsError() override;
455457
};

lib/Sema/CSSimplify.cpp

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1807,7 +1807,14 @@ static ConstraintSystem::TypeMatchResult matchCallArguments(
18071807
}
18081808

18091809
auto *argPack = PackType::get(cs.getASTContext(), argTypes);
1810-
auto *argPackExpansion = PackExpansionType::get(argPack, argPack);
1810+
auto argPackExpansion = [&]() {
1811+
if (argPack->getNumElements() == 1 &&
1812+
argPack->getElementType(0)->is<PackExpansionType>()) {
1813+
return argPack->getElementType(0)->castTo<PackExpansionType>();
1814+
}
1815+
1816+
return PackExpansionType::get(argPack, argPack);
1817+
}();
18111818

18121819
auto firstArgIdx =
18131820
argTypes.empty() ? paramIdx : parameterBindings[paramIdx].front();
@@ -13624,33 +13631,34 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifySameShapeConstraint(
1362413631
auto argLoc =
1362513632
loc->castLastElementTo<LocatorPathElt::ApplyArgToParam>();
1362613633

13627-
if (type1->getAs<PackArchetypeType>() &&
13628-
type2->getAs<PackArchetypeType>())
13634+
if (type1->is<PackArchetypeType>() &&
13635+
type2->is<PackArchetypeType>())
1362913636
return recordShapeMismatchFix();
1363013637

13631-
auto argPack = type1->getAs<PackType>();
13632-
auto paramPack = type2->getAs<PackType>();
13633-
13634-
if (!(argPack && paramPack))
13635-
return SolutionKind::Error;
13638+
auto numArgs = (shape1->is<PackType>()
13639+
? shape1->castTo<PackType>()->getNumElements()
13640+
: 1);
13641+
auto numParams = (shape2->is<PackType>()
13642+
? shape2->castTo<PackType>()->getNumElements()
13643+
: 1);
1363613644

1363713645
// Tailed diagnostic to explode tuples.
1363813646
// FIXME: This is very similar to
1363913647
// 'cannot_convert_single_tuple_into_multiple_arguments'; can we emit
1364013648
// both of these in the same place?
13641-
if (argPack->getNumElements() == 1) {
13642-
if (argPack->getElementType(0)->is<TupleType>() &&
13643-
paramPack->getNumElements() >= 1) {
13649+
if (numArgs == 1) {
13650+
if (type1->is<TupleType>() &&
13651+
numParams >= 1) {
1364413652
return recordShapeFix(
1364513653
DestructureTupleToMatchPackExpansionParameter::create(
13646-
*this, paramPack, loc),
13647-
/*impact=*/2 * paramPack->getNumElements());
13654+
*this,
13655+
(type2->is<PackType>()
13656+
? type2->castTo<PackType>()
13657+
: PackType::getSingletonPackExpansion(type2)), loc),
13658+
/*impact=*/2 * numParams);
1364813659
}
1364913660
}
1365013661

13651-
auto numArgs = shape1->castTo<PackType>()->getNumElements();
13652-
auto numParams = shape2->castTo<PackType>()->getNumElements();
13653-
1365413662
// Drops `ApplyArgToParam` and left with `ApplyArgument`.
1365513663
path.pop_back();
1365613664

lib/Sema/ConstraintSystem.cpp

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -855,25 +855,7 @@ Type ConstraintSystem::openUnboundGenericType(GenericTypeDecl *decl,
855855
result = DC->mapTypeIntoContext(result);
856856
}
857857

858-
return result.transform([&](Type type) -> Type {
859-
// Although generic parameters are declared with just `each`
860-
// their interface types introduce a pack expansion which
861-
// means that the solver has to extact generic argument type
862-
// variable from Pack{repeat ...} and drop that structure to
863-
// make sure that generic argument gets inferred to a pack type.
864-
if (auto *packTy = type->getAs<PackType>()) {
865-
assert(packTy->getNumElements() == 1);
866-
auto *expansion = packTy->getElementType(0)->castTo<PackExpansionType>();
867-
auto *typeVar = expansion->getPatternType()->castTo<TypeVariableType>();
868-
assert(typeVar->getImpl().getGenericParameter() &&
869-
typeVar->getImpl().canBindToPack());
870-
return typeVar;
871-
}
872-
873-
if (auto *expansion = dyn_cast<PackExpansionType>(type.getPointer()))
874-
return openPackExpansionType(expansion, replacements, locator);
875-
return type;
876-
});
858+
return result;
877859
}
878860

879861
static void checkNestedTypeConstraints(ConstraintSystem &cs, Type type,
@@ -1022,18 +1004,6 @@ Type ConstraintSystem::openType(Type type, OpenedTypeMap &replacements,
10221004
}
10231005
}
10241006

1025-
// While opening variadic generic types that appear in other types
1026-
// we need to extract generic parameter from Pack{repeat ...} structure
1027-
// that gets introduced by the interface type, see
1028-
// \c openUnboundGenericType for more details.
1029-
if (auto *packTy = type->getAs<PackType>()) {
1030-
if (auto expansionTy = packTy->unwrapSingletonPackExpansion()) {
1031-
auto patternTy = expansionTy->getPatternType();
1032-
if (patternTy->isTypeParameter())
1033-
return openType(patternTy, replacements, locator);
1034-
}
1035-
}
1036-
10371007
if (auto *expansion = type->getAs<PackExpansionType>()) {
10381008
return openPackExpansionType(expansion, replacements, locator);
10391009
}
@@ -3927,6 +3897,14 @@ struct TypeSimplifier {
39273897
auto countType = expansion->getCountType().transform(
39283898
TypeSimplifier(CS, GetFixedTypeFn));
39293899

3900+
if (!countType->is<PackType>() &&
3901+
!countType->is<PackArchetypeType>()) {
3902+
SmallVector<Type, 2> rootParameterPacks;
3903+
countType->getTypeParameterPacks(rootParameterPacks);
3904+
if (!rootParameterPacks.empty())
3905+
countType = rootParameterPacks[0];
3906+
}
3907+
39303908
// If both pattern and count are resolves, let's just return
39313909
// the pattern type for `transformWithPosition` to take care
39323910
// of the rest.

test/Constraints/issue-67906.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking
2+
3+
struct G<each T>: Sequence {
4+
typealias Element = Int
5+
typealias Iterator = [Int].Iterator
6+
7+
consuming func makeIterator() -> Iterator {
8+
fatalError()
9+
}
10+
}
11+
12+
// expected-note@+1 {{in call to function 'foo'}}
13+
func foo<each T>(_: repeat each T) -> G<repeat each T> {
14+
.init()
15+
}
16+
17+
// expected-error@+2 {{for-in loop requires '(repeat each T) -> G<repeat each T>' to conform to 'Sequence'}}
18+
// expected-error@+1 {{generic parameter 'each T' could not be inferred}}
19+
for a in foo {
20+
print(a)
21+
}
22+
23+
for a in foo() {
24+
print(a)
25+
}

test/Constraints/pack-expansion-expressions.swift

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ func tupleExpansion<each T, each U>(
139139
_ = zip(repeat each tuple1, with: repeat each tuple1.element) // legacy syntax
140140

141141
_ = zip(repeat each tuple1, with: repeat each tuple2)
142-
// expected-error@-1 {{global function 'zip(_:with:)' requires the type packs 'repeat each T' and 'repeat each U' have the same shape}}
142+
// expected-error@-1 {{global function 'zip(_:with:)' requires the type packs 'each T' and 'each U' have the same shape}}
143+
// expected-error@-2 {{pack expansion requires that 'each U' and 'each T' have the same shape}}
143144

144145
_ = forward(repeat each tuple3)
145146
}
@@ -349,37 +350,36 @@ func test_pack_expansions_with_closures() {
349350
func test_pack_expansion_specialization(tuple: (Int, String, Float)) {
350351
struct Data<each T> {
351352
init(_: repeat each T) {} // expected-note 4 {{'init(_:)' declared here}}
352-
init(vals: repeat each T) {} // expected-note {{'init(vals:)' declared here}}
353-
init<each U>(x: Int, _: repeat each T, y: repeat each U) {} // expected-note 3 {{'init(x:_:y:)' declared here}}
353+
init(vals: repeat each T) {}
354+
init<each U>(x: Int, _: repeat each T, y: repeat each U) {}
354355
}
355356

356357
_ = Data<Int>() // expected-error {{missing argument for parameter #1 in call}}
357358
_ = Data<Int>(0) // Ok
358359
_ = Data<Int, String>(42, "") // Ok
359-
_ = Data<Int>(42, "") // expected-error {{extra argument in call}}
360+
_ = Data<Int>(42, "") // expected-error {{pack expansion requires that 'Int' and 'Int, String' have the same shape}}
360361
_ = Data<Int, String>((42, ""))
361-
// expected-error@-1 {{value pack expansion at parameter #0 expects 2 separate arguments; remove extra parentheses to change tuple into separate arguments}} {{25-26=}} {{32-33=}}
362+
// expected-error@-1 {{initializer expects 2 separate arguments; remove extra parentheses to change tuple into separate arguments}} {{25-26=}} {{32-33=}}
362363
_ = Data<Int, String, Float>(vals: (42, "", 0))
363-
// expected-error@-1 {{value pack expansion at parameter #0 expects 3 separate arguments; remove extra parentheses to change tuple into separate arguments}} {{38-39=}} {{48-49=}}
364+
// expected-error@-1 {{pack expansion requires that 'Int, String, Float' and '(Int, String, Int)' have the same shape}}
364365
_ = Data<Int, String, Float>((vals: 42, "", 0))
365-
// expected-error@-1 {{value pack expansion at parameter #0 expects 3 separate arguments; remove extra parentheses to change tuple into separate arguments}} {{32-33=}} {{48-49=}}
366+
// expected-error@-1 {{initializer expects 3 separate arguments; remove extra parentheses to change tuple into separate arguments}} {{32-33=}} {{48-49=}}
366367
_ = Data<Int, String, Float>(tuple)
367-
// expected-error@-1 {{value pack expansion at parameter #0 expects 3 separate arguments}}
368+
// expected-error@-1 {{initializer expects 3 separate arguments}}
368369
_ = Data<Int, String, Float>(x: 42, tuple)
369-
// expected-error@-1 {{value pack expansion at parameter #1 expects 3 separate arguments}}
370+
// expected-error@-1 {{pack expansion requires that 'Int, String, Float' and '(Int, String, Float)' have the same shape}}
370371
_ = Data<Int, String, Float>(x: 42, tuple, y: 1, 2, 3)
371-
// expected-error@-1 {{value pack expansion at parameter #1 expects 3 separate arguments}}
372+
// expected-error@-1 {{pack expansion requires that 'Int, String, Float' and '(Int, String, Float)' have the same shape}}
372373
_ = Data<Int, String, Float>(x: 42, (42, "", 0), y: 1, 2, 3)
373-
// expected-error@-1 {{value pack expansion at parameter #1 expects 3 separate arguments}} {{39-40=}} {{49-50=}}
374+
// expected-error@-1 {{pack expansion requires that 'Int, String, Float' and '(Int, String, Int)' have the same shape}}
374375

375376
struct Ambiguity<each T> {
376377
func test(_: repeat each T) -> Int { 42 }
377-
// expected-note@-1 {{value pack expansion at parameter #0 expects 3 separate arguments}}
378+
// expected-note@-1 {{'test' declared here}}
378379
func test(_: repeat each T) -> String { "" }
379-
// expected-note@-1 {{value pack expansion at parameter #0 expects 3 separate arguments}}
380380
}
381381

382-
_ = Ambiguity<Int, String, Float>().test(tuple) // expected-error {{no exact matches in call to instance method 'test'}}
382+
_ = Ambiguity<Int, String, Float>().test(tuple) // expected-error {{instance method 'test' expects 3 separate arguments}}
383383
}
384384

385385
// rdar://107280056 - "Ambiguous without more context" with opaque return type + variadics
@@ -621,44 +621,40 @@ do {
621621
// https://github.com/apple/swift/issues/66393
622622
do {
623623
struct S<each T> {
624-
var property: (repeat each T) -> Void { // expected-note 4 {{'property' declared here}}
624+
var property: (repeat each T) -> Void {
625625
get {}
626626
}
627627

628-
func method(_: repeat each T) {} // expected-note 4 {{'method' declared here}}
628+
func method(_: repeat each T) {}
629629
}
630630
S<Int, Bool>().method((5, true))
631-
// expected-error@-1 {{value pack expansion at parameter #0 expects 2 separate arguments; remove extra parentheses to change tuple into separate arguments}}
631+
// expected-error@-1 {{pack expansion requires that 'Int, Bool' and '(Int, Bool)' have the same shape}}
632632

633633
S<Int, Bool>().method((5, true, 6))
634-
// expected-error@-1 {{value pack expansion at parameter #0 expects 2 separate arguments; remove extra parentheses to change tuple into separate arguments}}
634+
// expected-error@-1 {{pack expansion requires that 'Int, Bool' and '(Int, Bool, Int)' have the same shape}}
635635

636636
S<Int, Bool>().property((5, true))
637-
// expected-error@-1 {{value pack expansion at parameter #0 expects 2 separate arguments; remove extra parentheses to change tuple into separate arguments}}
637+
// expected-error@-1 {{cannot pass value pack expansion to non-pack parameter of type 'repeat each T'}}
638638

639639
S<Int, Bool>().property((5, true, 6))
640-
// expected-error@-1 {{value pack expansion at parameter #0 expects 2 separate arguments; remove extra parentheses to change tuple into separate arguments}}
640+
// expected-error@-1 {{cannot pass value pack expansion to non-pack parameter of type 'repeat each T'}}
641641

642642
func foo<each U>(u: repeat each U) {
643643
S<repeat each U>().property((3, 4, 5))
644-
// expected-error@-1 {{value pack expansion at parameter #0 expects 1 separate arguments; remove extra parentheses to change tuple into separate arguments}}
644+
// expected-error@-1 {{cannot pass value pack expansion to non-pack parameter of type 'repeat each T'}}
645645

646646
// FIXME: The count of 'repeat each U' is not statically known, but error suggests that it is 1.
647647
S<repeat each U>().method((3, 4, 5))
648-
// expected-error@-1 {{value pack expansion at parameter #0 expects 1 separate arguments; remove extra parentheses to change tuple into separate arguments}}
649-
// FIXME: Bad diagnostics
650-
// expected-error@-3 {{pack expansion requires that 'each U' and '_' have the same shape}}
651-
// expected-error@-4 {{pack expansion requires that 'each U' and '_.RawValue' have the same shape}}
648+
// expected-error@-1 {{pack expansion requires that 'each U' and '(Int, Int, Int)' have the same shape}}
652649

653650
// FIXME: The count of '(Int, Int), repeat each U' is not statically known, but error suggests that it is 2.
654651
S<(Int, Int), repeat each U>().method((3, 4))
655-
// expected-error@-1 {{value pack expansion at parameter #0 expects 2 separate arguments; remove extra parentheses to change tuple into separate arguments}}
656-
// FIXME: Duplicate diagnostics
657-
// expected-error@-3 2 {{pack expansion requires that 'each U' and '' have the same shape}}
652+
// expected-error@-1 {{pack expansion requires that '(Int, Int), repeat each U' and '(Int, Int)' have the same shape}}
653+
// expected-error@-2 {{pack expansion requires that '' and 'each U' have the same shape}}
658654

659655
// FIXME: The count of '(Int, Int), repeat each U' is not statically known, but error suggests that it is 2.
660656
S<(Int, Int), repeat each U>().property((3, 4))
661-
// expected-error@-1 {{value pack expansion at parameter #0 expects 2 separate arguments; remove extra parentheses to change tuple into separate arguments}}
657+
// expected-error@-1 {{cannot pass value pack expansion to non-pack parameter of type 'repeat each T'}}
662658
}
663659
}
664660

test/Constraints/variadic_generic_constraints.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,6 @@ func goodCallToZip<each T, each U>(t: repeat each T, u: repeat each U) where (re
7373

7474
func badCallToZip<each T, each U>(t: repeat each T, u: repeat each U) {
7575
_ = zip(t: repeat each t, u: repeat each u)
76-
// expected-error@-1 {{global function 'zip(t:u:)' requires the type packs 'repeat each T' and 'repeat each U' have the same shape}}
76+
// expected-error@-1 {{global function 'zip(t:u:)' requires the type packs 'each T' and 'each U' have the same shape}}
77+
// expected-error@-2 {{pack expansion requires that 'each U' and 'each T' have the same shape}}
7778
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking
2+
3+
// These test cases exercise variants of rdar://problem/112785081
4+
// and https://github.com/apple/swift/issues/68160.
5+
6+
protocol P {}
7+
8+
protocol Q {
9+
associatedtype A: Q
10+
11+
var a: A { get }
12+
}
13+
14+
struct S1<each T: Q>: P {
15+
init(_: repeat each T) {}
16+
}
17+
18+
func foo1a<each T: Q>(_ t: repeat each T) -> some P {
19+
return S1(repeat each t)
20+
}
21+
22+
func foo2a<each T: Q>(_ t: repeat each T) -> S1<repeat each T> {
23+
return S1(repeat each t)
24+
}
25+
26+
func foo3a<each T: Q>(_ t: repeat each T) -> some P {
27+
return S1(repeat (each t).a)
28+
}
29+
30+
func foo4a<each T: Q>(_ t: repeat each T) -> S1<repeat (each T).A> {
31+
return S1(repeat (each t).a)
32+
}
33+
34+
func foo1b<each T: Q>(_ t: repeat each T) -> some P {
35+
return S1.init(repeat each t)
36+
}
37+
38+
func foo2b<each T: Q>(_ t: repeat each T) -> S1<repeat each T> {
39+
return S1.init(repeat each t)
40+
}
41+
42+
func foo3b<each T: Q>(_ t: repeat each T) -> some P {
43+
return S1.init(repeat (each t).a)
44+
}
45+
46+
func foo4b<each T: Q>(_ t: repeat each T) -> S1<repeat (each T).A> {
47+
return S1.init(repeat (each t).a)
48+
}
49+
50+
struct S2<each T: Q>: P {
51+
init(arg: (repeat each T)) {}
52+
}
53+
54+
func bar1a<each T: Q>(_ t: repeat each T) -> some P {
55+
return S2(arg: (repeat each t))
56+
}
57+
58+
func bar2a<each T: Q>(_ t: repeat each T) -> S2<repeat each T> {
59+
return S2(arg: (repeat each t))
60+
}
61+
62+
func bar3a<each T: Q>(_ t: repeat each T) -> some P {
63+
return S2(arg: (repeat (each t).a))
64+
}
65+
66+
func bar4a<each T: Q>(_ t: repeat each T) -> S2<repeat (each T).A> {
67+
return S2(arg: (repeat (each t).a))
68+
}
69+
70+
func bar1b<each T: Q>(_ t: repeat each T) -> some P {
71+
return S2.init(arg: (repeat each t))
72+
}
73+
74+
func bar2b<each T: Q>(_ t: repeat each T) -> S2<repeat each T> {
75+
return S2.init(arg: (repeat each t))
76+
}
77+
78+
func bar3b<each T: Q>(_ t: repeat each T) -> some P {
79+
return S2.init(arg: (repeat (each t).a))
80+
}
81+
82+
func bar4b<each T: Q>(_ t: repeat each T) -> S2<repeat (each T).A> {
83+
return S2.init(arg: (repeat (each t).a))
84+
}

0 commit comments

Comments
 (0)