Skip to content

Commit 762bf1e

Browse files
committed
RequirementMachine: Refine 'derived via protocol typealias' criterion
Preserves concrete type rules on associated types that were derived from rules indirectly formed from protocol typealias rules. That is, if you have a pair of rules in another minimization domain: [P].A.[concrete: C] => [P].A [Q:T].[P] => [Q:T] Then completion will introduce a new rule: [Q:T].A.[concrete: C] => [Q:T].A Since this rule is outside of our minimization domain, we don't record a rewrite loop for it, and it will never become redundant. Now if we have a rule in our own minimization domain: T.[Q:T].A => T.[Q:U] Then we get a new rule: T.[Q:U].[concrete: C] => T.[Q:U] Make sure we keep this rule around on account of it being derived from ([Q:T].A.[concrete: C] => [Q:T].A).
1 parent 3576318 commit 762bf1e

File tree

4 files changed

+28
-4
lines changed

4 files changed

+28
-4
lines changed

lib/AST/RequirementMachine/HomotopyReduction.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,7 @@ void RewriteLoop::recompute(const RewriteSystem &system) {
8383
Useful |= (!step.isInContext() && !evaluator.isInContext());
8484

8585
const auto &rule = system.getRule(step.getRuleID());
86-
if (rule.isProtocolTypeAliasRule() &&
87-
rule.getLHS().size() == 3)
86+
if (rule.isDerivedFromConcreteProtocolTypeAliasRule())
8887
HasConcreteTypeAliasRule = 1;
8988

9089
break;

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,29 @@ Optional<Identifier> Rule::isProtocolTypeAliasRule() const {
193193
return LHS[1].getName();
194194
}
195195

196+
/// A rule was derived from a concrete protocol typealias if it
197+
/// takes the following form:
198+
///
199+
/// T.A.[concrete: C] => T.A
200+
///
201+
/// Where the prefix term T does not contain any name symbols, and
202+
/// A is a name symbol.
203+
bool Rule::isDerivedFromConcreteProtocolTypeAliasRule() const {
204+
auto optSymbol = isPropertyRule();
205+
if (!optSymbol || optSymbol->getKind() != Symbol::Kind::ConcreteType)
206+
return false;
207+
208+
for (unsigned i = 0, e = RHS.size() - 1; i < e; ++i) {
209+
if (RHS[i].getKind() == Symbol::Kind::Name)
210+
return false;
211+
}
212+
213+
if (RHS.back().getKind() != Symbol::Kind::Name)
214+
return false;
215+
216+
return true;
217+
}
218+
196219
/// Returns the length of the left hand side.
197220
unsigned Rule::getDepth() const {
198221
auto result = LHS.size();

lib/AST/RequirementMachine/RewriteSystem.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ class Rule final {
160160

161161
Optional<Identifier> isProtocolTypeAliasRule() const;
162162

163+
bool isDerivedFromConcreteProtocolTypeAliasRule() const;
164+
163165
void markLHSSimplified() {
164166
assert(!LHSSimplified);
165167
LHSSimplified = true;

test/Generics/protocol_type_aliases.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=verify
2-
// RUN: not %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=verify > %t.dump 2>&1
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
2+
// RUN: not %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify > %t.dump 2>&1
33

44

55
func sameType<T>(_: T.Type, _: T.Type) {}

0 commit comments

Comments
 (0)