Skip to content

Commit 47d02d2

Browse files
authored
Merge pull request #39673 from slavapestov/rqm-type-witness-recursion-hack
RequirementMachine: Tighten up type witness recursion hack
2 parents ca8b660 + 576845d commit 47d02d2

File tree

4 files changed

+53
-6
lines changed

4 files changed

+53
-6
lines changed

lib/AST/RequirementMachine/PropertyMap.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,19 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
910910

911911
MutableTerm constraintType;
912912

913-
if (concreteType == typeWitness &&
913+
auto simplify = [&](CanType t) -> CanType {
914+
return CanType(t.transformRec([&](Type t) -> Optional<Type> {
915+
if (!t->isTypeParameter())
916+
return None;
917+
918+
auto term = getRelativeTermForType(t->getCanonicalType(),
919+
substitutions, Context);
920+
System.simplify(term);
921+
return Context.getTypeForTerm(term, { }, Protos);
922+
}));
923+
};
924+
925+
if (simplify(concreteType) == simplify(typeWitness) &&
914926
requirementKind == RequirementKind::SameType) {
915927
// FIXME: ConcreteTypeInDomainMap should support substitutions so
916928
// that we can remove this.

lib/AST/RequirementMachine/PropertyMap.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ class PropertyBag {
139139
/// Out-of-line methods are documented in PropertyMap.cpp.
140140
class PropertyMap {
141141
RewriteContext &Context;
142+
RewriteSystem &System;
142143
std::vector<PropertyBag *> Entries;
143144
Trie<PropertyBag *, MatchKind::Longest> Trie;
144145

@@ -156,10 +157,11 @@ class PropertyMap {
156157
PropertyMap &operator=(PropertyMap &&) = delete;
157158

158159
public:
159-
explicit PropertyMap(RewriteContext &ctx,
160-
const ProtocolGraph &protos)
161-
: Context(ctx), Protos(protos) {
162-
Debug = ctx.getDebugOptions();
160+
explicit PropertyMap(RewriteSystem &system)
161+
: Context(system.getRewriteContext()),
162+
System(system),
163+
Protos(system.getProtocols()) {
164+
Debug = Context.getDebugOptions();
163165
}
164166

165167
~PropertyMap();

lib/AST/RequirementMachine/RequirementMachine.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ void RequirementMachine::dump(llvm::raw_ostream &out) const {
371371
}
372372

373373
RequirementMachine::RequirementMachine(RewriteContext &ctx)
374-
: Context(ctx), System(ctx), Map(ctx, System.getProtocols()) {
374+
: Context(ctx), System(ctx), Map(System) {
375375
auto &langOpts = ctx.getASTContext().LangOpts;
376376
Dump = langOpts.DumpRequirementMachine;
377377
RequirementMachineStepLimit = langOpts.RequirementMachineStepLimit;

test/Generics/rdar83894546.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
public protocol P1 {
4+
associatedtype A: P1 where A.A == A
5+
}
6+
7+
public protocol P2 {
8+
associatedtype B: P1
9+
associatedtype C: P2
10+
}
11+
12+
public struct G<B : P1> : P2 {
13+
public typealias C = G<B.A>
14+
}
15+
16+
// C == G<B> together with the definition of G<B>.C implies an infinite series
17+
// of rules:
18+
// - C.C == G<B.A>
19+
// - C.C.C == G<B.A.A>
20+
// - C.C.C.C == G<B.A.A.A>
21+
// - ...
22+
//
23+
// This would normally prevent the completion procedure from terminating,
24+
// however A.A == A in protocol P1 means that the right hand sides simplify
25+
// as follows:
26+
//
27+
// - C.C == G<B.A>
28+
// - C.C.C == B<G.A>
29+
// - C.C.C.C == G<B.A>
30+
// - ...
31+
//
32+
// Therefore, the single rule C.C == C.C.C suffices to "tie off" the recursion.
33+
public protocol P3: P2 where C == G<B> {}

0 commit comments

Comments
 (0)