Skip to content

Commit f7a7ee9

Browse files
author
Brian King
committed
Warn if a non dynamic class declaration is overridden in an extension
1 parent 0d0dc79 commit f7a7ee9

File tree

3 files changed

+26
-4
lines changed

3 files changed

+26
-4
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,9 @@ ERROR(override_ownership_mismatch,none,
17031703
"cannot override %select{strong|weak|unowned|unowned(unsafe)}0 property "
17041704
"with %select{strong|weak|unowned|unowned(unsafe)}1 property",
17051705
(/*Ownership*/unsigned, /*Ownership*/unsigned))
1706+
ERROR(override_class_declaration_in_extension,none,
1707+
"cannot override a non-dynamic class declaration from an extension.",
1708+
())
17061709
ERROR(override_throws,none,
17071710
"cannot override non-throwing %select{method|initializer}0 with "
17081711
"throwing %select{method|initializer}0", (bool))

lib/Sema/TypeCheckDecl.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6072,6 +6072,19 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
60726072
new (TC.Context) OverrideAttr(SourceLoc()));
60736073
}
60746074

6075+
// If the overridden method is declared in a Swift Class Declaration,
6076+
// dispatch will use table dispatch. If the override is in an extension
6077+
// warn, since it is not added to the class vtable.
6078+
// FIXME: Only warn if the extension is in another module, and if
6079+
// it is in the same module, update the vtable.
6080+
if (auto baseDecl = dyn_cast<ClassDecl>(base->getDeclContext())) {
6081+
if (baseDecl->hasKnownSwiftImplementation() &&
6082+
!base->isDynamic() &&
6083+
override->getDeclContext()->isExtensionContext()) {
6084+
TC.diagnose(override, diag::override_class_declaration_in_extension);
6085+
TC.diagnose(base, diag::overridden_here);
6086+
}
6087+
}
60756088
// If the overriding declaration is 'throws' but the base is not,
60766089
// complain.
60776090
if (auto overrideFn = dyn_cast<AbstractFunctionDecl>(override)) {

test/decl/inherit/override.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ class A {
77
func f1() { } // expected-note{{overridden declaration is here}}
88
func f2() -> A { } // expected-note{{overridden declaration is here}}
99

10-
@objc func f3() { }
11-
@objc func f4() -> ObjCClassA { }
10+
@objc func f3() { } // expected-note{{overridden declaration is here}}
11+
@objc func f4() -> ObjCClassA { } // expected-note{{overridden declaration is here}}
12+
13+
dynamic func f3D() { }
14+
dynamic func f4D() -> ObjCClassA { }
1215
}
1316

1417
extension A {
@@ -25,8 +28,11 @@ extension B {
2528
func f1() { } // expected-error{{declarations in extensions cannot override yet}}
2629
func f2() -> B { } // expected-error{{declarations in extensions cannot override yet}}
2730

28-
override func f3() { }
29-
override func f4() -> ObjCClassB { }
31+
override func f3() { } // expected-error{{cannot override a non-dynamic class declaration from an extension}}
32+
override func f4() -> ObjCClassB { } // expected-error{{cannot override a non-dynamic class declaration from an extension}}
33+
34+
override func f3D() { }
35+
override func f4D() -> ObjCClassB { }
3036

3137
func f5() { } // expected-error{{declarations in extensions cannot override yet}}
3238
func f6() -> A { } // expected-error{{declarations in extensions cannot override yet}}

0 commit comments

Comments
 (0)