Skip to content

Commit 1ba38c5

Browse files
committed
[Requirement Machine] When forming requirements from same-element rewrite rules, swap the sides depending on which one is longer once the [element] symbol is dropped.
This change fixes the "out-of-order" type parameters error in `GenericSignature::verify`
1 parent 10a4940 commit 1ba38c5

File tree

3 files changed

+36
-8
lines changed

3 files changed

+36
-8
lines changed

lib/AST/GenericSignature.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -936,12 +936,8 @@ void GenericSignature::verify(ArrayRef<Requirement> reqts) const {
936936
llvm::errs() << "\n";
937937
dumpAndAbort();
938938
}
939-
// FIXME: Same-element rewrite rules are of the form [element].T => U,
940-
// which turns into a same-type requirement repeat U == each T. The
941-
// pack element must always be on the left side of the rule, so type
942-
// parameters can appear out of order in the final same-type requirement.
943-
if (firstType->isParameterPack() == secondType->isParameterPack() &&
944-
compareDependentTypes(firstType, secondType) >= 0) {
939+
940+
if (compareDependentTypes(firstType, secondType) >= 0) {
945941
llvm::errs() << "Out-of-order type parameters: ";
946942
reqt.dump(llvm::errs());
947943
llvm::errs() << "\n";

lib/AST/RequirementMachine/RequirementBuilder.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,18 +236,42 @@ void RequirementBuilder::addRequirementRules(ArrayRef<unsigned> rules) {
236236
llvm_unreachable("Invalid symbol kind");
237237
}
238238

239+
MutableTerm constraintTerm = MutableTerm(rule.getLHS());
240+
MutableTerm subjectTerm = MutableTerm(rule.getRHS());
241+
242+
RewriteContext &ctx = this->System.getRewriteContext();
243+
244+
// Drop the [element] symbol from lhs to determine if we need to swap the
245+
// sides.
246+
if (constraintTerm[0].getKind() == Symbol::Kind::PackElement) {
247+
constraintTerm =
248+
MutableTerm(constraintTerm.begin() + 1, constraintTerm.end());
249+
250+
// Make sure that the shorter term is ordered first.
251+
if (constraintTerm.compare(subjectTerm, ctx) == -1) {
252+
MutableTerm tempTerm = subjectTerm;
253+
subjectTerm = constraintTerm;
254+
constraintTerm = tempTerm;
255+
}
256+
}
257+
239258
ASSERT(rule.getLHS().back().getKind() != Symbol::Kind::Protocol);
240259

241-
MutableTerm constraintTerm(rule.getLHS());
242260
if (constraintTerm.back().getKind() == Symbol::Kind::Shape) {
243261
ASSERT(rule.getRHS().back().getKind() == Symbol::Kind::Shape);
244262
// Strip off the shape symbol from the constraint term.
245263
constraintTerm = MutableTerm(constraintTerm.begin(),
246264
constraintTerm.end() - 1);
247265
}
248266

267+
if (constraintTerm.front().getKind() == Symbol::Kind::PackElement) {
268+
// Strip off the element symbol from the constraint term.
269+
constraintTerm = MutableTerm(constraintTerm.begin() + 1,
270+
constraintTerm.end());
271+
}
272+
249273
auto constraintType = Map.getTypeForTerm(constraintTerm, GenericParams);
250-
Components[rule.getRHS()].Members.push_back(constraintType);
274+
Components[Term::get(subjectTerm, ctx)].Members.push_back(constraintType);
251275
};
252276

253277
if (Debug) {
@@ -314,6 +338,10 @@ void RequirementBuilder::processConnectedComponents() {
314338
subjectTerm = MutableTerm(subjectTerm.begin(), subjectTerm.end() - 1);
315339
} else {
316340
kind = RequirementKind::SameType;
341+
if (subjectTerm.front().getKind() == Symbol::Kind::PackElement) {
342+
// Strip off the element symbol from the subject term.
343+
subjectTerm = MutableTerm(subjectTerm.begin() + 1, subjectTerm.end());
344+
}
317345
}
318346

319347
auto subjectType = Map.getTypeForTerm(subjectTerm, GenericParams);

lib/AST/RequirementMachine/Term.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,10 @@ class MutableTerm final {
171171

172172
std::reverse_iterator<Symbol *> rbegin() { return Symbols.rbegin(); }
173173
std::reverse_iterator<Symbol *> rend() { return Symbols.rend(); }
174+
175+
Symbol front() const {
176+
return Symbols.front();
177+
}
174178

175179
Symbol back() const {
176180
return Symbols.back();

0 commit comments

Comments
 (0)