Skip to content

Commit

Permalink
Sema: more robust diagnostic for circular inheritance
Browse files Browse the repository at this point in the history
The code would generate different diagnosics depending on
the cycle having length 1 or longer. The length 1 case
was broken if the path had a prefix that wasn't part
of the cycle, eg if we have C : A, A : A and visit C
first.

Swift SVN r28317
  • Loading branch information
slavapestov committed May 8, 2015
1 parent 8bd6b33 commit 74c2cb7
Show file tree
Hide file tree
Showing 8 changed files with 25 additions and 18 deletions.
27 changes: 14 additions & 13 deletions lib/Sema/TypeCheckDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -616,26 +616,27 @@ static void checkCircularity(TypeChecker &tc, T *decl,

case CircularityCheck::Checking: {
// We're already checking this protocol, which means we have a cycle.

// The type directly references itself.
if (path.size() == 1) {
tc.diagnose((*path.begin())->getLoc(),

// The beginning of the path might not be part of the cycle, so find
// where the cycle starts.
auto cycleStart = path.end() - 1;
while (*cycleStart != decl) {
assert(cycleStart != path.begin() && "Missing cycle start?");
--cycleStart;
}

// If the path length is 1 the type directly references itself.
if (path.end() - cycleStart == 1) {
tc.diagnose(path.back()->getLoc(),
circularDiag,
(*path.begin())->getName().str());
path.back()->getName().str());

decl->setInvalid();
decl->overwriteType(ErrorType::get(tc.Context));
breakInheritanceCycle(decl);
break;
}

// Find the beginning of the cycle within the full path.
auto cycleStart = path.end()-2;
while (*cycleStart != decl) {
assert(cycleStart != path.begin() && "Missing cycle start?");
--cycleStart;
}

// Form the textual path illustrating the cycle.
llvm::SmallString<128> pathStr;
for (auto i = cycleStart, iEnd = path.end(); i != iEnd; ++i) {
Expand Down
3 changes: 3 additions & 0 deletions test/decl/class/circular_inheritance.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ class A : C { } // expected-note{{class 'A' declared here}}

class TrivialCycle : TrivialCycle {} // expected-error{{circular class inheritance TrivialCycle}}
protocol P : P {} // expected-error{{circular protocol inheritance P}}

class Isomorphism : Automorphism { }
class Automorphism : Automorphism { } // expected-error{{circular class inheritance Automorphism}}
3 changes: 3 additions & 0 deletions test/decl/protocol/protocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ protocol CircleMiddle : CircleStart { func circle_middle() } // expected-error{{
protocol CircleStart : CircleEnd { func circle_start() } // expected-note{{protocol 'CircleStart' declared here}}
protocol CircleEnd : CircleMiddle { func circle_end()} // expected-note{{protocol 'CircleEnd' declared here}}

protocol CircleEntry : CircleTrivial { }
protocol CircleTrivial : CircleTrivial { } // expected-error{{circular protocol inheritance CircleTrivial}}

struct Circle {
func circle_start() {}
func circle_middle() {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: not --crash %target-swift-frontend %s -parse
// RUN: not %target-swift-frontend %s -parse

// Distributed under the terms of the MIT license
// Test case submitted to project by https://github.com/practicalswift (practicalswift)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: not --crash %target-swift-frontend %s -parse
// RUN: not %target-swift-frontend %s -parse

// Distributed under the terms of the MIT license
// Test case submitted to project by https://github.com/practicalswift (practicalswift)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: not --crash %target-swift-frontend %s -parse
// RUN: not %target-swift-frontend %s -parse

// Distributed under the terms of the MIT license
// Test case submitted to project by https://github.com/practicalswift (practicalswift)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: not --crash %target-swift-frontend %s -parse
// RUN: not %target-swift-frontend %s -parse

// Distributed under the terms of the MIT license
// Test case submitted to project by https://github.com/practicalswift (practicalswift)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: not --crash %target-swift-frontend %s -parse
// RUN: not %target-swift-frontend %s -parse

// Distributed under the terms of the MIT license
// Test case submitted to project by https://github.com/practicalswift (practicalswift)
Expand Down

0 comments on commit 74c2cb7

Please sign in to comment.