Skip to content

Commit b028b44

Browse files
committed
Sema: Clean up openType() and openUnboundGenericType()
Fixes: - rdar://112785081 - swiftlang#67906 - swiftlang#68160
1 parent f972ad8 commit b028b44

File tree

7 files changed

+159
-34
lines changed

7 files changed

+159
-34
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/CSSimplify.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1810,7 +1810,14 @@ static ConstraintSystem::TypeMatchResult matchCallArguments(
18101810
}
18111811

18121812
auto *argPack = PackType::get(cs.getASTContext(), argTypes);
1813-
auto *argPackExpansion = PackExpansionType::get(argPack, argPack);
1813+
auto argPackExpansion = [&]() {
1814+
if (argPack->getNumElements() == 1 &&
1815+
argPack->getElementType(0)->is<PackExpansionType>()) {
1816+
return argPack->getElementType(0)->castTo<PackExpansionType>();
1817+
}
1818+
1819+
return PackExpansionType::get(argPack, argPack);
1820+
}();
18141821

18151822
auto firstArgIdx =
18161823
argTypes.empty() ? paramIdx : parameterBindings[paramIdx].front();

lib/Sema/ConstraintSystem.cpp

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

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

881863
static void checkNestedTypeConstraints(ConstraintSystem &cs, Type type,
@@ -1024,18 +1006,6 @@ Type ConstraintSystem::openType(Type type, OpenedTypeMap &replacements,
10241006
}
10251007
}
10261008

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

3960+
if (!countType->is<PackType>() &&
3961+
!countType->is<PackArchetypeType>()) {
3962+
SmallVector<Type, 2> rootParameterPacks;
3963+
countType->getTypeParameterPacks(rootParameterPacks);
3964+
if (!rootParameterPacks.empty())
3965+
countType = rootParameterPacks[0];
3966+
}
3967+
39903968
// If both pattern and count are resolves, let's just return
39913969
// the pattern type for `transformWithPosition` to take care
39923970
// 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
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+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// RUN: %target-typecheck-verify-swift
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+
}

test/Constraints/variadic_generic_types.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ do {
5656
return Test<String, Int, repeat each T>("a", 42, repeat each v) // Ok
5757
}
5858
}
59+
5960
// rdar://107479662 - variadic tuple of Sendable elements does not conform to Sendable
6061
do {
6162
struct Test<each T> : Sendable {
@@ -65,3 +66,14 @@ do {
6566
struct TestProperty<T> : Sendable {
6667
}
6768
}
69+
70+
// https://github.com/apple/swift/issues/68160
71+
do {
72+
struct G<each T, U> {
73+
let f: (repeat Optional<each T>) -> U
74+
75+
init(f: @escaping (repeat Optional<each T>) -> U) {
76+
self.f = f
77+
}
78+
}
79+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %target-swift-frontend -emit-ir %s -disable-availability-checking
2+
3+
protocol SomeObjectProtocol {}
4+
5+
struct SomeObject: SomeObjectProtocol {}
6+
7+
protocol ObjectProviding {
8+
associatedtype Object: SomeObjectProtocol
9+
var object: Object { get }
10+
}
11+
12+
struct ConformingObject<each B>: ObjectProviding {
13+
var object: some SomeObjectProtocol {
14+
SomeObject()
15+
}
16+
}

0 commit comments

Comments
 (0)