Skip to content

Commit b2d3eed

Browse files
authored
Merge pull request #41435 from slavapestov/rqm-fixes-for-inferred-signatures-enabled
RequirementMachine: Fix assorted issues when running validation tests with -requirement-machine-inferred-signatures=verify
2 parents 616a404 + 1050519 commit b2d3eed

30 files changed

+602
-310
lines changed

lib/AST/RequirementMachine/ConcreteTypeWitness.cpp

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,16 @@ void PropertyMap::concretizeNestedTypesFromConcreteParents() {
4747
llvm::dbgs() << "- via concrete type requirement\n";
4848
}
4949

50-
concretizeNestedTypesFromConcreteParent(
51-
props->getKey(),
52-
RequirementKind::SameType,
53-
*props->ConcreteTypeRule,
54-
props->ConcreteType->getConcreteType(),
55-
props->ConcreteType->getSubstitutions(),
56-
props->ConformsToRules,
57-
props->ConformsTo,
58-
props->ConcreteConformances);
50+
for (auto pair : props->ConcreteTypeRules) {
51+
concretizeNestedTypesFromConcreteParent(
52+
props->getKey(),
53+
RequirementKind::SameType,
54+
pair.second,
55+
pair.first.getConcreteType(),
56+
pair.first.getSubstitutions(),
57+
props->ConformsToRules,
58+
props->ConformsTo);
59+
}
5960
}
6061

6162
if (props->hasSuperclassBound()) {
@@ -64,15 +65,16 @@ void PropertyMap::concretizeNestedTypesFromConcreteParents() {
6465
}
6566

6667
const auto &superclassReq = props->getSuperclassRequirement();
67-
concretizeNestedTypesFromConcreteParent(
68-
props->getKey(),
69-
RequirementKind::Superclass,
70-
*superclassReq.SuperclassRule,
71-
superclassReq.SuperclassType->getConcreteType(),
72-
superclassReq.SuperclassType->getSubstitutions(),
73-
props->ConformsToRules,
74-
props->ConformsTo,
75-
props->SuperclassConformances);
68+
for (auto pair : superclassReq.SuperclassRules) {
69+
concretizeNestedTypesFromConcreteParent(
70+
props->getKey(),
71+
RequirementKind::Superclass,
72+
pair.second,
73+
pair.first.getConcreteType(),
74+
pair.first.getSubstitutions(),
75+
props->ConformsToRules,
76+
props->ConformsTo);
77+
}
7678
}
7779
}
7880
}
@@ -115,8 +117,7 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
115117
CanType concreteType,
116118
ArrayRef<Term> substitutions,
117119
ArrayRef<unsigned> conformsToRules,
118-
ArrayRef<const ProtocolDecl *> conformsTo,
119-
llvm::TinyPtrVector<ProtocolConformance *> &conformances) {
120+
ArrayRef<const ProtocolDecl *> conformsTo) {
120121
assert(requirementKind == RequirementKind::SameType ||
121122
requirementKind == RequirementKind::Superclass);
122123
assert(conformsTo.size() == conformsToRules.size());
@@ -132,10 +133,8 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
132133
// entry for this key's suffix.
133134
auto pair = std::make_pair(concreteRuleID, conformanceRuleID);
134135
auto found = ConcreteConformances.find(pair);
135-
if (found != ConcreteConformances.end()) {
136-
conformances.push_back(found->second);
136+
if (found != ConcreteConformances.end())
137137
continue;
138-
}
139138

140139
// FIXME: Either remove the ModuleDecl entirely from conformance lookup,
141140
// or pass the correct one down in here.
@@ -183,10 +182,6 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
183182
assert(inserted.second);
184183
(void) inserted;
185184

186-
// Record the conformance for use by
187-
// PropertyBag::getConformsToExcludingSuperclassConformances().
188-
conformances.push_back(concrete);
189-
190185
auto concreteConformanceSymbol = Symbol::forConcreteConformance(
191186
concreteType, substitutions, proto, Context);
192187

lib/AST/RequirementMachine/GenericSignatureQueries.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ RequirementMachine::getLocalRequirements(
5353
result.superclass = props->getSuperclassBound({}, term, Map);
5454
}
5555

56-
for (const auto *proto : props->getConformsToExcludingSuperclassConformances())
56+
for (const auto *proto : props->getConformsTo())
5757
result.protos.push_back(const_cast<ProtocolDecl *>(proto));
5858

5959
result.layout = props->getLayoutConstraint();

lib/AST/RequirementMachine/HomotopyReduction.cpp

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,41 @@ void RewriteSystem::propagateExplicitBits() {
198198
}
199199
}
200200

201+
/// After propagating the 'explicit' bit on rules, process pairs of
202+
/// conflicting rules, marking one or both of the rules as conflicting,
203+
/// which instructs minimization to drop them.
204+
void RewriteSystem::processConflicts() {
205+
for (auto pair : ConflictingRules) {
206+
auto existingRuleID = pair.first;
207+
auto newRuleID = pair.second;
208+
209+
auto *existingRule = &getRule(existingRuleID);
210+
auto *newRule = &getRule(newRuleID);
211+
212+
auto existingKind = existingRule->isPropertyRule()->getKind();
213+
auto newKind = newRule->isPropertyRule()->getKind();
214+
215+
// The GSB preferred to drop an explicit rule in a conflict, but
216+
// only if the kinds were the same.
217+
if (existingRule->isExplicit() && !newRule->isExplicit() &&
218+
existingKind == newKind) {
219+
std::swap(existingRule, newRule);
220+
}
221+
222+
if (newRule->getRHS().size() >= existingRule->getRHS().size()) {
223+
newRule->markConflicting();
224+
} else if (existingKind != Symbol::Kind::Superclass &&
225+
existingKind == newKind) {
226+
// The GSB only dropped the new rule in the case of a conflicting
227+
// superclass requirement, so maintain that behavior here.
228+
if (existingRule->getRHS().size() >= newRule->getRHS().size())
229+
existingRule->markConflicting();
230+
}
231+
232+
// FIXME: Diagnose the conflict later.
233+
}
234+
}
235+
201236
/// Given a rewrite rule which appears exactly once in a loop
202237
/// without context, return a new definition for this rewrite rule.
203238
/// The new definition is the path obtained by deleting the
@@ -507,7 +542,6 @@ findRuleToDelete(llvm::function_ref<bool(unsigned)> isRedundantRuleFn) {
507542
// Two rules (T.[C] => T) and (T.[C'] => T) are incomparable if
508543
// C and C' are superclass, concrete type or concrete conformance
509544
// symbols.
510-
found = pair;
511545
continue;
512546
}
513547

@@ -641,6 +675,7 @@ void RewriteSystem::minimizeRewriteSystem() {
641675
Minimized = 1;
642676

643677
propagateExplicitBits();
678+
processConflicts();
644679

645680
// First pass:
646681
// - Eliminate all LHS-simplified non-conformance rules.
@@ -867,8 +902,16 @@ void RewriteSystem::verifyMinimizedRules(
867902
const auto &rule = getRule(ruleID);
868903

869904
// Ignore the rewrite rule if it is not part of our minimization domain.
870-
if (!isInMinimizationDomain(rule.getLHS().getRootProtocol()))
905+
if (!isInMinimizationDomain(rule.getLHS().getRootProtocol())) {
906+
if (rule.isRedundant()) {
907+
llvm::errs() << "Redundant rule outside minimization domain: "
908+
<< rule << "\n\n";
909+
dump(llvm::errs());
910+
abort();
911+
}
912+
871913
continue;
914+
}
872915

873916
// Note that sometimes permanent rules can be simplified, but they can never
874917
// be redundant.

lib/AST/RequirementMachine/PropertyMap.cpp

Lines changed: 20 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -60,41 +60,6 @@
6060
using namespace swift;
6161
using namespace rewriting;
6262

63-
/// This papers over a behavioral difference between
64-
/// GenericSignature::getRequiredProtocols() and ArchetypeType::getConformsTo();
65-
/// the latter drops any protocols to which the superclass requirement
66-
/// conforms to concretely.
67-
llvm::TinyPtrVector<const ProtocolDecl *>
68-
PropertyBag::getConformsToExcludingSuperclassConformances() const {
69-
llvm::TinyPtrVector<const ProtocolDecl *> result;
70-
71-
if (SuperclassConformances.empty()) {
72-
result = ConformsTo;
73-
return result;
74-
}
75-
76-
// The conformances in SuperclassConformances should appear in the same order
77-
// as the protocols in ConformsTo.
78-
auto conformanceIter = SuperclassConformances.begin();
79-
80-
for (const auto *proto : ConformsTo) {
81-
if (conformanceIter == SuperclassConformances.end()) {
82-
result.push_back(proto);
83-
continue;
84-
}
85-
86-
if (proto == (*conformanceIter)->getProtocol()) {
87-
++conformanceIter;
88-
continue;
89-
}
90-
91-
result.push_back(proto);
92-
}
93-
94-
assert(conformanceIter == SuperclassConformances.end());
95-
return result;
96-
}
97-
9863
void PropertyBag::dump(llvm::raw_ostream &out) const {
9964
out << Key << " => {";
10065

@@ -205,30 +170,41 @@ void PropertyBag::copyPropertiesFrom(const PropertyBag *next,
205170
if (next->ConcreteType) {
206171
ConcreteType = next->ConcreteType->prependPrefixToConcreteSubstitutions(
207172
prefix, ctx);
208-
ConcreteTypeRule = next->ConcreteTypeRule;
173+
ConcreteTypeRules = next->ConcreteTypeRules;
174+
for (auto &pair : ConcreteTypeRules) {
175+
pair.first = pair.first.prependPrefixToConcreteSubstitutions(
176+
prefix, ctx);
177+
}
209178
}
210179

211180
// Copy over class hierarchy information.
212181
SuperclassDecl = next->SuperclassDecl;
213182
if (!next->Superclasses.empty()) {
214183
Superclasses = next->Superclasses;
215184

216-
for (auto &pair : Superclasses) {
217-
pair.second.SuperclassType =
218-
pair.second.SuperclassType->prependPrefixToConcreteSubstitutions(
185+
for (auto &req : Superclasses) {
186+
req.second.SuperclassType =
187+
req.second.SuperclassType->prependPrefixToConcreteSubstitutions(
219188
prefix, ctx);
189+
for (auto &pair : req.second.SuperclassRules) {
190+
pair.first = pair.first.prependPrefixToConcreteSubstitutions(
191+
prefix, ctx);
192+
}
220193
}
221194
}
222195
}
223196

224197
Symbol PropertyBag::concretelySimplifySubstitution(const MutableTerm &mutTerm,
225198
RewriteContext &ctx,
226199
RewritePath *path) const {
200+
assert(!ConcreteTypeRules.empty());
201+
auto &pair = ConcreteTypeRules.front();
202+
227203
// The property map entry might apply to a suffix of the substitution
228204
// term, so prepend the appropriate prefix to its own substitutions.
229205
auto prefix = getPrefixAfterStrippingKey(mutTerm);
230206
auto concreteSymbol =
231-
ConcreteType->prependPrefixToConcreteSubstitutions(
207+
pair.first.prependPrefixToConcreteSubstitutions(
232208
prefix, ctx);
233209

234210
// If U.V is the substitution term and V is the property map key,
@@ -238,7 +214,7 @@ Symbol PropertyBag::concretelySimplifySubstitution(const MutableTerm &mutTerm,
238214
if (path) {
239215
path->add(RewriteStep::forRewriteRule(/*startOffset=*/prefix.size(),
240216
/*endOffset=*/0,
241-
/*ruleID=*/*ConcreteTypeRule,
217+
/*ruleID=*/pair.second,
242218
/*inverse=*/true));
243219

244220
if (!prefix.empty()) {
@@ -263,13 +239,13 @@ void PropertyBag::verify(const RewriteSystem &system) const {
263239
// FIXME: Add asserts requiring that the layout, superclass and
264240
// concrete type symbols match, as above
265241
assert(!Layout.isNull() == LayoutRule.hasValue());
266-
assert(ConcreteType.hasValue() == ConcreteTypeRule.hasValue());
242+
assert(ConcreteType.hasValue() == !ConcreteTypeRules.empty());
267243

268244
assert((SuperclassDecl == nullptr) == Superclasses.empty());
269245
for (const auto &pair : Superclasses) {
270246
const auto &req = pair.second;
271247
assert(req.SuperclassType.hasValue());
272-
assert(req.SuperclassRule.hasValue());
248+
assert(!req.SuperclassRules.empty());
273249
}
274250

275251
#endif
@@ -396,8 +372,7 @@ void PropertyMap::buildPropertyMap() {
396372

397373
for (const auto &rule : System.getRules()) {
398374
if (rule.isLHSSimplified() ||
399-
rule.isRHSSimplified() ||
400-
rule.isSubstitutionSimplified())
375+
rule.isRHSSimplified())
401376
continue;
402377

403378
// Identity conformances ([P].[P] => [P]) are permanent rules, but we

lib/AST/RequirementMachine/PropertyMap.h

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ namespace rewriting {
4444
class MutableTerm;
4545
class Term;
4646

47-
/// Records a superclass constraint at a given level in the class hierarchy.
47+
/// Records superclass requirements at a given level in the class hierarchy.
4848
struct SuperclassRequirement {
4949
/// The most specific superclass constraint (in type difference order) for
5050
/// this level in the class hierarchy.
5151
Optional<Symbol> SuperclassType;
5252

53-
/// The corresponding superclass rule for the above.
54-
Optional<unsigned> SuperclassRule;
53+
/// Superclass rules that apply to this key.
54+
llvm::SmallVector<std::pair<Symbol, unsigned>, 1> SuperclassRules;
5555
};
5656

5757
/// Stores a convenient representation of all "property-like" rewrite rules of
@@ -83,19 +83,11 @@ class PropertyBag {
8383
/// for the most specific substituted type.
8484
llvm::SmallDenseMap<const ClassDecl *, SuperclassRequirement, 2> Superclasses;
8585

86-
/// All concrete conformances of Superclass to the protocols in the
87-
/// ConformsTo list.
88-
llvm::TinyPtrVector<ProtocolConformance *> SuperclassConformances;
89-
9086
/// The most specific concrete type constraint this type satisfies.
9187
Optional<Symbol> ConcreteType;
9288

93-
/// The corresponding layout rule for the above.
94-
Optional<unsigned> ConcreteTypeRule;
95-
96-
/// All concrete conformances of ConcreteType to the protocols in the
97-
/// ConformsTo list.
98-
llvm::TinyPtrVector<ProtocolConformance *> ConcreteConformances;
89+
/// Concrete type rules that apply to this key.
90+
llvm::SmallVector<std::pair<Symbol, unsigned>, 1> ConcreteTypeRules;
9991

10092
/// Cache of associated type declarations.
10193
llvm::SmallDenseMap<Identifier, AssociatedTypeDecl *, 2> AssocTypes;
@@ -156,9 +148,6 @@ class PropertyBag {
156148
return ConformsTo;
157149
}
158150

159-
llvm::TinyPtrVector<const ProtocolDecl *>
160-
getConformsToExcludingSuperclassConformances() const;
161-
162151
AssociatedTypeDecl *getAssociatedType(Identifier name);
163152

164153
Symbol concretelySimplifySubstitution(const MutableTerm &mutTerm,
@@ -270,10 +259,14 @@ class PropertyMap {
270259
void addLayoutProperty(Term key, Symbol property, unsigned ruleID);
271260

272261
void unifyConcreteTypes(Term key,
273-
Optional<Symbol> &existingProperty,
274-
Optional<unsigned> &existingRuleID,
275-
Symbol property,
276-
unsigned ruleID);
262+
Symbol lhsProperty, unsigned lhsRuleID,
263+
Symbol rhsProperty, unsigned rhsRuleID);
264+
265+
void unifyConcreteTypes(Term key,
266+
Optional<Symbol> &bestProperty,
267+
llvm::SmallVectorImpl<std::pair<Symbol, unsigned>> &
268+
existingRules,
269+
Symbol property, unsigned ruleID);
277270

278271
void recordSuperclassRelation(Term key,
279272
Symbol superclassType,
@@ -293,8 +286,7 @@ class PropertyMap {
293286
CanType concreteType,
294287
ArrayRef<Term> substitutions,
295288
ArrayRef<unsigned> conformsToRules,
296-
ArrayRef<const ProtocolDecl *> conformsTo,
297-
llvm::TinyPtrVector<ProtocolConformance *> &conformances);
289+
ArrayRef<const ProtocolDecl *> conformsTo);
298290

299291
void concretizeTypeWitnessInConformance(
300292
Term key, RequirementKind requirementKind,

0 commit comments

Comments
 (0)