Skip to content

Commit a259844

Browse files
committed
RequirementMachine: Record those rewrite loops involving protocol typealiases
1 parent 5cfee4e commit a259844

File tree

3 files changed

+32
-6
lines changed

3 files changed

+32
-6
lines changed

lib/AST/RequirementMachine/HomotopyReduction.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,23 +65,30 @@
6565
using namespace swift;
6666
using namespace rewriting;
6767

68-
/// Recompute Useful, RulesInEmptyContext, ProjectionCount and DecomposeCount
69-
/// if needed.
68+
/// Recompute various cached values if needed.
7069
void RewriteLoop::recompute(const RewriteSystem &system) {
7170
if (!Dirty)
7271
return;
7372
Dirty = 0;
7473

74+
Useful = 0;
7575
ProjectionCount = 0;
7676
DecomposeCount = 0;
77-
Useful = false;
77+
HasConcreteTypeAliasRule = 0;
7878

7979
RewritePathEvaluator evaluator(Basepoint);
8080
for (auto step : Path) {
8181
switch (step.Kind) {
82-
case RewriteStep::Rule:
82+
case RewriteStep::Rule: {
8383
Useful |= (!step.isInContext() && !evaluator.isInContext());
84+
85+
const auto &rule = system.getRule(step.getRuleID());
86+
if (rule.isProtocolTypeAliasRule() &&
87+
rule.getLHS().size() == 3)
88+
HasConcreteTypeAliasRule = 1;
89+
8490
break;
91+
}
8592

8693
case RewriteStep::LeftConcreteProjection:
8794
++ProjectionCount;
@@ -130,6 +137,14 @@ unsigned RewriteLoop::getDecomposeCount(
130137
return DecomposeCount;
131138
}
132139

140+
/// Returns true if the loop contains at least one concrete protocol typealias rule,
141+
/// which have the form ([P].A.[concrete: C] => [P].A).
142+
bool RewriteLoop::hasConcreteTypeAliasRule(
143+
const RewriteSystem &system) const {
144+
const_cast<RewriteLoop *>(this)->recompute(system);
145+
return HasConcreteTypeAliasRule;
146+
}
147+
133148
/// The number of Decompose steps, used by the elimination order to prioritize
134149
/// loops that are not concrete simplifications.
135150
bool RewriteLoop::isUseful(

lib/AST/RequirementMachine/RewriteLoop.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,9 @@ class RewriteLoop {
457457
/// Cached value for getDecomposeCount().
458458
unsigned DecomposeCount : 15;
459459

460+
/// Cached value for hasConcreteTypeAliasRule().
461+
unsigned HasConcreteTypeAliasRule : 1;
462+
460463
/// A useful loop contains at least one rule in empty context, even if that
461464
/// rule appears multiple times or also in non-empty context. The only loops
462465
/// that are elimination candidates contain a rule in empty context *exactly
@@ -478,6 +481,7 @@ class RewriteLoop {
478481
: Basepoint(basepoint), Path(path) {
479482
ProjectionCount = 0;
480483
DecomposeCount = 0;
484+
HasConcreteTypeAliasRule = 0;
481485
Useful = 0;
482486
Deleted = 0;
483487

@@ -509,6 +513,8 @@ class RewriteLoop {
509513

510514
unsigned getDecomposeCount(const RewriteSystem &system) const;
511515

516+
bool hasConcreteTypeAliasRule(const RewriteSystem &system) const;
517+
512518
void findProtocolConformanceRules(
513519
llvm::SmallDenseMap<const ProtocolDecl *,
514520
ProtocolConformanceRules, 2> &result,

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,13 @@ Optional<Identifier> Rule::isProtocolTypeAliasRule() const {
174174
//
175175
// We shouldn't have unresolved symbols on the right hand side;
176176
// they should have been simplified away.
177-
if (RHS.containsUnresolvedSymbols())
178-
return None;
177+
if (RHS.containsUnresolvedSymbols()) {
178+
if (RHS.size() != 2 ||
179+
RHS[0] != LHS[0] ||
180+
RHS[1].getKind() != Symbol::Kind::Name) {
181+
return None;
182+
}
183+
}
179184
} else {
180185
// This is the case where the underlying type is concrete.
181186
assert(LHS.size() == 3);

0 commit comments

Comments
 (0)