1010//
1111// ===----------------------------------------------------------------------===//
1212//
13- // This file implements the main entry points into the requirement machine
14- // via the request evaluator.
13+ // This file implements the main entry points for computing minimized generic
14+ // signatures using the requirement machine via the request evaluator.
15+ //
16+ // The actual logic for finding a minimal set of rewrite rules is implemented in
17+ // HomotopyReduction.cpp and GeneratingConformances.cpp.
1518//
1619// ===----------------------------------------------------------------------===//
1720
18- #include " RequirementMachine.h"
1921#include " swift/AST/ASTContext.h"
2022#include " swift/AST/Decl.h"
23+ #include " swift/AST/GenericSignature.h"
2124#include " swift/AST/GenericSignatureBuilder.h"
2225#include " swift/AST/LazyResolver.h"
26+ #include " swift/AST/Requirement.h"
2327#include " swift/AST/TypeCheckRequests.h"
2428#include " swift/Basic/Statistic.h"
29+ #include < vector>
30+
31+ #include " RequirementMachine.h"
2532
2633using namespace swift ;
2734using namespace rewriting ;
@@ -33,6 +40,111 @@ STATISTIC(NumLazyRequirementSignaturesLoaded,
3340
3441#undef DEBUG_TYPE
3542
43+ // / Convert a list of non-permanent, non-redundant rewrite rules into a minimal
44+ // / protocol requirement signature for \p proto. The requirements are sorted in
45+ // / canonical order, and same-type requirements are canonicalized.
46+ std::vector<Requirement>
47+ RequirementMachine::buildRequirementSignature (ArrayRef<unsigned > rules,
48+ const ProtocolDecl *proto) const {
49+ std::vector<Requirement> reqs;
50+ llvm::SmallDenseMap<TypeBase *, llvm::SmallVector<Type, 2 >> sameTypeReqs;
51+
52+ auto genericParams = proto->getGenericSignature ().getGenericParams ();
53+
54+ // Convert a rewrite rule into a requirement.
55+ auto createRequirementFromRule = [&](const Rule &rule) {
56+ if (auto prop = rule.isPropertyRule ()) {
57+ auto subjectType = Context.getTypeForTerm (rule.getRHS (), genericParams,
58+ System.getProtocols ());
59+
60+ switch (prop->getKind ()) {
61+ case Symbol::Kind::Protocol:
62+ reqs.emplace_back (RequirementKind::Conformance,
63+ subjectType,
64+ prop->getProtocol ()->getDeclaredInterfaceType ());
65+ return ;
66+
67+ case Symbol::Kind::Layout:
68+ case Symbol::Kind::ConcreteType:
69+ case Symbol::Kind::Superclass:
70+ // FIXME
71+ return ;
72+
73+ case Symbol::Kind::Name:
74+ case Symbol::Kind::AssociatedType:
75+ case Symbol::Kind::GenericParam:
76+ break ;
77+ }
78+
79+ llvm_unreachable (" Invalid symbol kind" );
80+ } else if (rule.getLHS ().back ().getKind () != Symbol::Kind::Protocol) {
81+ auto constraintType = Context.getTypeForTerm (rule.getLHS (), genericParams,
82+ System.getProtocols ());
83+ auto subjectType = Context.getTypeForTerm (rule.getRHS (), genericParams,
84+ System.getProtocols ());
85+
86+ sameTypeReqs[subjectType.getPointer ()].push_back (constraintType);
87+ }
88+ };
89+
90+ // Build the list of requirements, storing same-type requirements off
91+ // to the side.
92+ for (unsigned ruleID : rules) {
93+ const auto &rule = System.getRule (ruleID);
94+ createRequirementFromRule (rule);
95+ }
96+
97+ // A set of rewrite rules of the form:
98+ //
99+ // B => A
100+ // C => A
101+ // D => A
102+ //
103+ // Become a series of same-type requirements
104+ //
105+ // A == B, B == C, C == D
106+ //
107+ for (auto &pair : sameTypeReqs) {
108+ std::sort (pair.second .begin (), pair.second .end (),
109+ [](Type first, Type second) -> bool {
110+ return compareDependentTypes (first, second) < 0 ;
111+ });
112+
113+ Type subjectType (pair.first );
114+ for (auto constraintType : pair.second ) {
115+ reqs.emplace_back (RequirementKind::SameType, subjectType, constraintType);
116+ subjectType = constraintType;
117+ }
118+ }
119+
120+ // Sort the requirements in canonical order.
121+ std::sort (reqs.begin (), reqs.end (),
122+ [](const Requirement &lhs, const Requirement &rhs) -> bool {
123+ return lhs.compare (rhs) < 0 ;
124+ });
125+
126+ return reqs;
127+ }
128+
129+ // / Builds the requirement signatures for each protocol in this strongly
130+ // / connected component.
131+ llvm::DenseMap<const ProtocolDecl *, std::vector<Requirement>>
132+ RequirementMachine::computeMinimalRequirements () {
133+ assert (Protos.size () > 0 );
134+ System.minimizeRewriteSystem ();
135+
136+ auto rules = System.getMinimizedRules (Protos);
137+
138+ // Note that we build 'result' by iterating over 'Protos' rather than
139+ // 'rules'; this is intentional, so that even if a protocol has no
140+ // rules, we still end up creating an entry for it in 'result'.
141+ llvm::DenseMap<const ProtocolDecl *, std::vector<Requirement>> result;
142+ for (const auto *proto : Protos)
143+ result[proto] = buildRequirementSignature (rules[proto], proto);
144+
145+ return result;
146+ }
147+
36148ArrayRef<Requirement>
37149RequirementSignatureRequest::evaluate (Evaluator &evaluator,
38150 ProtocolDecl *proto) const {
0 commit comments