Skip to content

Commit 60f8000

Browse files
committed
[RequirementMachine] Generalize connected components to process same
shape requirements.
1 parent f4bfce6 commit 60f8000

File tree

2 files changed

+62
-27
lines changed

2 files changed

+62
-27
lines changed

lib/AST/RequirementMachine/RequirementBuilder.cpp

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ struct ConnectedComponent {
4343
Type ConcreteType;
4444

4545
void buildRequirements(Type subjectType,
46+
RequirementKind kind,
4647
std::vector<Requirement> &reqs,
4748
std::vector<ProtocolTypeAlias> &aliases);
4849
};
@@ -68,6 +69,7 @@ struct ConnectedComponent {
6869
///
6970
/// A == X, B == X, C == X, D == X
7071
void ConnectedComponent::buildRequirements(Type subjectType,
72+
RequirementKind kind,
7173
std::vector<Requirement> &reqs,
7274
std::vector<ProtocolTypeAlias> &aliases) {
7375
std::sort(Members.begin(), Members.end(),
@@ -81,12 +83,14 @@ void ConnectedComponent::buildRequirements(Type subjectType,
8183
}
8284

8385
for (auto constraintType : Members) {
84-
reqs.emplace_back(RequirementKind::SameType,
85-
subjectType, constraintType);
86+
reqs.emplace_back(kind, subjectType, constraintType);
8687
subjectType = constraintType;
8788
}
8889

8990
} else {
91+
// Shape requirements cannot be concrete.
92+
assert(kind == RequirementKind::SameType);
93+
9094
// If there are multiple protocol typealiases in the connected component,
9195
// lower them all to a series of identical concrete-type aliases.
9296
for (auto name : Aliases) {
@@ -135,7 +139,7 @@ class RequirementBuilder {
135139

136140
// Temporary state populated by addRequirementRules() and
137141
// addTypeAliasRules().
138-
llvm::SmallDenseMap<TypeBase *, ConnectedComponent> Components;
142+
llvm::SmallDenseMap<Term, ConnectedComponent> Components;
139143

140144
public:
141145
// Results.
@@ -229,7 +233,7 @@ void RequirementBuilder::addRequirementRules(ArrayRef<unsigned> rules) {
229233
if (ReconstituteSugar)
230234
concreteType = concreteType->reconstituteSugar(/*recursive=*/true);
231235

232-
auto &component = Components[subjectType.getPointer()];
236+
auto &component = Components[rule.getRHS()];
233237
assert(!component.ConcreteType);
234238
component.ConcreteType = concreteType;
235239
return;
@@ -250,28 +254,18 @@ void RequirementBuilder::addRequirementRules(ArrayRef<unsigned> rules) {
250254
llvm_unreachable("Invalid symbol kind");
251255
}
252256

253-
if (rule.getLHS().back().getKind() == Symbol::Kind::Shape) {
254-
assert(rule.getRHS().back().getKind() == Symbol::Kind::Shape);
257+
assert(rule.getLHS().back().getKind() != Symbol::Kind::Protocol);
255258

256-
// Strip off the shape symbols from either side of the rule.
257-
MutableTerm lhsTerm(rule.getLHS().begin(),
258-
rule.getLHS().end() - 1);
259-
MutableTerm rhsTerm(rule.getRHS().begin(),
260-
rule.getRHS().end() - 1);
261-
262-
// Add a SameCount requirement between the two parameter packs.
263-
auto constraintType = Map.getTypeForTerm(lhsTerm, GenericParams);
264-
auto subjectType = Map.getTypeForTerm(rhsTerm, GenericParams);
265-
Reqs.emplace_back(RequirementKind::SameCount,
266-
subjectType, constraintType);
267-
return;
259+
MutableTerm constraintTerm(rule.getLHS());
260+
if (constraintTerm.back().getKind() == Symbol::Kind::Shape) {
261+
assert(rule.getRHS().back().getKind() == Symbol::Kind::Shape);
262+
// Strip off the shape symbol from the constraint term.
263+
constraintTerm = MutableTerm(constraintTerm.begin(),
264+
constraintTerm.end() - 1);
268265
}
269266

270-
assert(rule.getLHS().back().getKind() != Symbol::Kind::Protocol);
271-
auto constraintType = Map.getTypeForTerm(rule.getLHS(), GenericParams);
272-
auto subjectType = Map.getTypeForTerm(rule.getRHS(), GenericParams);
273-
274-
Components[subjectType.getPointer()].Members.push_back(constraintType);
267+
auto constraintType = Map.getTypeForTerm(constraintTerm, GenericParams);
268+
Components[rule.getRHS()].Members.push_back(constraintType);
275269
};
276270

277271
if (Debug) {
@@ -319,11 +313,11 @@ void RequirementBuilder::addTypeAliasRules(ArrayRef<unsigned> rules) {
319313
if (ReconstituteSugar)
320314
concreteType = concreteType->reconstituteSugar(/*recursive=*/true);
321315

322-
auto &component = Components[subjectType.getPointer()];
316+
auto &component = Components[rule.getRHS()];
323317
assert(!component.ConcreteType);
324-
Components[subjectType.getPointer()].ConcreteType = concreteType;
318+
Components[rule.getRHS()].ConcreteType = concreteType;
325319
} else {
326-
Components[subjectType.getPointer()].Aliases.push_back(name);
320+
Components[rule.getRHS()].Aliases.push_back(name);
327321
}
328322
}
329323
}
@@ -332,7 +326,18 @@ void RequirementBuilder::processConnectedComponents() {
332326
// Now, convert each connected component into a series of same-type
333327
// requirements.
334328
for (auto &pair : Components) {
335-
pair.second.buildRequirements(pair.first, Reqs, Aliases);
329+
MutableTerm subjectTerm(pair.first);
330+
RequirementKind kind;
331+
if (subjectTerm.back().getKind() == Symbol::Kind::Shape) {
332+
kind = RequirementKind::SameCount;
333+
// Strip off the shape symbol from the subject term.
334+
subjectTerm = MutableTerm{subjectTerm.begin(), subjectTerm.end() - 1};
335+
} else {
336+
kind = RequirementKind::SameType;
337+
}
338+
339+
auto subjectType = Map.getTypeForTerm(subjectTerm, GenericParams);
340+
pair.second.buildRequirements(subjectType, kind, Reqs, Aliases);
336341
}
337342
}
338343

test/Generics/pack-shape-requirements.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,33 @@ func inferSameShape<@_typeSequence T, @_typeSequence U>(ts t: T..., us u: U...)
1313
// CHECK-NEXT: Generic signature: <@_typeSequence T, @_typeSequence U where T : P, T.count == U.count, U : P>
1414
func desugarSameShape<@_typeSequence T, @_typeSequence U>(ts t: T..., us u: U...) where T: P, U: P, ((T.A, U.A)...): Any {
1515
}
16+
17+
// CHECK-LABEL: multipleSameShape1(ts:us:vs:)
18+
// CHECK-NEXT: Generic signature: <@_typeSequence T, @_typeSequence U, @_typeSequence V where T.count == U.count, U.count == V.count>
19+
func multipleSameShape1<@_typeSequence T, @_typeSequence U, @_typeSequence V>(ts t: T..., us u: U..., vs v: V...) where ((T, U, V)...): Any {
20+
}
21+
22+
// CHECK-LABEL: multipleSameShape2(ts:us:vs:)
23+
// CHECK-NEXT: Generic signature: <@_typeSequence T, @_typeSequence U, @_typeSequence V where T.count == U.count, U.count == V.count>
24+
func multipleSameShape2<@_typeSequence T, @_typeSequence U, @_typeSequence V>(ts t: T..., us u: U..., vs v: V...) where ((V, T, U)...): Any {
25+
}
26+
27+
// CHECK-LABEL: multipleSameShape3(ts:us:vs:)
28+
// CHECK-NEXT: Generic signature: <@_typeSequence T, @_typeSequence U, @_typeSequence V where T.count == U.count, U.count == V.count>
29+
func multipleSameShape3<@_typeSequence T, @_typeSequence U, @_typeSequence V>(ts t: T..., us u: U..., vs v: V...) where ((U, V, T)...): Any {
30+
}
31+
32+
// CHECK-LABEL: multipleSameShape4(ts:us:vs:)
33+
// CHECK-NEXT: Generic signature: <@_typeSequence T, @_typeSequence U, @_typeSequence V where T.count == U.count, U.count == V.count>
34+
func multipleSameShape4<@_typeSequence T, @_typeSequence U, @_typeSequence V>(ts t: T..., us u: U..., vs v: V...) where ((U, T, V)...): Any {
35+
}
36+
37+
// CHECK-LABEL: multipleSameShape5(ts:us:vs:)
38+
// CHECK-NEXT: Generic signature: <@_typeSequence T, @_typeSequence U, @_typeSequence V where T.count == U.count, U.count == V.count>
39+
func multipleSameShape5<@_typeSequence T, @_typeSequence U, @_typeSequence V>(ts t: T..., us u: U..., vs v: V...) where ((T, V, U)...): Any {
40+
}
41+
42+
// CHECK-LABEL: multipleSameShape6(ts:us:vs:)
43+
// CHECK-NEXT: Generic signature: <@_typeSequence T, @_typeSequence U, @_typeSequence V where T.count == U.count, U.count == V.count>
44+
func multipleSameShape6<@_typeSequence T, @_typeSequence U, @_typeSequence V>(ts t: T..., us u: U..., vs v: V...) where ((V, U, T)...): Any {
45+
}

0 commit comments

Comments
 (0)