Skip to content

Commit 8e2f122

Browse files
authored
Merge pull request swiftlang#40752 from slavapestov/rqm-more-property-map-rewrite-loops
RequirementMachine: More fixes for property map induced rules
2 parents 127528a + 746f4a5 commit 8e2f122

18 files changed

+346
-177
lines changed

lib/AST/RequirementMachine/HomotopyReduction.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ findRuleToDelete(llvm::function_ref<bool(unsigned)> isRedundantRuleFn,
367367
foundAny = true;
368368
}
369369

370+
// Delete loops that don't contain any rewrite rules in empty context,
371+
// since such loops do not give us useful information.
370372
if (!foundAny)
371373
loop.markDeleted();
372374
}
@@ -566,15 +568,14 @@ bool RewriteSystem::hadError() const {
566568
}
567569

568570
/// Collect all non-permanent, non-redundant rules whose domain is equal to
569-
/// one of the protocols in \p proto. In other words, the first symbol of the
570-
/// left hand side term is either a protocol symbol or associated type symbol
571-
/// whose protocol is in \p proto.
571+
/// one of the protocols in the connected component represented by this
572+
/// rewrite system.
572573
///
573574
/// These rules form the requirement signatures of these protocols.
574575
llvm::DenseMap<const ProtocolDecl *, std::vector<unsigned>>
575-
RewriteSystem::getMinimizedProtocolRules(
576-
ArrayRef<const ProtocolDecl *> protos) const {
576+
RewriteSystem::getMinimizedProtocolRules() const {
577577
assert(Minimized);
578+
assert(!Protos.empty());
578579

579580
llvm::DenseMap<const ProtocolDecl *, std::vector<unsigned>> rules;
580581
for (unsigned ruleID : indices(Rules)) {
@@ -591,7 +592,7 @@ RewriteSystem::getMinimizedProtocolRules(
591592
assert(domain.size() == 1);
592593

593594
const auto *proto = domain[0];
594-
if (std::find(protos.begin(), protos.end(), proto) != protos.end())
595+
if (std::find(Protos.begin(), Protos.end(), proto) != Protos.end())
595596
rules[proto].push_back(ruleID);
596597
}
597598

@@ -605,6 +606,7 @@ RewriteSystem::getMinimizedProtocolRules(
605606
std::vector<unsigned>
606607
RewriteSystem::getMinimizedGenericSignatureRules() const {
607608
assert(Minimized);
609+
assert(Protos.empty());
608610

609611
std::vector<unsigned> rules;
610612
for (unsigned ruleID : indices(Rules)) {
@@ -685,6 +687,10 @@ void RewriteSystem::verifyMinimizedRules(
685687
for (unsigned ruleID : indices(Rules)) {
686688
const auto &rule = getRule(ruleID);
687689

690+
// Ignore the rewrite rule if it is not part of our minimization domain.
691+
if (!isInMinimizationDomain(rule.getLHS().getRootProtocols()))
692+
continue;
693+
688694
// Note that sometimes permanent rules can be simplified, but they can never
689695
// be redundant.
690696
if (rule.isPermanent()) {

lib/AST/RequirementMachine/KnuthBendix.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ RewriteSystem::computeConfluentCompletion(unsigned maxIterations,
622622
}
623623

624624
for (const auto &loop : resolvedLoops) {
625-
recordRewriteLoop(loop);
625+
recordRewriteLoop(loop.Basepoint, loop.Path);
626626
}
627627

628628
resolvedCriticalPairs.clear();

lib/AST/RequirementMachine/PropertyMap.cpp

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -307,22 +307,6 @@ void PropertyMap::clear() {
307307
ConcreteTypeInDomainMap.clear();
308308
}
309309

310-
/// Record a protocol conformance, layout or superclass constraint on the given
311-
/// key. Must be called in monotonically non-decreasing key order.
312-
///
313-
/// If there was a conflict, returns the conflicting rule ID; otherwise
314-
/// returns None.
315-
Optional<unsigned> PropertyMap::addProperty(
316-
Term key, Symbol property, unsigned ruleID,
317-
SmallVectorImpl<InducedRule> &inducedRules) {
318-
assert(property.isProperty());
319-
assert(*System.getRule(ruleID).isPropertyRule() == property);
320-
auto *props = getOrCreateProperties(key);
321-
bool debug = Debug.contains(DebugFlags::ConcreteUnification);
322-
return props->addProperty(property, ruleID, System,
323-
inducedRules, debug);
324-
}
325-
326310
/// Build the property map from all rules of the form T.[p] => T, where
327311
/// [p] is a property symbol.
328312
///
@@ -379,25 +363,14 @@ PropertyMap::buildPropertyMap(unsigned maxIterations,
379363

380364
for (const auto &bucket : properties) {
381365
for (auto property : bucket) {
382-
auto existingRuleID = addProperty(property.key, property.symbol,
383-
property.ruleID, inducedRules);
384-
if (existingRuleID) {
385-
// The GSB only dropped the new rule in the case of a conflicting
386-
// superclass requirement, so maintain that behavior here.
387-
auto &existingRule = System.getRule(*existingRuleID);
388-
if (existingRule.isPropertyRule()->getKind() !=
389-
Symbol::Kind::Superclass) {
390-
if (existingRule.getRHS().size() == property.key.size())
391-
existingRule.markConflicting();
392-
}
393-
394-
auto &newRule = System.getRule(property.ruleID);
395-
assert(newRule.getRHS().size() == property.key.size());
396-
newRule.markConflicting();
397-
}
366+
addProperty(property.key, property.symbol,
367+
property.ruleID, inducedRules);
398368
}
399369
}
400370

371+
// Now, check for conflicts between superclass and concrete type rules.
372+
checkConcreteTypeRequirements(inducedRules);
373+
401374
// We collect terms with fully concrete types so that we can re-use them
402375
// to tie off recursion in the next step.
403376
computeConcreteTypeInDomainMap();

lib/AST/RequirementMachine/PropertyMap.h

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,6 @@ class PropertyBag {
101101

102102
explicit PropertyBag(Term key) : Key(key) {}
103103

104-
Optional<unsigned> addProperty(Symbol property,
105-
unsigned ruleID,
106-
RewriteSystem &system,
107-
SmallVectorImpl<InducedRule> &inducedRules,
108-
bool debug);
109104
void copyPropertiesFrom(const PropertyBag *next,
110105
RewriteContext &ctx);
111106

@@ -173,9 +168,35 @@ class PropertyMap {
173168
using ConcreteTypeInDomain = std::pair<CanType, ArrayRef<const ProtocolDecl *>>;
174169
llvm::DenseMap<ConcreteTypeInDomain, Term> ConcreteTypeInDomainMap;
175170

171+
// Building the property map introduces new induced rules, which
172+
// runs another round of Knuth-Bendix completion, which rebuilds the
173+
// property map again.
174+
//
175+
// To avoid wasted work from re-introducing the same induced rules,
176+
// we track the rules we've seen already on previous builds.
177+
178+
/// Maps a pair of rules where the first is a conformance rule and the
179+
/// second is a superclass or concrete type rule, to a concrete
180+
/// conformance.
176181
llvm::DenseMap<std::pair<unsigned, unsigned>, ProtocolConformance *>
177182
ConcreteConformances;
178183

184+
/// Superclass requirements always imply a layout requirement, and
185+
/// concrete type requirements where the type is a class imply a
186+
/// superclass requirement.
187+
///
188+
/// Keep track of such rules to avoid wasted work from recording the
189+
/// same rewrite loop more than once.
190+
llvm::DenseSet<unsigned> CheckedRules;
191+
192+
/// When a type parameter is subject to two requirements of the same
193+
/// kind, we have a pair of rewrite rules T.[p1] => T and T.[p2] => T.
194+
///
195+
/// One of these rules might imply the other. Keep track of these pairs
196+
/// to avoid wasted work from recording the same rewrite loop more than
197+
/// once.
198+
llvm::DenseSet<std::pair<unsigned, unsigned>> CheckedRulePairs;
199+
179200
DebugOptions Debug;
180201

181202
PropertyBag *getOrCreateProperties(Term key);
@@ -204,9 +225,15 @@ class PropertyMap {
204225

205226
private:
206227
void clear();
207-
Optional<unsigned>
208-
addProperty(Term key, Symbol property, unsigned ruleID,
209-
SmallVectorImpl<InducedRule> &inducedRules);
228+
229+
bool checkRuleOnce(unsigned ruleID);
230+
bool checkRulePairOnce(unsigned firstRuleID, unsigned secondRuleID);
231+
232+
void addProperty(Term key, Symbol property, unsigned ruleID,
233+
SmallVectorImpl<InducedRule> &inducedRules);
234+
235+
void checkConcreteTypeRequirements(
236+
SmallVectorImpl<InducedRule> &inducedRules);
210237

211238
void computeConcreteTypeInDomainMap();
212239
void concretizeNestedTypesFromConcreteParents(

0 commit comments

Comments
 (0)