Skip to content

Commit 25d9f37

Browse files
authored
Merge pull request #41631 from slavapestov/rqm-abstract-signatures-on-by-default
RequirementMachine: Enable -requirement-machine-abstract-signatures=verify by default
2 parents 7b810b2 + a0b71e9 commit 25d9f37

File tree

6 files changed

+108
-22
lines changed

6 files changed

+108
-22
lines changed

lib/AST/RequirementMachine/InterfaceType.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,13 @@ getTypeForSymbolRange(const Symbol *begin, const Symbol *end, Type root,
263263
unsigned index = GenericParamKey(genericParam).findIndexIn(genericParams);
264264

265265
if (index == genericParams.size()) {
266-
llvm::errs() << "Invalid generic parameter: " << genericParam << "\n";
267-
llvm::errs() << "Valid generic parameters are";
266+
llvm::errs() << "Cannot build interface type for term "
267+
<< MutableTerm(begin, end) << "\n";
268+
llvm::errs() << "Invalid generic parameter: "
269+
<< Type(genericParam) << "\n";
270+
llvm::errs() << "Valid generic parameters: ";
268271
for (auto *otherParam : genericParams)
269-
llvm::errs() << " " << Type(otherParam);
272+
llvm::errs() << " " << otherParam->getCanonicalType();
270273
llvm::errs() << "\n";
271274
abort();
272275
}

lib/AST/RequirementMachine/KnuthBendix.cpp

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,56 @@ RewriteSystem::computeCriticalPair(ArrayRef<Symbol>::const_iterator from,
212212
return false;
213213
}
214214

215-
// Add the pair (XV, TY).
216-
pairs.emplace_back(xv, ty, path);
215+
// If Y == UW for some W, then the critical pair is (XV, TUW),
216+
// and we have
217+
// - lhs == (TU -> X)
218+
// - rhs == (UV -> UW).
219+
//
220+
// We explicitly apply the rewrite step (TU = X) to the rewrite path,
221+
// transforming the critical pair to (XV, XW).
222+
//
223+
// In particular, if T == X, U == [P] for some protocol P, and
224+
// V == W.[p] for some property symbol p, then we in fact have a pair
225+
// of property rules:
226+
//
227+
// - lhs == (T.[P] => T)
228+
// - rhs == ([P].W.[p] => [P].W)
229+
//
230+
// Without this hack, the critical pair would be:
231+
//
232+
// (T.w.[p] => T.[P].w)
233+
//
234+
// With this hack, the critical pair becomes:
235+
//
236+
// (T.w.[p] => T.w)
237+
//
238+
// This ensures that the newly-added rule is itself a property rule;
239+
// otherwise, this would only be the case if addRule() reduced T.[P].w
240+
// into T.w without immediately reducing some subterm of T first.
241+
//
242+
// While completion will eventually simplify all such rules down into
243+
// property rules, their existance in the first place breaks subtle
244+
// invariants in the minimal conformances algorithm, which expects
245+
// homotopy generators describing redundant protocol conformance rules
246+
// to have a certain structure.
247+
if (lhs.getLHS().size() <= ty.size() &&
248+
std::equal(lhs.getLHS().begin(),
249+
lhs.getLHS().end(),
250+
ty.begin())) {
251+
unsigned endOffset = ty.size() - lhs.getLHS().size();
252+
path.add(RewriteStep::forRewriteRule(/*startOffset=*/0,
253+
endOffset,
254+
getRuleID(lhs),
255+
/*inverse=*/false));
256+
257+
// Compute the term XW.
258+
MutableTerm xw(lhs.getRHS());
259+
xw.append(ty.end() - endOffset, ty.end());
260+
261+
pairs.emplace_back(xv, xw, path);
262+
} else {
263+
pairs.emplace_back(xv, ty, path);
264+
}
217265
}
218266

219267
return true;
@@ -244,12 +292,14 @@ RewriteSystem::computeConfluentCompletion(unsigned maxRuleCount,
244292
// adding new rules in the property map's concrete type unification procedure.
245293
Complete = 1;
246294

247-
bool again = false;
295+
unsigned ruleCount;
248296

249297
std::vector<CriticalPair> resolvedCriticalPairs;
250298
std::vector<RewriteLoop> resolvedLoops;
251299

252300
do {
301+
ruleCount = Rules.size();
302+
253303
// For every rule, looking for other rules that overlap with this rule.
254304
for (unsigned i = 0, e = Rules.size(); i < e; ++i) {
255305
const auto &lhs = getRule(i);
@@ -335,9 +385,10 @@ RewriteSystem::computeConfluentCompletion(unsigned maxRuleCount,
335385
}
336386
}
337387

388+
assert(ruleCount == Rules.size());
389+
338390
simplifyLeftHandSides();
339391

340-
again = false;
341392
for (const auto &pair : resolvedCriticalPairs) {
342393
// Check if we've already done too much work.
343394
if (Rules.size() > maxRuleCount)
@@ -349,8 +400,6 @@ RewriteSystem::computeConfluentCompletion(unsigned maxRuleCount,
349400
// Check if the new rule is too long.
350401
if (Rules.back().getDepth() > maxRuleLength)
351402
return std::make_pair(CompletionResult::MaxRuleLength, Rules.size() - 1);
352-
353-
again = true;
354403
}
355404

356405
for (const auto &loop : resolvedLoops) {
@@ -362,7 +411,7 @@ RewriteSystem::computeConfluentCompletion(unsigned maxRuleCount,
362411

363412
simplifyRightHandSides();
364413
simplifyLeftHandSideSubstitutions(/*map=*/nullptr);
365-
} while (again);
414+
} while (Rules.size() > ruleCount);
366415

367416
return std::make_pair(CompletionResult::Success, 0);
368417
}

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,10 @@ void RewriteSystem::simplifyRightHandSides() {
563563

564564
unsigned newRuleID = Rules.size();
565565

566+
if (Debug.contains(DebugFlags::Add)) {
567+
llvm::dbgs() << "## RHS simplification adds a rule " << lhs << " => " << rhs << "\n\n";
568+
}
569+
566570
// Add a new rule with the simplified right hand side.
567571
Rules.emplace_back(lhs, Term::get(rhs, Context));
568572
auto oldRuleID = Trie.insert(lhs.begin(), lhs.end(), newRuleID);
@@ -655,10 +659,7 @@ void RewriteSystem::verifyRewriteRules(ValidityPolicy policy) const {
655659
ASSERT_RULE(symbol.getKind() != Symbol::Kind::GenericParam);
656660
}
657661

658-
// Completion can produce rules like [P:T].[Q].[R] => [P:T].[Q]
659-
// which are immediately simplified away.
660-
if (!rule.isLHSSimplified() &&
661-
index != 0 && index != lhs.size() - 1) {
662+
if (index != 0 && index != lhs.size() - 1) {
662663
ASSERT_RULE(symbol.getKind() != Symbol::Kind::Protocol);
663664
}
664665
}
@@ -689,9 +690,10 @@ void RewriteSystem::verifyRewriteRules(ValidityPolicy policy) const {
689690
ASSERT_RULE(symbol.getKind() != Symbol::Kind::GenericParam);
690691
}
691692

692-
// Completion can produce rules like [P:T].[Q].[R] => [P:T].[Q]
693+
// Completion can produce rules like [P:T].[Q:R] => [P:T].[Q]
693694
// which are immediately simplified away.
694-
if (!rule.isRHSSimplified() && index != 0) {
695+
if (!rule.isRHSSimplified() &&
696+
index != 0) {
695697
ASSERT_RULE(symbol.getKind() != Symbol::Kind::Protocol);
696698
}
697699
}

lib/Frontend/CompilerInvocation.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,7 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
914914
Args.hasArg(OPT_disable_subst_sil_function_types);
915915

916916
Opts.RequirementMachineProtocolSignatures = RequirementMachineMode::Verify;
917+
Opts.RequirementMachineAbstractSignatures = RequirementMachineMode::Verify;
917918

918919
if (auto A = Args.getLastArg(OPT_requirement_machine_protocol_signatures_EQ)) {
919920
auto value = llvm::StringSwitch<Optional<RequirementMachineMode>>(A->getValue())

stdlib/cmake/modules/SwiftSource.cmake

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -465,12 +465,6 @@ function(_compile_swift_files
465465
endif()
466466
endif()
467467

468-
# The standard library and overlays are built with the Requirement Machine enabled.
469-
if(SWIFTFILE_IS_STDLIB)
470-
list(APPEND swift_flags "-Xfrontend" "-requirement-machine-protocol-signatures=verify")
471-
list(APPEND swift_flags "-Xfrontend" "-requirement-machine-abstract-signatures=verify")
472-
endif()
473-
474468
# The standard library and overlays are built resiliently when SWIFT_STDLIB_STABLE_ABI=On.
475469
if(SWIFTFILE_IS_STDLIB AND SWIFT_STDLIB_STABLE_ABI)
476470
list(APPEND swift_flags "-enable-library-evolution")
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
2+
3+
public protocol P1 {
4+
associatedtype T
5+
}
6+
7+
public protocol P2 : P1 {}
8+
9+
public protocol P3 : P2 {}
10+
11+
public protocol Q1 {}
12+
13+
public protocol Q2 : Q1 {}
14+
15+
public protocol Q3 : Q1 {}
16+
17+
public protocol R {
18+
associatedtype U: Q2, Q3
19+
}
20+
21+
struct G<X: P3, Y: R> where X.T == Y.U {
22+
// CHECK-LABEL: .G.Nested0@
23+
// CHECK-NEXT: <X, Y, Z where X : P3, Y : R, X.[P1]T == Y.[R]U>
24+
struct Nested0<Z> {}
25+
26+
// CHECK-LABEL: .G.Nested1@
27+
// CHECK-NEXT: <X, Y, Z where X : P3, Y : R, X.[P1]T == Y.[R]U>
28+
struct Nested1<Z> where X.T : Q1 {}
29+
30+
// CHECK-LABEL: .G.Nested2@
31+
// CHECK-NEXT: <X, Y, Z where X : P3, Y : R, X.[P1]T == Y.[R]U>
32+
struct Nested2<Z> where X.T : Q2 {}
33+
34+
// CHECK-LABEL: .G.Nested3@
35+
// CHECK-NEXT: <X, Y, Z where X : P3, Y : R, X.[P1]T == Y.[R]U>
36+
struct Nested3<Z> where X.T : Q3 {}
37+
}

0 commit comments

Comments
 (0)