@@ -40,14 +40,71 @@ STATISTIC(NumLazyRequirementSignaturesLoaded,
4040
4141#undef DEBUG_TYPE
4242
43+ namespace {
44+
45+ // / Represents a set of types related by same-type requirements, and an
46+ // / optional concrete type requirement.
47+ struct ConnectedComponent {
48+ llvm::SmallVector<Type, 2 > Members;
49+ Type ConcreteType;
50+
51+ void buildRequirements (Type subjectType, std::vector<Requirement> &reqs);
52+ };
53+
54+ // / Case 1: A set of rewrite rules of the form:
55+ // /
56+ // / B => A
57+ // / C => A
58+ // / D => A
59+ // /
60+ // / Become a series of same-type requirements
61+ // /
62+ // / A == B, B == C, C == D
63+ // /
64+ // / Case 2: A set of rewrite rules of the form:
65+ // /
66+ // / A.[concrete: X] => A
67+ // / B => A
68+ // / C => A
69+ // / D => A
70+ // /
71+ // / Become a series of same-type requirements
72+ // /
73+ // / A == X, B == X, C == X, D == X
74+ void ConnectedComponent::buildRequirements (Type subjectType,
75+ std::vector<Requirement> &reqs) {
76+ std::sort (Members.begin (), Members.end (),
77+ [](Type first, Type second) -> bool {
78+ return compareDependentTypes (first, second) < 0 ;
79+ });
80+
81+ if (!ConcreteType) {
82+ for (auto constraintType : Members) {
83+ reqs.emplace_back (RequirementKind::SameType,
84+ subjectType, constraintType);
85+ subjectType = constraintType;
86+ }
87+ } else {
88+ reqs.emplace_back (RequirementKind::SameType,
89+ subjectType, ConcreteType);
90+
91+ for (auto constraintType : Members) {
92+ reqs.emplace_back (RequirementKind::SameType,
93+ constraintType, ConcreteType);
94+ }
95+ }
96+ }
97+
98+ } // end namespace
99+
43100// / Convert a list of non-permanent, non-redundant rewrite rules into a minimal
44101// / protocol requirement signature for \p proto. The requirements are sorted in
45102// / canonical order, and same-type requirements are canonicalized.
46103std::vector<Requirement>
47104RequirementMachine::buildRequirementSignature (ArrayRef<unsigned > rules,
48105 const ProtocolDecl *proto) const {
49106 std::vector<Requirement> reqs;
50- llvm::SmallDenseMap<TypeBase *, llvm::SmallVector<Type, 2 > > sameTypeReqs;
107+ llvm::SmallDenseMap<TypeBase *, ConnectedComponent > sameTypeReqs;
51108
52109 auto genericParams = proto->getGenericSignature ().getGenericParams ();
53110 const auto &protos = System.getProtocols ();
@@ -81,15 +138,18 @@ RequirementMachine::buildRequirementSignature(ArrayRef<unsigned> rules,
81138 protos));
82139 return ;
83140
84- case Symbol::Kind::ConcreteType:
85- reqs.emplace_back (RequirementKind::SameType,
86- subjectType,
87- Context.getTypeFromSubstitutionSchema (
88- prop->getConcreteType (),
89- prop->getSubstitutions (),
90- genericParams, MutableTerm (),
91- protos));
141+ case Symbol::Kind::ConcreteType: {
142+ auto concreteType = Context.getTypeFromSubstitutionSchema (
143+ prop->getConcreteType (),
144+ prop->getSubstitutions (),
145+ genericParams, MutableTerm (),
146+ protos);
147+
148+ auto &component = sameTypeReqs[subjectType.getPointer ()];
149+ assert (!component.ConcreteType );
150+ component.ConcreteType = concreteType;
92151 return ;
152+ }
93153
94154 case Symbol::Kind::Name:
95155 case Symbol::Kind::AssociatedType:
@@ -104,41 +164,41 @@ RequirementMachine::buildRequirementSignature(ArrayRef<unsigned> rules,
104164 auto subjectType = Context.getTypeForTerm (rule.getRHS (), genericParams,
105165 protos);
106166
107- sameTypeReqs[subjectType.getPointer ()].push_back (constraintType);
167+ sameTypeReqs[subjectType.getPointer ()].Members . push_back (constraintType);
108168 }
109169 };
110170
171+ if (getDebugOptions ().contains (DebugFlags::Minimization)) {
172+ llvm::dbgs () << " Minimized rules:\n " ;
173+ }
174+
111175 // Build the list of requirements, storing same-type requirements off
112176 // to the side.
113177 for (unsigned ruleID : rules) {
114178 const auto &rule = System.getRule (ruleID);
179+
180+ if (getDebugOptions ().contains (DebugFlags::Minimization)) {
181+ llvm::dbgs () << " - " << rule << " \n " ;
182+ }
183+
115184 createRequirementFromRule (rule);
116185 }
117186
118- // A set of rewrite rules of the form:
119- //
120- // B => A
121- // C => A
122- // D => A
123- //
124- // Become a series of same-type requirements
125- //
126- // A == B, B == C, C == D
127- //
187+ // Now, convert each connected component into a series of same-type
188+ // requirements.
128189 for (auto &pair : sameTypeReqs) {
129- std::sort (pair.second .begin (), pair.second .end (),
130- [](Type first, Type second) -> bool {
131- return compareDependentTypes (first, second) < 0 ;
132- });
133-
134- Type subjectType (pair.first );
135- for (auto constraintType : pair.second ) {
136- reqs.emplace_back (RequirementKind::SameType, subjectType, constraintType);
137- subjectType = constraintType;
190+ pair.second .buildRequirements (pair.first , reqs);
191+ }
192+
193+ if (getDebugOptions ().contains (DebugFlags::Minimization)) {
194+ llvm::dbgs () << " Requirements:\n " ;
195+ for (const auto &req : reqs) {
196+ req.dump (llvm::dbgs ());
197+ llvm::dbgs () << " \n " ;
138198 }
139199 }
140200
141- // Sort the requirements in canonical order.
201+ // Finally, sort the requirements in canonical order.
142202 std::sort (reqs.begin (), reqs.end (),
143203 [](const Requirement &lhs, const Requirement &rhs) -> bool {
144204 return lhs.compare (rhs) < 0 ;
0 commit comments