diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 2d3dc242c2f89..a9c7492c687be 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -1614,6 +1614,11 @@ ERROR(attr_objc_implementation_category_not_found,none, NOTE(attr_objc_implementation_fixit_remove_category_name,none, "remove arguments to implement the main '@interface' for this class", ()) +ERROR(attr_objc_implementation_no_conformance,none, + "'@_objcImplementation' extension cannot add conformance to %0; " + "add this conformance %select{with an ordinary extension|" + "in the Objective-C header}1", + (Type, bool)) ERROR(member_of_objc_implementation_not_objc_or_final,none, "%0 %1 does not match any %0 declared in the headers for %2; did you use " diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp index fd3bae37321f4..5f4ebdf8988cd 100644 --- a/lib/Sema/TypeCheckDeclObjC.cpp +++ b/lib/Sema/TypeCheckDeclObjC.cpp @@ -2906,6 +2906,18 @@ class ObjCImplementationChecker { { assert(!ext->hasClangNode() && "passed interface, not impl, to checker"); + // Conformances are declared exclusively in the interface, so diagnose any + // in the implementation right away. + for (auto &inherited : ext->getInherited()) { + bool isImportedProtocol = false; + if (auto protoNominal = inherited.getType()->getAnyNominal()) + isImportedProtocol = protoNominal->hasClangNode(); + + diagnose(inherited.getLoc(), + diag::attr_objc_implementation_no_conformance, + inherited.getType(), isImportedProtocol); + } + // Did we actually match this extension to an interface? (In invalid code, // we might not have.) auto interfaceDecl = ext->getImplementedObjCDecl(); diff --git a/test/decl/ext/Inputs/objc_implementation.h b/test/decl/ext/Inputs/objc_implementation.h index f6fc4856df29f..c4798088dd528 100644 --- a/test/decl/ext/Inputs/objc_implementation.h +++ b/test/decl/ext/Inputs/objc_implementation.h @@ -142,3 +142,6 @@ struct ObjCStruct { int foo; }; + +@protocol EmptyObjCProto +@end diff --git a/test/decl/ext/objc_implementation.swift b/test/decl/ext/objc_implementation.swift index 06a266410bf83..b702b782fda10 100644 --- a/test/decl/ext/objc_implementation.swift +++ b/test/decl/ext/objc_implementation.swift @@ -1,13 +1,17 @@ // RUN: %target-typecheck-verify-swift -import-objc-header %S/Inputs/objc_implementation.h // REQUIRES: objc_interop -@_objcImplementation extension ObjCClass { +protocol EmptySwiftProto {} + +@_objcImplementation extension ObjCClass: EmptySwiftProto, EmptyObjCProto { // expected-note@-1 {{previously implemented by extension here}} // expected-warning@-2 {{extension for main class interface should provide implementation for instance method 'method(fromHeader4:)'; this will become an error before '@_objcImplementation' is stabilized}} // expected-warning@-3 {{extension for main class interface should provide implementation for property 'propertyFromHeader9'; this will become an error before '@_objcImplementation' is stabilized}} // FIXME: give better diagnostic expected-warning@-4 {{extension for main class interface should provide implementation for property 'propertyFromHeader8'; this will become an error before '@_objcImplementation' is stabilized}} // FIXME: give better diagnostic expected-warning@-5 {{extension for main class interface should provide implementation for property 'propertyFromHeader7'; this will become an error before '@_objcImplementation' is stabilized}} // FIXME: give better diagnostic expected-warning@-6 {{extension for main class interface should provide implementation for instance method 'method(fromHeader3:)'; this will become an error before '@_objcImplementation' is stabilized}} + // expected-warning@-7 {{'@_objcImplementation' extension cannot add conformance to 'EmptySwiftProto'; add this conformance with an ordinary extension}} + // expected-warning@-8 {{'@_objcImplementation' extension cannot add conformance to 'EmptyObjCProto'; add this conformance in the Objective-C header}} func method(fromHeader1: CInt) { // OK, provides an implementation for the header's method.