Skip to content

Commit e9b50f0

Browse files
committed
RequirementMachine: Record property rule IDs in property bags
For homotopy reduction to properly deal with rewrite rules introduced by property map construction, we need to keep track of the original property rules when recording properties in property bags. For now, this doesn't even attempt to handle unification or conflicts; we only record the first rule for each kind of property on a fixed key. This isn't actually used for anything yet, except a new verify pass that runs after property map construction.
1 parent 7427b68 commit e9b50f0

File tree

3 files changed

+71
-11
lines changed

3 files changed

+71
-11
lines changed

lib/AST/RequirementMachine/PropertyMap.cpp

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
211232
PropertyMap::~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.
291312
void PropertyMap::addProperty(
292-
Term key, Symbol property,
313+
Term key, Symbol property, unsigned ruleID,
293314
SmallVectorImpl<std::pair<MutableTerm, MutableTerm>> &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.
344374
SmallVector<std::pair<MutableTerm, MutableTerm>, 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

@@ -371,6 +401,9 @@ PropertyMap::buildPropertyMap(unsigned maxIterations,
371401
}
372402
}
373403

404+
// Check invariants of the constructed property map.
405+
verify();
406+
374407
if (System.getRules().size() > maxIterations)
375408
return std::make_pair(CompletionResult::MaxIterations, addedNewRules);
376409

@@ -385,4 +418,11 @@ void PropertyMap::dump(llvm::raw_ostream &out) const {
385418
out << "\n";
386419
}
387420
out << "}\n";
421+
}
422+
423+
void PropertyMap::verify() const {
424+
#ifndef NDEBUG
425+
for (const auto &props : Entries)
426+
props->verify(System);
427+
#endif
388428
}

lib/AST/RequirementMachine/PropertyMap.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ enum class RequirementKind : unsigned;
4141
namespace rewriting {
4242

4343
class MutableTerm;
44-
class RewriteContext;
4544
class Term;
4645

4746
/// Stores a convenient representation of all "property-like" rewrite rules of
@@ -55,26 +54,39 @@ class PropertyBag {
5554
/// All protocols this type conforms to.
5655
llvm::TinyPtrVector<const ProtocolDecl *> ConformsTo;
5756

57+
/// The corresponding protocol conformance rules.
58+
llvm::SmallVector<unsigned, 1> ConformsToRules;
59+
5860
/// The most specific layout constraint this type satisfies.
5961
LayoutConstraint Layout;
6062

63+
/// The corresponding layout rule for the above.
64+
Optional<unsigned> LayoutRule;
65+
6166
/// The most specific superclass constraint this type satisfies.
6267
Optional<Symbol> Superclass;
6368

69+
/// The corresponding superclass rule for the above.
70+
Optional<unsigned> SuperclassRule;
71+
6472
/// All concrete conformances of Superclass to the protocols in the
6573
/// ConformsTo list.
6674
llvm::TinyPtrVector<ProtocolConformance *> SuperclassConformances;
6775

6876
/// The most specific concrete type constraint this type satisfies.
6977
Optional<Symbol> ConcreteType;
7078

79+
/// The corresponding layout rule for the above.
80+
Optional<unsigned> ConcreteTypeRule;
81+
7182
/// All concrete conformances of ConcreteType to the protocols in the
7283
/// ConformsTo list.
7384
llvm::TinyPtrVector<ProtocolConformance *> ConcreteConformances;
7485

7586
explicit PropertyBag(Term key) : Key(key) {}
7687

7788
void addProperty(Symbol property,
89+
unsigned ruleID,
7890
RewriteContext &ctx,
7991
SmallVectorImpl<std::pair<MutableTerm, MutableTerm>> &inducedRules,
8092
bool debug);
@@ -128,6 +140,8 @@ class PropertyBag {
128140
getConformsToExcludingSuperclassConformances() const;
129141

130142
MutableTerm getPrefixAfterStrippingKey(const MutableTerm &lookupTerm) const;
143+
144+
void verify(const RewriteSystem &system) const;
131145
};
132146

133147
/// Stores all rewrite rules of the form T.[p] => T, where [p] is a property
@@ -171,7 +185,7 @@ class PropertyMap {
171185

172186
private:
173187
void clear();
174-
void addProperty(Term key, Symbol property,
188+
void addProperty(Term key, Symbol property, unsigned ruleID,
175189
SmallVectorImpl<std::pair<MutableTerm, MutableTerm>> &inducedRules);
176190

177191
void computeConcreteTypeInDomainMap();
@@ -188,6 +202,8 @@ class PropertyMap {
188202
MutableTerm computeConstraintTermForTypeWitness(
189203
Term key, CanType concreteType, CanType typeWitness,
190204
const MutableTerm &subjectType, ArrayRef<Term> substitutions) const;
205+
206+
void verify() const;
191207
};
192208

193209
} // end namespace rewriting

lib/AST/RequirementMachine/PropertyUnification.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,19 +309,21 @@ static Symbol unifySuperclasses(
309309
}
310310

311311
void PropertyBag::addProperty(
312-
Symbol property, RewriteContext &ctx,
312+
Symbol property, unsigned ruleID, RewriteContext &ctx,
313313
SmallVectorImpl<std::pair<MutableTerm, MutableTerm>> &inducedRules,
314314
bool debug) {
315315

316316
switch (property.getKind()) {
317317
case Symbol::Kind::Protocol:
318318
ConformsTo.push_back(property.getProtocol());
319+
ConformsToRules.push_back(ruleID);
319320
return;
320321

321322
case Symbol::Kind::Layout:
322-
if (!Layout)
323+
if (!Layout) {
323324
Layout = property.getLayoutConstraint();
324-
else
325+
LayoutRule = ruleID;
326+
} else
325327
Layout = Layout.merge(property.getLayoutConstraint());
326328

327329
return;
@@ -334,6 +336,7 @@ void PropertyBag::addProperty(
334336
ctx, inducedRules, debug);
335337
} else {
336338
Superclass = property;
339+
SuperclassRule = ruleID;
337340
}
338341

339342
return;
@@ -345,6 +348,7 @@ void PropertyBag::addProperty(
345348
ctx, inducedRules, debug);
346349
} else {
347350
ConcreteType = property;
351+
ConcreteTypeRule = ruleID;
348352
}
349353

350354
return;

0 commit comments

Comments
 (0)