Skip to content

Commit a5a162a

Browse files
committed
[GSB] Install basic recursion checking.
Recursive protocol conformances still aren't functional, so reinstate some checking for recursive protocol conformances. It doesn't catch everything that the previous version did---but we don't crash on such cases anymore, either.
1 parent 17846e2 commit a5a162a

File tree

2 files changed

+22
-20
lines changed

2 files changed

+22
-20
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2355,21 +2355,6 @@ ConstraintResult GenericSignatureBuilder::addConformanceRequirement(
23552355
if (!PAT->addConformance(Proto, Source, *this))
23562356
return ConstraintResult::Resolved;
23572357

2358-
#if false
2359-
// FIXME: Ad hoc recursion breaking.
2360-
if (Visited.count(Proto)) {
2361-
markPotentialArchetypeRecursive(PAT, Proto, Source);
2362-
return ConstraintResult::Conflicting;
2363-
}
2364-
2365-
bool inserted = Visited.insert(Proto).second;
2366-
assert(inserted);
2367-
(void) inserted;
2368-
SWIFT_DEFER {
2369-
Visited.erase(Proto);
2370-
};
2371-
#endif
2372-
23732358
auto concreteSelf = PAT->getDependentType({}, /*allowUnresolved=*/true);
23742359
auto protocolSubMap = SubstitutionMap::getProtocolSubstitutions(
23752360
Proto, concreteSelf, ProtocolConformanceRef(Proto));
@@ -3091,6 +3076,23 @@ ConstraintResult GenericSignatureBuilder::addInheritedRequirements(
30913076
getFloatingSource(typeRepr, /*forInferred=*/true));
30923077
}
30933078

3079+
// Check for direct recursion.
3080+
if (auto assocType = dyn_cast<AssociatedTypeDecl>(decl)) {
3081+
auto proto = assocType->getProtocol();
3082+
if (auto inheritedProto = inheritedType->getAs<ProtocolType>()) {
3083+
if (inheritedProto->getDecl() == proto ||
3084+
inheritedProto->getDecl()->inheritsFrom(proto)) {
3085+
auto source = getFloatingSource(typeRepr, /*forInferred=*/false);
3086+
if (auto resolved = resolve(type, source)) {
3087+
if (auto pa = resolved->getPotentialArchetype()) {
3088+
markPotentialArchetypeRecursive(pa, proto, source.getSource(pa));
3089+
return ConstraintResult::Conflicting;
3090+
}
3091+
}
3092+
}
3093+
}
3094+
}
3095+
30943096
return addTypeRequirement(type, inheritedType,
30953097
getFloatingSource(typeRepr,
30963098
/*forInferred=*/false),

test/decl/protocol/recursive_requirement.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ struct Y2 : P2 {
4141
}
4242

4343
func f<T : P2>(_ z: T) {
44-
_ = X2<T.A>()
44+
_ = X2<T.A>() // expected-error{{type 'T.A' does not conform to protocol 'P2'}}
4545
}
4646

4747
// -----
@@ -69,11 +69,11 @@ f2(Y3())
6969
// -----
7070

7171
protocol Alpha {
72-
associatedtype Beta: Gamma // expected-error{{type may not reference itself as a requirement}}
72+
associatedtype Beta: Gamma
7373
}
7474

7575
protocol Gamma {
76-
associatedtype Delta: Alpha // expected-error{{type may not reference itself as a requirement}}
76+
associatedtype Delta: Alpha
7777
}
7878

7979
// FIXME: Redundancy diagnostics are odd here.
@@ -111,7 +111,7 @@ protocol AsExistentialAssocTypeAgainB {
111111

112112
// SR-547
113113
protocol A {
114-
associatedtype B1: B // expected-error{{type may not reference itself as a requirement}}
114+
associatedtype B1: B
115115
associatedtype C1: C
116116

117117
mutating func addObserver(_ observer: B1, forProperty: C1)
@@ -122,7 +122,7 @@ protocol C {
122122
}
123123

124124
protocol B {
125-
associatedtype BA: A // expected-error{{type may not reference itself as a requirement}}
125+
associatedtype BA: A
126126
associatedtype BC: C
127127

128128
func observeChangeOfProperty(_ property: BC, observable: BA)

0 commit comments

Comments
 (0)