Skip to content

Commit 5b233d8

Browse files
authored
Merge pull request #3747 from CodaFi/circumnavigating-a-graph-in-eighty-days
[Sema] Shepherd @manavgabhawala's changes to circular protocol diagnostics
2 parents 3d1ff4d + f8fa87a commit 5b233d8

File tree

3 files changed

+20
-28
lines changed

3 files changed

+20
-28
lines changed

lib/AST/ConformanceLookupTable.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ bool ConformanceLookupTable::addProtocol(NominalTypeDecl *nominal,
445445

446446
// If this entry is synthesized or implied, scan to determine
447447
// whether there are any explicit better conformances that make this
448-
// conformance trivially superseded (and, therefore, no worth
448+
// conformance trivially superseded (and, therefore, not worth
449449
// recording).
450450
auto &conformanceEntries = Conformances[protocol];
451451
if (kind == ConformanceEntryKind::Implied ||
@@ -458,7 +458,9 @@ bool ConformanceLookupTable::addProtocol(NominalTypeDecl *nominal,
458458

459459
case ConformanceEntryKind::Implied:
460460
// An implied conformance is better than a synthesized one.
461-
if (kind == ConformanceEntryKind::Synthesized)
461+
// Ignore implied circular protocol inheritance
462+
if (kind == ConformanceEntryKind::Synthesized ||
463+
existingEntry->getProtocol() == protocol)
462464
return false;
463465
break;
464466

lib/Sema/ITCDecl.cpp

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ void IterativeTypeChecker::processInheritedProtocols(
222222
// FIXME: Technically, we only need very basic name binding.
223223
auto inheritedClause = protocol->getInherited();
224224
bool anyDependencies = false;
225+
bool diagnosedCircularity = false;
225226
llvm::SmallSetVector<ProtocolDecl *, 4> allProtocols;
226227
for (unsigned i = 0, n = inheritedClause.size(); i != n; ++i) {
227228
TypeLoc &inherited = inheritedClause[i];
@@ -237,43 +238,32 @@ void IterativeTypeChecker::processInheritedProtocols(
237238
// FIXME: We'd prefer to keep what the user wrote here.
238239
SmallVector<ProtocolDecl *, 4> protocols;
239240
if (inherited.getType()->isExistentialType(protocols)) {
240-
allProtocols.insert(protocols.begin(), protocols.end());
241-
continue;
241+
for (auto inheritedProtocol: protocols) {
242+
if (inheritedProtocol == protocol ||
243+
inheritedProtocol->inheritsFrom(protocol)) {
244+
if (!diagnosedCircularity &&
245+
!protocol->isInheritedProtocolsValid()) {
246+
diagnose(protocol,
247+
diag::circular_protocol_def, protocol->getName().str())
248+
.fixItRemove(inherited.getSourceRange());
249+
diagnosedCircularity = true;
250+
}
251+
continue;
252+
}
253+
allProtocols.insert(inheritedProtocol);
254+
}
242255
}
243256
}
244257

245258
// If we enumerated any dependencies, we can't complete this request.
246259
if (anyDependencies)
247260
return;
248261

249-
// Check for circular inheritance.
250-
// FIXME: The diagnostics here should be improved... and this should probably
251-
// be handled by the normal cycle detection.
252-
bool diagnosedCircularity = false;
253-
for (unsigned i = 0, n = allProtocols.size(); i != n; /*in loop*/) {
254-
if (allProtocols[i] == protocol ||
255-
allProtocols[i]->inheritsFrom(protocol)) {
256-
if (!diagnosedCircularity &&
257-
!protocol->isInheritedProtocolsValid()) {
258-
diagnose(protocol,
259-
diag::circular_protocol_def, protocol->getName().str());
260-
diagnosedCircularity = true;
261-
}
262-
263-
allProtocols.remove(allProtocols[i]);
264-
--n;
265-
continue;
266-
}
267-
268-
++i;
269-
}
270-
271262
// FIXME: Hack to deal with recursion elsewhere.
272263
// We recurse through DeclContext::getLocalProtocols() -- this should be
273264
// redone to use the IterativeDeclChecker also.
274265
if (protocol->isInheritedProtocolsValid())
275266
return;
276-
277267
protocol->setInheritedProtocols(getASTContext().AllocateCopy(allProtocols));
278268
}
279269

validation-test/compiler_crashers/10659-swift-printingdiagnosticconsumer-handlediagnostic.timeout.swift renamed to validation-test/compiler_crashers_fixed/10659-swift-printingdiagnosticconsumer-handlediagnostic.timeout.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// See http://swift.org/LICENSE.txt for license information
66
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

8-
// RUN: not --crash %target-swift-frontend %s -parse
8+
// RUN: not %target-swift-frontend %s -parse
99
// REQUIRES: asserts
1010
protocol c:A
1111
protocol A:d

0 commit comments

Comments
 (0)