Skip to content

Commit 235ed55

Browse files
committed
[TypeChecker] When formatting witness type for diagnostics don't assume it's always valid
Sometimes witness candidates have error type e.g. when re-declaration checking marks them as `invalid`, so formatting of the diagnostic should account of potential witnesses not having a valid type. Resolves: rdar://problem/41141944
1 parent 7937406 commit 235ed55

File tree

3 files changed

+32
-3
lines changed

3 files changed

+32
-3
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -938,13 +938,13 @@ static void checkRedeclaration(TypeChecker &tc, ValueDecl *current) {
938938
if (!other->isAccessibleFrom(currentDC))
939939
continue;
940940

941-
const auto markInvalid = [&current, &tc]() {
941+
const auto markInvalid = [&current]() {
942942
current->setInvalid();
943943
if (auto *varDecl = dyn_cast<VarDecl>(current))
944944
if (varDecl->hasType())
945-
varDecl->setType(ErrorType::get(tc.Context));
945+
varDecl->setType(ErrorType::get(varDecl->getType()));
946946
if (current->hasInterfaceType())
947-
current->setInterfaceType(ErrorType::get(tc.Context));
947+
current->setInterfaceType(ErrorType::get(current->getInterfaceType()));
948948
};
949949

950950
// Thwart attempts to override the same declaration more than once.

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,6 +1662,17 @@ static Type getTypeForDisplay(ModuleDecl *module, ValueDecl *decl) {
16621662
}
16631663
}
16641664

1665+
// Redeclaration checking might mark a candidate as `invalid` and
1666+
// reset it's type to ErrorType, let's dig out original type to
1667+
// make the diagnostic better.
1668+
if (auto errorType = type->getAs<ErrorType>()) {
1669+
auto originalType = errorType->getOriginalType();
1670+
if (!originalType || !originalType->is<AnyFunctionType>())
1671+
return type;
1672+
1673+
type = originalType;
1674+
}
1675+
16651676
return type->castTo<AnyFunctionType>()->getResult();
16661677
}
16671678

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %s -verify
2+
// REQUIRES: objc_interop
3+
4+
import Foundation
5+
6+
@objc protocol P {
7+
func foo(a arg: Int) // expected-note {{protocol requires function 'foo(a:)' with type '(Int) -> ()'; do you want to add a stub?}}
8+
}
9+
10+
class C : P {
11+
// expected-error@-1 {{type 'C' does not conform to protocol 'P'}}
12+
var foo: Float = 0.75
13+
// expected-note@-1 {{'foo' previously declared here}}
14+
// expected-note@-2 {{candidate is not a function}}
15+
func foo() {}
16+
// expected-error@-1 {{invalid redeclaration of 'foo()'}}
17+
// expected-note@-2 {{candidate has non-matching type '() -> ()'}}
18+
}

0 commit comments

Comments
 (0)