@@ -190,7 +190,9 @@ void PropertyBag::copyPropertiesFrom(const PropertyBag *next,
190
190
// Conformances and the layout constraint, if any, can be copied over
191
191
// unmodified.
192
192
ConformsTo = next->ConformsTo ;
193
+ ConformsToRules = next->ConformsToRules ;
193
194
Layout = next->Layout ;
195
+ LayoutRule = next->LayoutRule ;
194
196
195
197
// If the property bag of V has superclass or concrete type
196
198
// substitutions {X1, ..., Xn}, then the property bag of
@@ -200,14 +202,33 @@ void PropertyBag::copyPropertiesFrom(const PropertyBag *next,
200
202
if (next->Superclass ) {
201
203
Superclass = next->Superclass ->prependPrefixToConcreteSubstitutions (
202
204
prefix, ctx);
205
+ SuperclassRule = next->SuperclassRule ;
203
206
}
204
207
205
208
if (next->ConcreteType ) {
206
209
ConcreteType = next->ConcreteType ->prependPrefixToConcreteSubstitutions (
207
210
prefix, ctx);
211
+ ConcreteTypeRule = next->ConcreteTypeRule ;
208
212
}
209
213
}
210
214
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
+
211
232
PropertyMap::~PropertyMap () {
212
233
Trie.updateHistograms (Context.PropertyTrieHistogram ,
213
234
Context.PropertyTrieRootHistogram );
@@ -289,11 +310,12 @@ void PropertyMap::clear() {
289
310
// / Record a protocol conformance, layout or superclass constraint on the given
290
311
// / key. Must be called in monotonically non-decreasing key order.
291
312
void PropertyMap::addProperty (
292
- Term key, Symbol property,
313
+ Term key, Symbol property, unsigned ruleID,
293
314
SmallVectorImpl<std::pair<MutableTerm, MutableTerm>> &inducedRules) {
294
315
assert (property.isProperty ());
316
+ assert (*System.getRule (ruleID).isPropertyRule () == property);
295
317
auto *props = getOrCreateProperties (key);
296
- props->addProperty (property, Context,
318
+ props->addProperty (property, ruleID, Context,
297
319
inducedRules, Debug.contains (DebugFlags::ConcreteUnification));
298
320
}
299
321
@@ -314,11 +336,17 @@ PropertyMap::buildPropertyMap(unsigned maxIterations,
314
336
unsigned maxDepth) {
315
337
clear ();
316
338
339
+ struct Property {
340
+ Term key;
341
+ Symbol symbol;
342
+ unsigned ruleID;
343
+ };
344
+
317
345
// PropertyMap::addRule() requires that shorter rules are added
318
346
// before longer rules, so that it can perform lookups on suffixes and call
319
347
// PropertyBag::copyPropertiesFrom(). However, we don't have to perform a
320
348
// 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;
322
350
323
351
for (const auto &rule : System.getRules ()) {
324
352
if (rule.isSimplified ())
@@ -336,16 +364,18 @@ PropertyMap::buildPropertyMap(unsigned maxIterations,
336
364
unsigned length = rhs.size ();
337
365
if (length >= properties.size ())
338
366
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});
340
370
}
341
371
342
372
// Merging multiple superclass or concrete type rules can induce new rules
343
373
// to unify concrete type constructor arguments.
344
374
SmallVector<std::pair<MutableTerm, MutableTerm>, 3 > inducedRules;
345
375
346
376
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);
349
379
}
350
380
}
351
381
@@ -371,6 +401,9 @@ PropertyMap::buildPropertyMap(unsigned maxIterations,
371
401
}
372
402
}
373
403
404
+ // Check invariants of the constructed property map.
405
+ verify ();
406
+
374
407
if (System.getRules ().size () > maxIterations)
375
408
return std::make_pair (CompletionResult::MaxIterations, addedNewRules);
376
409
@@ -385,4 +418,11 @@ void PropertyMap::dump(llvm::raw_ostream &out) const {
385
418
out << " \n " ;
386
419
}
387
420
out << " }\n " ;
421
+ }
422
+
423
+ void PropertyMap::verify () const {
424
+ #ifndef NDEBUG
425
+ for (const auto &props : Entries)
426
+ props->verify (System);
427
+ #endif
388
428
}
0 commit comments