Skip to content

Commit f3b8bed

Browse files
committed
RequirementMachine: Fix assertion failure when conflicting rules are also redundant
We can end up with two redundant concrete type rules on the same term, but we would crash in homotopy reduction because the rules were incomparable due to the concrete type symbol at the end. If one of them is conflicting though, we don't really care about the homotopy reduction order, so skip the check if the other rule was already marked conflicting.
1 parent 7a5758e commit f3b8bed

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

lib/AST/RequirementMachine/HomotopyReduction.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,9 +386,13 @@ findRuleToDelete(llvm::function_ref<bool(unsigned)> isRedundantRuleFn,
386386

387387
const auto &otherRule = getRule(found->second);
388388

389-
// Prefer to delete "less canonical" rules.
390-
if (rule.compare(otherRule, Context) > 0)
389+
// If the new rule is conflicting, don't compare the rules at all
390+
// and prefer to delete the new rule. Otherwise, prefer to delete
391+
// the less canonical of the two rules.
392+
if (rule.isConflicting() ||
393+
rule.compare(otherRule, Context) > 0) {
391394
found = pair;
395+
}
392396
}
393397

394398
if (!found)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %target-typecheck-verify-swift -debug-generic-signatures -requirement-machine-protocol-signatures=verify
2+
3+
protocol P1 {
4+
associatedtype T where T == Int
5+
}
6+
7+
protocol P2 {
8+
associatedtype T where T == String
9+
}
10+
11+
protocol P3 {
12+
associatedtype T where T == Float
13+
}
14+
15+
// We end up with two redundant rules:
16+
//
17+
// [P4:T].[P1:T].[concrete: String]
18+
// [P4:T].[P1:T].[concrete: Float]
19+
//
20+
// These rules are unordered with respect to each other because concrete type
21+
// symbols are incomparable, but they conflict so we should not compare them;
22+
// just make sure we don't crash.
23+
24+
// CHECK-LABEL: concrete_conflict_in_protocol.(file).P4@
25+
// CHECK-LABEL: Requirement signature: <Self where Self.[P4]T : P1, Self.[P4]T : P2, Self.[P4]T : P3>
26+
27+
protocol P4 {
28+
associatedtype T : P1 & P2 & P3
29+
// expected-note@-1 2{{same-type constraint 'Self.T.T' == 'Int' implied here}}
30+
// expected-error@-2 {{'Self.T.T' cannot be equal to both 'String' and 'Int'}}
31+
// expected-error@-3 {{'Self.T.T' cannot be equal to both 'Float' and 'Int'}}
32+
}

0 commit comments

Comments
 (0)