Skip to content

Commit 1532fb1

Browse files
authored
Merge pull request #66609 from beccadax/just-empty-protocol
Diagnose conformances on @objcImpl extensions
2 parents 12b1843 + 6758fdb commit 1532fb1

File tree

4 files changed

+25
-1
lines changed

4 files changed

+25
-1
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,6 +1676,11 @@ ERROR(attr_objc_implementation_category_not_found,none,
16761676
NOTE(attr_objc_implementation_fixit_remove_category_name,none,
16771677
"remove arguments to implement the main '@interface' for this class",
16781678
())
1679+
ERROR(attr_objc_implementation_no_conformance,none,
1680+
"'@_objcImplementation' extension cannot add conformance to %0; "
1681+
"add this conformance %select{with an ordinary extension|"
1682+
"in the Objective-C header}1",
1683+
(Type, bool))
16791684

16801685
ERROR(member_of_objc_implementation_not_objc_or_final,none,
16811686
"%0 %1 does not match any %0 declared in the headers for %2; did you use "

lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2899,6 +2899,18 @@ class ObjCImplementationChecker {
28992899
{
29002900
assert(!ext->hasClangNode() && "passed interface, not impl, to checker");
29012901

2902+
// Conformances are declared exclusively in the interface, so diagnose any
2903+
// in the implementation right away.
2904+
for (auto &inherited : ext->getInherited()) {
2905+
bool isImportedProtocol = false;
2906+
if (auto protoNominal = inherited.getType()->getAnyNominal())
2907+
isImportedProtocol = protoNominal->hasClangNode();
2908+
2909+
diagnose(inherited.getLoc(),
2910+
diag::attr_objc_implementation_no_conformance,
2911+
inherited.getType(), isImportedProtocol);
2912+
}
2913+
29022914
// Did we actually match this extension to an interface? (In invalid code,
29032915
// we might not have.)
29042916
auto interfaceDecl = ext->getImplementedObjCDecl();

test/decl/ext/Inputs/objc_implementation.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,6 @@
151151
struct ObjCStruct {
152152
int foo;
153153
};
154+
155+
@protocol EmptyObjCProto
156+
@end

test/decl/ext/objc_implementation.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
// RUN: %target-typecheck-verify-swift -import-objc-header %S/Inputs/objc_implementation.h
22
// REQUIRES: objc_interop
33

4-
@_objcImplementation extension ObjCClass {
4+
protocol EmptySwiftProto {}
5+
6+
@_objcImplementation extension ObjCClass: EmptySwiftProto, EmptyObjCProto {
57
// expected-note@-1 {{previously implemented by extension here}}
68
// expected-error@-2 {{extension for main class interface should provide implementation for instance method 'method(fromHeader4:)'}}
79
// expected-error@-3 {{extension for main class interface should provide implementation for property 'propertyFromHeader9'}}
810
// FIXME: give better diagnostic expected-error@-4 {{extension for main class interface should provide implementation for property 'propertyFromHeader8'}}
911
// FIXME: give better diagnostic expected-error@-5 {{extension for main class interface should provide implementation for property 'propertyFromHeader7'}}
1012
// FIXME: give better diagnostic expected-error@-6 {{extension for main class interface should provide implementation for instance method 'method(fromHeader3:)'}}
13+
// expected-error@-7 {{'@_objcImplementation' extension cannot add conformance to 'EmptySwiftProto'; add this conformance with an ordinary extension}}
14+
// expected-error@-8 {{'@_objcImplementation' extension cannot add conformance to 'EmptyObjCProto'; add this conformance in the Objective-C header}}
1115

1216
func method(fromHeader1: CInt) {
1317
// OK, provides an implementation for the header's method.

0 commit comments

Comments
 (0)