Skip to content

Commit eb67b1f

Browse files
committed
Sema: Clean up openType() and openUnboundGenericType()
Fixes: - rdar://112785081 - #67906 - #68160
1 parent 94c295e commit eb67b1f

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
@@ -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();

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+
}
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+
}

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)