Skip to content

Commit e445335

Browse files
committed
RequirementMachine: Record rewrite loops during superclass unification
This is the second half of rdar://problem/88134910. Also addresses rdar://problem/25065503.
1 parent 94b55bd commit e445335

10 files changed

+801
-235
lines changed

lib/AST/RequirementMachine/ConcreteTypeWitness.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,13 @@ void PropertyMap::concretizeNestedTypesFromConcreteParents() {
6363
llvm::dbgs() << "- via superclass requirement\n";
6464
}
6565

66+
const auto &superclassReq = props->getSuperclassRequirement();
6667
concretizeNestedTypesFromConcreteParent(
6768
props->getKey(),
6869
RequirementKind::Superclass,
69-
*props->SuperclassRule,
70-
props->Superclass->getConcreteType(),
71-
props->Superclass->getSubstitutions(),
70+
*superclassReq.SuperclassRule,
71+
superclassReq.SuperclassType->getConcreteType(),
72+
superclassReq.SuperclassType->getSubstitutions(),
7273
props->ConformsToRules,
7374
props->ConformsTo,
7475
props->SuperclassConformances);

lib/AST/RequirementMachine/PropertyMap.cpp

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,12 @@ void PropertyBag::dump(llvm::raw_ostream &out) const {
115115
out << " layout: " << Layout;
116116
}
117117

118-
if (Superclass) {
119-
out << " superclass: " << *Superclass;
118+
if (hasSuperclassBound()) {
119+
const auto &superclassReq = getSuperclassRequirement();
120+
out << " superclass: " << *superclassReq.SuperclassType;
120121
}
121122

122-
if (ConcreteType) {
123+
if (isConcreteType()) {
123124
out << " concrete_type: " << *ConcreteType;
124125
}
125126

@@ -154,8 +155,10 @@ Type PropertyBag::getSuperclassBound(
154155
const MutableTerm &lookupTerm,
155156
const PropertyMap &map) const {
156157
MutableTerm prefix = getPrefixAfterStrippingKey(lookupTerm);
157-
return map.getTypeFromSubstitutionSchema(Superclass->getConcreteType(),
158-
Superclass->getSubstitutions(),
158+
159+
const auto &req = getSuperclassRequirement();
160+
return map.getTypeFromSubstitutionSchema(req.SuperclassType->getConcreteType(),
161+
req.SuperclassType->getSubstitutions(),
159162
genericParams, prefix);
160163
}
161164

@@ -199,17 +202,23 @@ void PropertyBag::copyPropertiesFrom(const PropertyBag *next,
199202
// T := UV should have substitutions {UX1, ..., UXn}.
200203
MutableTerm prefix(Key.begin(), Key.begin() + prefixLength);
201204

202-
if (next->Superclass) {
203-
Superclass = next->Superclass->prependPrefixToConcreteSubstitutions(
204-
prefix, ctx);
205-
SuperclassRule = next->SuperclassRule;
206-
}
207-
208205
if (next->ConcreteType) {
209206
ConcreteType = next->ConcreteType->prependPrefixToConcreteSubstitutions(
210207
prefix, ctx);
211208
ConcreteTypeRule = next->ConcreteTypeRule;
212209
}
210+
211+
// Copy over class hierarchy information.
212+
SuperclassDecl = next->SuperclassDecl;
213+
if (!next->Superclasses.empty()) {
214+
Superclasses = next->Superclasses;
215+
216+
for (auto &pair : Superclasses) {
217+
pair.second.SuperclassType =
218+
pair.second.SuperclassType->prependPrefixToConcreteSubstitutions(
219+
prefix, ctx);
220+
}
221+
}
213222
}
214223

215224
void PropertyBag::verify(const RewriteSystem &system) const {
@@ -221,11 +230,18 @@ void PropertyBag::verify(const RewriteSystem &system) const {
221230
assert(symbol.getProtocol() == ConformsTo[i]);
222231
}
223232

224-
// FIXME: Once unification introduces new rules, add asserts requiring
225-
// that the layout, superclass and concrete type symbols match, as above
233+
// FIXME: Add asserts requiring that the layout, superclass and
234+
// concrete type symbols match, as above
226235
assert(!Layout.isNull() == LayoutRule.hasValue());
227-
assert(Superclass.hasValue() == SuperclassRule.hasValue());
228236
assert(ConcreteType.hasValue() == ConcreteTypeRule.hasValue());
237+
238+
assert((SuperclassDecl == nullptr) == Superclasses.empty());
239+
for (const auto &pair : Superclasses) {
240+
const auto &req = pair.second;
241+
assert(req.SuperclassType.hasValue());
242+
assert(req.SuperclassRule.hasValue());
243+
}
244+
229245
#endif
230246
}
231247

lib/AST/RequirementMachine/PropertyMap.h

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

47+
/// Records a superclass constraint at a given level in the class hierarchy.
48+
struct SuperclassRequirement {
49+
/// The most specific superclass constraint (in type difference order) for
50+
/// this level in the class hierarchy.
51+
Optional<Symbol> SuperclassType;
52+
53+
/// The corresponding superclass rule for the above.
54+
Optional<unsigned> SuperclassRule;
55+
};
56+
4757
/// Stores a convenient representation of all "property-like" rewrite rules of
4858
/// the form T.[p] => T, where [p] is a property symbol, for some term 'T'.
4959
class PropertyBag {
@@ -64,11 +74,14 @@ class PropertyBag {
6474
/// The corresponding layout rule for the above.
6575
Optional<unsigned> LayoutRule;
6676

67-
/// The most specific superclass constraint this type satisfies.
68-
Optional<Symbol> Superclass;
77+
/// The most specific superclass declaration for which this type has a
78+
/// superclass constraint.
79+
const ClassDecl *SuperclassDecl = nullptr;
6980

70-
/// The corresponding superclass rule for the above.
71-
Optional<unsigned> SuperclassRule;
81+
/// Used for unifying superclass rules at different levels in the class
82+
/// hierarchy. For each class declaration, stores a symbol and rule pair
83+
/// for the most specific substituted type.
84+
llvm::SmallDenseMap<const ClassDecl *, SuperclassRequirement, 2> Superclasses;
7285

7386
/// All concrete conformances of Superclass to the protocols in the
7487
/// ConformsTo list.
@@ -97,16 +110,22 @@ class PropertyBag {
97110
PropertyBag &operator=(const PropertyBag &) = delete;
98111
PropertyBag &operator=(PropertyBag &&) = delete;
99112

113+
const SuperclassRequirement &getSuperclassRequirement() const {
114+
assert(SuperclassDecl != nullptr);
115+
auto found = Superclasses.find(SuperclassDecl);
116+
return found->second;
117+
}
118+
100119
public:
101120
Term getKey() const { return Key; }
102121
void dump(llvm::raw_ostream &out) const;
103122

104123
bool hasSuperclassBound() const {
105-
return Superclass.hasValue();
124+
return SuperclassDecl != nullptr;
106125
}
107126

108127
CanType getSuperclassBound() const {
109-
return Superclass->getConcreteType();
128+
return getSuperclassRequirement().SuperclassType->getConcreteType();
110129
}
111130

112131
Type getSuperclassBound(
@@ -257,6 +276,11 @@ class PropertyMap {
257276
Symbol property,
258277
unsigned ruleID);
259278

279+
void recordSuperclassRelation(Term key,
280+
Symbol superclassType,
281+
unsigned superclassRuleID,
282+
const ClassDecl *otherClass);
283+
260284
void addSuperclassProperty(Term key, Symbol property, unsigned ruleID);
261285
void addConcreteTypeProperty(Term key, Symbol property, unsigned ruleID);
262286

0 commit comments

Comments
 (0)