Skip to content

Commit a9fe0a6

Browse files
committed
Improve redeclaration error for implicit inits
1 parent bf909ca commit a9fe0a6

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,9 @@ ERROR(reserved_member_name,none,
667667
" 'foo.%1' expression", (DeclName, StringRef))
668668

669669
ERROR(invalid_redecl,none,"invalid redeclaration of %0", (DeclName))
670+
ERROR(invalid_redecl_init,none,
671+
"invalid redeclaration of %select{synthesized|"
672+
"synthesized memberwise|inherited}1 %0", (DeclName, unsigned))
670673
WARNING(invalid_redecl_swift5_warning,none,
671674
"redeclaration of %0 is deprecated and will be an error in Swift 5",
672675
(DeclName))

lib/Sema/TypeCheckDecl.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -914,8 +914,23 @@ static void checkRedeclaration(TypeChecker &tc, ValueDecl *current) {
914914
current->getFullName());
915915
tc.diagnose(other, diag::invalid_redecl_prev, other->getFullName());
916916
} else {
917-
tc.diagnose(current, diag::invalid_redecl, current->getFullName());
918-
tc.diagnose(other, diag::invalid_redecl_prev, other->getFullName());
917+
const auto *otherInit = dyn_cast<ConstructorDecl>(other);
918+
// Provide a better description for implicit initializers.
919+
if (otherInit && otherInit->isImplicit()) {
920+
enum {
921+
Synthetic, SyntheticMemberwise, Inherited
922+
} kind = Synthetic;
923+
if (otherInit->isMemberwiseInitializer())
924+
kind = SyntheticMemberwise;
925+
else if (otherInit->getOverriddenDecl())
926+
kind = Inherited;
927+
928+
tc.diagnose(current, diag::invalid_redecl_init,
929+
current->getFullName(), kind);
930+
} else {
931+
tc.diagnose(current, diag::invalid_redecl, current->getFullName());
932+
tc.diagnose(other, diag::invalid_redecl_prev, other->getFullName());
933+
}
919934
markInvalid();
920935
}
921936

test/decl/init/basic_init.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,26 @@ class C {
1313
typealias t = t // expected-error {{type alias 't' references itself}}
1414
// expected-note@-1{{type declared here}}
1515

16+
extension Foo {
17+
convenience init() {} // expected-error{{invalid redeclaration of synthesized 'init()'}}
18+
}
1619

20+
class InitClass {
21+
init(arg: Bool) {} // expected-note{{add '@objc' to make this declaration overridable}}
22+
}
23+
class InitSubclass: InitClass {}
24+
extension InitSubclass {
25+
convenience init(arg: Bool) {}
26+
// expected-error@-1{{invalid redeclaration of inherited 'init(arg:)'}}
27+
// expected-error@-2{{overriding non-@objc declarations from extensions is not supported}}
28+
}
1729

30+
struct InitStruct {
31+
let foo: Int
32+
}
33+
extension InitStruct {
34+
init(foo: Int) {} // expected-error{{invalid redeclaration of synthesized memberwise 'init(foo:)'}}
35+
}
1836

1937
// <rdar://problem/17564699> QoI: Structs should get convenience initializers
2038
struct MyStruct {

0 commit comments

Comments
 (0)