@@ -190,7 +190,9 @@ void PropertyBag::copyPropertiesFrom(const PropertyBag *next,
190190 // Conformances and the layout constraint, if any, can be copied over
191191 // unmodified.
192192 ConformsTo = next->ConformsTo ;
193+ ConformsToRules = next->ConformsToRules ;
193194 Layout = next->Layout ;
195+ LayoutRule = next->LayoutRule ;
194196
195197 // If the property bag of V has superclass or concrete type
196198 // substitutions {X1, ..., Xn}, then the property bag of
@@ -200,14 +202,33 @@ void PropertyBag::copyPropertiesFrom(const PropertyBag *next,
200202 if (next->Superclass ) {
201203 Superclass = next->Superclass ->prependPrefixToConcreteSubstitutions (
202204 prefix, ctx);
205+ SuperclassRule = next->SuperclassRule ;
203206 }
204207
205208 if (next->ConcreteType ) {
206209 ConcreteType = next->ConcreteType ->prependPrefixToConcreteSubstitutions (
207210 prefix, ctx);
211+ ConcreteTypeRule = next->ConcreteTypeRule ;
208212 }
209213}
210214
215+ void PropertyBag::verify (const RewriteSystem &system) const {
216+ #ifndef NDEBUG
217+ assert (ConformsTo.size () == ConformsToRules.size ());
218+ for (unsigned i : indices (ConformsTo)) {
219+ auto symbol = system.getRule (ConformsToRules[i]).getLHS ().back ();
220+ assert (symbol.getKind () == Symbol::Kind::Protocol);
221+ assert (symbol.getProtocol () == ConformsTo[i]);
222+ }
223+
224+ // FIXME: Once unification introduces new rules, add asserts requiring
225+ // that the layout, superclass and concrete type symbols match, as above
226+ assert (!Layout.isNull () == LayoutRule.hasValue ());
227+ assert (Superclass.hasValue () == SuperclassRule.hasValue ());
228+ assert (ConcreteType.hasValue () == ConcreteTypeRule.hasValue ());
229+ #endif
230+ }
231+
211232PropertyMap::~PropertyMap () {
212233 Trie.updateHistograms (Context.PropertyTrieHistogram ,
213234 Context.PropertyTrieRootHistogram );
@@ -289,11 +310,12 @@ void PropertyMap::clear() {
289310// / Record a protocol conformance, layout or superclass constraint on the given
290311// / key. Must be called in monotonically non-decreasing key order.
291312void PropertyMap::addProperty (
292- Term key, Symbol property,
293- SmallVectorImpl<std::pair<MutableTerm, MutableTerm> > &inducedRules) {
313+ Term key, Symbol property, unsigned ruleID,
314+ SmallVectorImpl<InducedRule > &inducedRules) {
294315 assert (property.isProperty ());
316+ assert (*System.getRule (ruleID).isPropertyRule () == property);
295317 auto *props = getOrCreateProperties (key);
296- props->addProperty (property, Context,
318+ props->addProperty (property, ruleID, Context,
297319 inducedRules, Debug.contains (DebugFlags::ConcreteUnification));
298320}
299321
@@ -314,11 +336,17 @@ PropertyMap::buildPropertyMap(unsigned maxIterations,
314336 unsigned maxDepth) {
315337 clear ();
316338
339+ struct Property {
340+ Term key;
341+ Symbol symbol;
342+ unsigned ruleID;
343+ };
344+
317345 // PropertyMap::addRule() requires that shorter rules are added
318346 // before longer rules, so that it can perform lookups on suffixes and call
319347 // PropertyBag::copyPropertiesFrom(). However, we don't have to perform a
320348 // full sort by term order here; a bucket sort by term length suffices.
321- SmallVector<std::vector<std::pair<Term, Symbol> >, 4 > properties;
349+ SmallVector<std::vector<Property >, 4 > properties;
322350
323351 for (const auto &rule : System.getRules ()) {
324352 if (rule.isSimplified ())
@@ -336,16 +364,18 @@ PropertyMap::buildPropertyMap(unsigned maxIterations,
336364 unsigned length = rhs.size ();
337365 if (length >= properties.size ())
338366 properties.resize (length + 1 );
339- properties[length].emplace_back (rhs, *property);
367+
368+ unsigned ruleID = System.getRuleID (rule);
369+ properties[length].push_back ({rhs, *property, ruleID});
340370 }
341371
342372 // Merging multiple superclass or concrete type rules can induce new rules
343373 // to unify concrete type constructor arguments.
344- SmallVector<std::pair<MutableTerm, MutableTerm> , 3 > inducedRules;
374+ SmallVector<InducedRule , 3 > inducedRules;
345375
346376 for (const auto &bucket : properties) {
347- for (auto pair : bucket) {
348- addProperty (pair. first , pair. second , inducedRules);
377+ for (auto property : bucket) {
378+ addProperty (property. key , property. symbol , property. ruleID , inducedRules);
349379 }
350380 }
351381
@@ -358,11 +388,17 @@ PropertyMap::buildPropertyMap(unsigned maxIterations,
358388 // the concrete type witnesses in the concrete type's conformance.
359389 concretizeNestedTypesFromConcreteParents (inducedRules);
360390
391+ // Finally, introduce concrete conformance rules, relating conformance rules
392+ // to concrete type and superclass rules.
393+ recordConcreteConformanceRules (inducedRules);
394+
361395 // Some of the induced rules might be trivial; only count the induced rules
362396 // where the left hand side is not already equivalent to the right hand side.
363397 unsigned addedNewRules = 0 ;
364398 for (auto pair : inducedRules) {
365- if (System.addRule (pair.first , pair.second )) {
399+ // FIXME: Eventually, all induced rules will have a rewrite path.
400+ if (System.addRule (pair.LHS , pair.RHS ,
401+ pair.Path .empty () ? nullptr : &pair.Path )) {
366402 ++addedNewRules;
367403
368404 const auto &newRule = System.getRules ().back ();
@@ -371,6 +407,9 @@ PropertyMap::buildPropertyMap(unsigned maxIterations,
371407 }
372408 }
373409
410+ // Check invariants of the constructed property map.
411+ verify ();
412+
374413 if (System.getRules ().size () > maxIterations)
375414 return std::make_pair (CompletionResult::MaxIterations, addedNewRules);
376415
@@ -385,4 +424,11 @@ void PropertyMap::dump(llvm::raw_ostream &out) const {
385424 out << " \n " ;
386425 }
387426 out << " }\n " ;
427+ }
428+
429+ void PropertyMap::verify () const {
430+ #ifndef NDEBUG
431+ for (const auto &props : Entries)
432+ props->verify (System);
433+ #endif
388434}
0 commit comments