Skip to content

Commit 658ba01

Browse files
committed
RequirementMachine: Redo concrete contraction after splitting concrete equivalence classes
This fixes an edge case where we start with the following requirements: - U : P - T : P - T.[P]A == C - T == G<T.[P]A> - U.[P]A == T.[P]A and end up with the following set of minimal rules (where the type witness for [P]A in the conformance G<C> : P is C): - U.[P] => U - U.[P:A] => T.[P:A] - T.[concrete: G<C>] => T - T.[concrete: G<C> : P] => T Since U.[P]A and T.[P]A are concrete, we split the abstract same-type requirement into two requirements, and re-run minimization: - U : P - T.[P]A == C - U.[P]A == C - T == G<C> The concrete conformance rule T.[concrete: G<C> : P] => T does not correspond to a requirement, so it was simply dropped, and the above rules violate post-contraction invariants; T.[P]A is not a valid type parameter because there is no conformance requirement T : P in the minimized signature. We can fix this by re-running concrete contraction after splitting concrete equivalence classes. After contraction, the above requirements turn into - U : P - C == C - U.[P]A == C - T == G<C> Which correctly minimizes to - U : P - U.[P]A == C - T == G<C> Both concrete contraction and concrete equivalence classes are hacks, and we should think of a way to directly express the transformations they perform with the rewrite system. Fixes #61192.
1 parent 6bd817c commit 658ba01

File tree

2 files changed

+57
-38
lines changed

2 files changed

+57
-38
lines changed

lib/AST/RequirementMachine/RequirementMachineRequests.cpp

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -320,20 +320,6 @@ RequirementSignatureRequest::evaluate(Evaluator &evaluator,
320320
requirements.push_back(req);
321321
for (auto req : proto->getTypeAliasRequirements())
322322
requirements.push_back({req, SourceLoc(), /*inferred=*/false});
323-
324-
// Preprocess requirements to eliminate conformances on type parameters
325-
// which are made concrete.
326-
if (ctx.LangOpts.EnableRequirementMachineConcreteContraction) {
327-
SmallVector<StructuralRequirement, 4> contractedRequirements;
328-
329-
bool debug = rewriteCtx.getDebugOptions()
330-
.contains(DebugFlags::ConcreteContraction);
331-
332-
if (performConcreteContraction(requirements, contractedRequirements,
333-
errors, debug)) {
334-
std::swap(contractedRequirements, requirements);
335-
}
336-
}
337323
}
338324

339325
if (rewriteCtx.getDebugOptions().contains(DebugFlags::Timers)) {
@@ -356,6 +342,24 @@ RequirementSignatureRequest::evaluate(Evaluator &evaluator,
356342

357343
unsigned attempt = 0;
358344
for (;;) {
345+
for (const auto *proto : component) {
346+
auto &requirements = protos[proto];
347+
348+
// Preprocess requirements to eliminate conformances on type parameters
349+
// which are made concrete.
350+
if (ctx.LangOpts.EnableRequirementMachineConcreteContraction) {
351+
SmallVector<StructuralRequirement, 4> contractedRequirements;
352+
353+
bool debug = rewriteCtx.getDebugOptions()
354+
.contains(DebugFlags::ConcreteContraction);
355+
356+
if (performConcreteContraction(requirements, contractedRequirements,
357+
errors, debug)) {
358+
std::swap(contractedRequirements, requirements);
359+
}
360+
}
361+
}
362+
359363
// Heap-allocate the requirement machine to save stack space.
360364
std::unique_ptr<RequirementMachine> machine(new RequirementMachine(
361365
rewriteCtx));
@@ -660,20 +664,20 @@ AbstractGenericSignatureRequest::evaluate(
660664
llvm::dbgs() << "\n";
661665
}
662666

663-
// Preprocess requirements to eliminate conformances on generic parameters
664-
// which are made concrete.
665-
if (ctx.LangOpts.EnableRequirementMachineConcreteContraction) {
666-
SmallVector<StructuralRequirement, 4> contractedRequirements;
667-
bool debug = rewriteCtx.getDebugOptions()
668-
.contains(DebugFlags::ConcreteContraction);
669-
if (performConcreteContraction(requirements, contractedRequirements,
670-
errors, debug)) {
671-
std::swap(contractedRequirements, requirements);
672-
}
673-
}
674-
675667
unsigned attempt = 0;
676668
for (;;) {
669+
// Preprocess requirements to eliminate conformances on generic parameters
670+
// which are made concrete.
671+
if (ctx.LangOpts.EnableRequirementMachineConcreteContraction) {
672+
SmallVector<StructuralRequirement, 4> contractedRequirements;
673+
bool debug = rewriteCtx.getDebugOptions()
674+
.contains(DebugFlags::ConcreteContraction);
675+
if (performConcreteContraction(requirements, contractedRequirements,
676+
errors, debug)) {
677+
std::swap(contractedRequirements, requirements);
678+
}
679+
}
680+
677681
// Heap-allocate the requirement machine to save stack space.
678682
std::unique_ptr<RequirementMachine> machine(new RequirementMachine(
679683
rewriteCtx));
@@ -855,20 +859,20 @@ InferredGenericSignatureRequest::evaluate(
855859
llvm::dbgs() << "\n";
856860
}
857861

858-
// Preprocess requirements to eliminate conformances on generic parameters
859-
// which are made concrete.
860-
if (ctx.LangOpts.EnableRequirementMachineConcreteContraction) {
861-
SmallVector<StructuralRequirement, 4> contractedRequirements;
862-
bool debug = rewriteCtx.getDebugOptions()
863-
.contains(DebugFlags::ConcreteContraction);
864-
if (performConcreteContraction(requirements, contractedRequirements,
865-
errors, debug)) {
866-
std::swap(contractedRequirements, requirements);
867-
}
868-
}
869-
870862
unsigned attempt = 0;
871863
for (;;) {
864+
// Preprocess requirements to eliminate conformances on generic parameters
865+
// which are made concrete.
866+
if (ctx.LangOpts.EnableRequirementMachineConcreteContraction) {
867+
SmallVector<StructuralRequirement, 4> contractedRequirements;
868+
bool debug = rewriteCtx.getDebugOptions()
869+
.contains(DebugFlags::ConcreteContraction);
870+
if (performConcreteContraction(requirements, contractedRequirements,
871+
errors, debug)) {
872+
std::swap(contractedRequirements, requirements);
873+
}
874+
}
875+
872876
// Heap-allocate the requirement machine to save stack space.
873877
std::unique_ptr<RequirementMachine> machine(new RequirementMachine(
874878
rewriteCtx));

test/Generics/issue-61192.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-swift-frontend -typecheck -verify %s -debug-generic-signatures -warn-redundant-requirements 2>&1 | %FileCheck %s
2+
3+
struct C {}
4+
5+
protocol P {
6+
associatedtype A
7+
}
8+
9+
struct G<A>: P {}
10+
11+
struct Body<T: P> where T.A == C {
12+
// CHECK-LABEL: .init(_:)@
13+
// CHECK-NEXT: <T, U where T == G<C>, U : P, U.[P]A == C>
14+
init<U: P>(_: U) where T == G<T.A>, U.A == T.A {}
15+
}

0 commit comments

Comments
 (0)