Skip to content

Commit 88f404f

Browse files
committed
Don’t require @optional ObjC methods in @objcImpl
rdar://108461441
1 parent c7e97a1 commit 88f404f

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
#include "swift/AST/SourceFile.h"
2929
#include "swift/AST/TypeCheckRequests.h"
3030
#include "swift/Basic/StringExtras.h"
31+
32+
#include "clang/AST/DeclObjC.h"
33+
3134
using namespace swift;
3235

3336
#pragma mark Determine whether an entity is representable in Objective-C.
@@ -3326,9 +3329,25 @@ class ObjCImplementationChecker {
33263329
return Identifier();
33273330
}
33283331

3332+
/// Is this member an `@optional` ObjC protocol requirement?
3333+
static bool isOptionalObjCProtocolRequirement(ValueDecl *vd) {
3334+
if (auto clangDecl = vd->getClangDecl()) {
3335+
if (auto method = dyn_cast<clang::ObjCMethodDecl>(clangDecl))
3336+
return method->isOptional();
3337+
if (auto property = dyn_cast<clang::ObjCPropertyDecl>(clangDecl))
3338+
return property->isOptional();
3339+
}
3340+
3341+
return false;
3342+
}
3343+
33293344
public:
33303345
void diagnoseUnmatchedRequirements() {
33313346
for (auto req : unmatchedRequirements) {
3347+
// Ignore `@optional` protocol requirements.
3348+
if (isOptionalObjCProtocolRequirement(req))
3349+
continue;
3350+
33323351
auto ext = cast<IterableDeclContext>(req->getDeclContext()->getAsDecl())
33333352
->getImplementationContext();
33343353

test/decl/ext/Inputs/objc_implementation.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,21 @@
9191
- (void)doSomethingFunAndAsynchronousWithCompletionHandler:(void (^ _Nonnull)(id _Nullable result, NSError * _Nullable error))completionHandler;
9292
@end
9393

94+
@protocol PartiallyOptionalProtocol
95+
96+
- (void)requiredMethod1;
97+
- (void)requiredMethod2;
98+
99+
@optional
100+
- (void)optionalMethod1;
101+
- (void)optionalMethod2;
102+
103+
@end
104+
105+
@interface ObjCClass (Conformance) <PartiallyOptionalProtocol>
106+
107+
@end
108+
94109
@interface ObjCSubclass : ObjCClass
95110

96111
- (void)subclassMethodFromHeader1:(int)param;

test/decl/ext/objc_implementation.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,15 @@
291291
}
292292
}
293293

294+
@_objcImplementation(Conformance) extension ObjCClass {
295+
// expected-error@-1 {{extension for category 'Conformance' should provide implementation for instance method 'requiredMethod2()'}}
296+
// no-error concerning 'optionalMethod2()'
297+
298+
func requiredMethod1() {}
299+
300+
func optionalMethod1() {}
301+
}
302+
294303
@_objcImplementation extension ObjCClass {}
295304
// expected-error@-1 {{duplicate implementation of Objective-C class 'ObjCClass'}}
296305

0 commit comments

Comments
 (0)