Skip to content

Commit 29b5934

Browse files
authored
Merge pull request #6346 from KingOfBrian/bugfix/SR-584
Warn if a non dynamic class declaration is overridden in an extension
2 parents d33cbf5 + 4495fde commit 29b5934

File tree

4 files changed

+45
-5
lines changed

4 files changed

+45
-5
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,6 +1707,12 @@ ERROR(override_ownership_mismatch,none,
17071707
"cannot override %select{strong|weak|unowned|unowned(unsafe)}0 property "
17081708
"with %select{strong|weak|unowned|unowned(unsafe)}1 property",
17091709
(/*Ownership*/unsigned, /*Ownership*/unsigned))
1710+
ERROR(override_class_declaration_in_extension,none,
1711+
"cannot override a non-dynamic class declaration from an extension",
1712+
())
1713+
WARNING(override_class_declaration_in_extension_warning,none,
1714+
"cannot override a non-dynamic class declaration from an extension",
1715+
())
17101716
ERROR(override_throws,none,
17111717
"cannot override non-throwing %select{method|initializer}0 with "
17121718
"throwing %select{method|initializer}0", (bool))

lib/Sema/TypeCheckDecl.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6087,6 +6087,23 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
60876087
new (TC.Context) OverrideAttr(SourceLoc()));
60886088
}
60896089

6090+
// If the overridden method is declared in a Swift Class Declaration,
6091+
// dispatch will use table dispatch. If the override is in an extension
6092+
// warn, since it is not added to the class vtable.
6093+
//
6094+
// FIXME: Only warn if the extension is in another module, and if
6095+
// it is in the same module, update the vtable.
6096+
if (auto *baseDecl = dyn_cast<ClassDecl>(base->getDeclContext())) {
6097+
if (baseDecl->hasKnownSwiftImplementation() &&
6098+
!base->isDynamic() &&
6099+
override->getDeclContext()->isExtensionContext()) {
6100+
// For compatibility, only generate a warning in Swift 3
6101+
TC.diagnose(override, (TC.Context.isSwiftVersion3()
6102+
? diag::override_class_declaration_in_extension_warning
6103+
: diag::override_class_declaration_in_extension));
6104+
TC.diagnose(base, diag::overridden_here);
6105+
}
6106+
}
60906107
// If the overriding declaration is 'throws' but the base is not,
60916108
// complain.
60926109
if (auto overrideFn = dyn_cast<AbstractFunctionDecl>(override)) {

test/Compatibility/override.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-typecheck-verify-swift -parse-as-library -swift-version 3
2+
3+
class A {
4+
@objc func objcVirtualFunction() { } // expected-note{{overridden declaration is here}}
5+
}
6+
7+
class B : A { }
8+
9+
extension B {
10+
override func objcVirtualFunction() { } // expected-warning{{cannot override a non-dynamic class declaration from an extension}}
11+
}

test/decl/inherit/override.swift

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -parse-as-library
1+
// RUN: %target-typecheck-verify-swift -parse-as-library -swift-version 4
22

33
@objc class ObjCClassA {}
44
@objc class ObjCClassB : ObjCClassA {}
@@ -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)