Skip to content

Commit 2e3cb17

Browse files
committed
RequirementMachine: Refactor concrete substitution pass
1 parent e478ced commit 2e3cb17

File tree

4 files changed

+72
-49
lines changed

4 files changed

+72
-49
lines changed

lib/AST/RequirementMachine/PropertyMap.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,36 @@ void PropertyBag::copyPropertiesFrom(const PropertyBag *next,
221221
}
222222
}
223223

224+
Symbol PropertyBag::concretelySimplifySubstitution(const MutableTerm &mutTerm,
225+
RewriteContext &ctx,
226+
RewritePath *path) const {
227+
// The property map entry might apply to a suffix of the substitution
228+
// term, so prepend the appropriate prefix to its own substitutions.
229+
auto prefix = getPrefixAfterStrippingKey(mutTerm);
230+
auto concreteSymbol =
231+
ConcreteType->prependPrefixToConcreteSubstitutions(
232+
prefix, ctx);
233+
234+
// If U.V is the substitution term and V is the property map key,
235+
// apply the rewrite step U.(V => V.[concrete: C]) followed by
236+
// prepending the prefix U to each substitution in the concrete type
237+
// symbol if |U| > 0.
238+
if (path) {
239+
path->add(RewriteStep::forRewriteRule(/*startOffset=*/prefix.size(),
240+
/*endOffset=*/0,
241+
/*ruleID=*/*ConcreteTypeRule,
242+
/*inverse=*/true));
243+
244+
if (!prefix.empty()) {
245+
path->add(RewriteStep::forPrefixSubstitutions(/*length=*/prefix.size(),
246+
/*endOffset=*/0,
247+
/*inverse=*/false));
248+
}
249+
}
250+
251+
return concreteSymbol;
252+
}
253+
224254
void PropertyBag::verify(const RewriteSystem &system) const {
225255
#ifndef NDEBUG
226256
assert(ConformsTo.size() == ConformsToRules.size());
@@ -408,7 +438,7 @@ void PropertyMap::buildPropertyMap() {
408438

409439
// Finally, a post-processing pass to reduce substitutions down to
410440
// concrete types.
411-
concretelySimplifyLeftHandSideSubstitutions();
441+
System.simplifyLeftHandSideSubstitutions(this);
412442

413443
// Check invariants of the constructed property map.
414444
verify();

lib/AST/RequirementMachine/PropertyMap.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ class PropertyBag {
116116
return found->second;
117117
}
118118

119+
MutableTerm getPrefixAfterStrippingKey(const MutableTerm &lookupTerm) const;
120+
119121
public:
120122
Term getKey() const { return Key; }
121123
void dump(llvm::raw_ostream &out) const;
@@ -157,10 +159,12 @@ class PropertyBag {
157159
llvm::TinyPtrVector<const ProtocolDecl *>
158160
getConformsToExcludingSuperclassConformances() const;
159161

160-
MutableTerm getPrefixAfterStrippingKey(const MutableTerm &lookupTerm) const;
161-
162162
AssociatedTypeDecl *getAssociatedType(Identifier name);
163163

164+
Symbol concretelySimplifySubstitution(const MutableTerm &mutTerm,
165+
RewriteContext &ctx,
166+
RewritePath *path) const;
167+
164168
void verify(const RewriteSystem &system) const;
165169
};
166170

@@ -320,12 +324,6 @@ class PropertyMap {
320324
RequirementKind requirementKind,
321325
Symbol concreteConformanceSymbol) const;
322326

323-
Optional<unsigned> concretelySimplifySubstitutions(Term baseTerm,
324-
Symbol symbol,
325-
RewritePath *path) const;
326-
327-
void concretelySimplifyLeftHandSideSubstitutions() const;
328-
329327
void verify() const;
330328
};
331329

lib/AST/RequirementMachine/RewriteSystem.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,10 @@ class RewriteSystem final {
318318

319319
bool simplifySubstitutions(Symbol &symbol, RewritePath *path=nullptr) const;
320320

321+
Optional<unsigned>
322+
simplifySubstitutions(Term baseTerm, Symbol symbol, const PropertyMap *map,
323+
RewritePath *path);
324+
321325
//////////////////////////////////////////////////////////////////////////////
322326
///
323327
/// Completion
@@ -337,6 +341,8 @@ class RewriteSystem final {
337341

338342
void simplifyLeftHandSideSubstitutions();
339343

344+
void simplifyLeftHandSideSubstitutions(const PropertyMap *map);
345+
340346
enum ValidityPolicy {
341347
AllowInvalidRequirements,
342348
DisallowInvalidRequirements

lib/AST/RequirementMachine/SimplifySubstitutions.cpp

Lines changed: 29 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -128,17 +128,21 @@ void RewriteSystem::simplifyLeftHandSideSubstitutions() {
128128
}
129129
}
130130

131-
/// Similar to RewriteSystem::simplifySubstitutions(), but also replaces type
132-
/// parameters with concrete types and builds a type difference describing
133-
/// the transformation.
131+
/// Simplify terms appearing in the substitutions of the last symbol of \p term,
132+
/// which must be a superclass or concrete type symbol.
133+
///
134+
/// Additionally, if \p map is non-null, any terms which become concrete types
135+
/// will cause the corresponding generic parameter in the concrete type symbol
136+
/// to be replaced.
134137
///
135138
/// Returns None if the concrete type symbol cannot be simplified further.
136139
///
137140
/// Otherwise returns an index which can be passed to
138141
/// RewriteSystem::getTypeDifference().
139142
Optional<unsigned>
140-
PropertyMap::concretelySimplifySubstitutions(Term baseTerm, Symbol symbol,
141-
RewritePath *path) const {
143+
RewriteSystem::simplifySubstitutions(Term baseTerm, Symbol symbol,
144+
const PropertyMap *map,
145+
RewritePath *path) {
142146
assert(symbol.hasSubstitutions());
143147

144148
// Fast path if the type is fully concrete.
@@ -181,39 +185,19 @@ PropertyMap::concretelySimplifySubstitutions(Term baseTerm, Symbol symbol,
181185
// has to iterate until fixed point anyway.
182186
//
183187
// This should be rare in practice.
184-
if (System.simplify(mutTerm, path)) {
188+
if (simplify(mutTerm, path)) {
185189
// Record a mapping from this substitution to the simplified term.
186190
sameTypes.emplace_back(index, Term::get(mutTerm, Context));
187-
} else {
188-
auto *props = lookUpProperties(mutTerm);
189191

190-
if (props && props->ConcreteType) {
191-
// The property map entry might apply to a suffix of the substitution
192-
// term, so prepend the appropriate prefix to its own substitutions.
193-
auto prefix = props->getPrefixAfterStrippingKey(mutTerm);
194-
auto concreteSymbol =
195-
props->ConcreteType->prependPrefixToConcreteSubstitutions(
196-
prefix, Context);
192+
} else if (map) {
193+
auto *props = map->lookUpProperties(mutTerm);
194+
195+
if (props && props->isConcreteType()) {
196+
auto concreteSymbol = props->concretelySimplifySubstitution(
197+
mutTerm, Context, path);
197198

198199
// Record a mapping from this substitution to the concrete type.
199200
concreteTypes.emplace_back(index, concreteSymbol);
200-
201-
// If U.V is the substitution term and V is the property map key,
202-
// apply the rewrite step U.(V => V.[concrete: C]) followed by
203-
// prepending the prefix U to each substitution in the concrete type
204-
// symbol if |U| > 0.
205-
if (path) {
206-
path->add(RewriteStep::forRewriteRule(/*startOffset=*/prefix.size(),
207-
/*endOffset=*/0,
208-
/*ruleID=*/*props->ConcreteTypeRule,
209-
/*inverse=*/true));
210-
211-
if (!prefix.empty()) {
212-
path->add(RewriteStep::forPrefixSubstitutions(/*length=*/prefix.size(),
213-
/*endOffset=*/0,
214-
/*inverse=*/false));
215-
}
216-
}
217201
}
218202
}
219203
}
@@ -240,7 +224,7 @@ PropertyMap::concretelySimplifySubstitutions(Term baseTerm, Symbol symbol,
240224
Context);
241225
assert(difference.LHS != difference.RHS);
242226

243-
unsigned differenceID = System.recordTypeDifference(difference);
227+
unsigned differenceID = recordTypeDifference(difference);
244228

245229
// All simplified substitutions are now on the primary stack. Collect them to
246230
// produce the new term.
@@ -252,9 +236,15 @@ PropertyMap::concretelySimplifySubstitutions(Term baseTerm, Symbol symbol,
252236
return differenceID;
253237
}
254238

255-
void PropertyMap::concretelySimplifyLeftHandSideSubstitutions() const {
256-
for (unsigned ruleID = 0, e = System.getRules().size(); ruleID < e; ++ruleID) {
257-
auto &rule = System.getRule(ruleID);
239+
/// Simplify substitution terms in superclass, concrete type and concrete
240+
/// conformance symbols.
241+
///
242+
/// During completion, \p map will be null. After completion, the property map
243+
/// is built, and a final simplification pass is performed with \p map set to
244+
/// the new property map.
245+
void RewriteSystem::simplifyLeftHandSideSubstitutions(const PropertyMap *map) {
246+
for (unsigned ruleID = 0, e = Rules.size(); ruleID < e; ++ruleID) {
247+
auto &rule = getRule(ruleID);
258248
if (rule.isLHSSimplified() ||
259249
rule.isRHSSimplified() ||
260250
rule.isSubstitutionSimplified())
@@ -268,14 +258,13 @@ void PropertyMap::concretelySimplifyLeftHandSideSubstitutions() const {
268258

269259
RewritePath path;
270260

271-
auto differenceID = concretelySimplifySubstitutions(
272-
rule.getRHS(), symbol, &path);
261+
auto differenceID = simplifySubstitutions(rule.getRHS(), symbol, map, &path);
273262
if (!differenceID)
274263
continue;
275264

276265
rule.markSubstitutionSimplified();
277266

278-
auto difference = System.getTypeDifference(*differenceID);
267+
auto difference = getTypeDifference(*differenceID);
279268
assert(difference.LHS == symbol);
280269

281270
// If the original rule is (T.[concrete: C] => T) and [concrete: C'] is
@@ -295,6 +284,6 @@ void PropertyMap::concretelySimplifyLeftHandSideSubstitutions() const {
295284
MutableTerm lhs(rhs);
296285
lhs.add(difference.RHS);
297286

298-
System.addRule(lhs, rhs, &path);
287+
addRule(lhs, rhs, &path);
299288
}
300289
}

0 commit comments

Comments
 (0)