Skip to content

Commit 7f688ef

Browse files
committed
Refactor and expand @objcImpl checking
Create a checker for @_objcImplementation member implementations that considers all of a class’s interface and implementation decls at once. This allows us to handle several things better: • Unimplemented requirements are now diagnosed • Header members that can match several implementations, or implementations that could match several header members, are now diagnosed • Tailored diagnostic when the implementation's Swift name matches the header's selector instead of its Swift name • Recommends inserting `@objc(<selector>)` when a Swift name matches but the implicit ObjC name doesn't • An `@objc(<selector>)` on one implementation can eliminate its requirement from being considered for other implementations, resolving ambiguities This does unfortunately regress the diagnostics when a requirement is implemented in the wrong extension. Some sort of whole-module checking would be needed to address this problem.
1 parent 2c0abf0 commit 7f688ef

File tree

9 files changed

+737
-159
lines changed

9 files changed

+737
-159
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,6 +1610,33 @@ ERROR(objc_implementation_wrong_swift_name,none,
16101610
"mean %2?",
16111611
(ObjCSelector, DescriptiveDeclKind, DeclName))
16121612

1613+
ERROR(objc_implementation_missing_impl,none,
1614+
"extension for %select{main class interface|category %0}0 should "
1615+
"provide implementation for %1 %2",
1616+
(Identifier, DescriptiveDeclKind, ValueDecl *))
1617+
1618+
ERROR(objc_implementation_class_or_instance_mismatch,none,
1619+
"%0 %1 does not match %2 declared in header",
1620+
(DescriptiveDeclKind, ValueDecl *, DescriptiveDeclKind))
1621+
1622+
ERROR(objc_implementation_multiple_matching_candidates,none,
1623+
"found multiple implementations that could match %0 %1 with selector %2",
1624+
(DescriptiveDeclKind, ValueDecl *, ObjCSelector))
1625+
NOTE(objc_implementation_candidate_impl_here,none,
1626+
"%0 %1 is a potential match%select{|; insert '@objc(%3)' to use it}2",
1627+
(DescriptiveDeclKind, ValueDecl *, bool, StringRef))
1628+
NOTE(objc_implementation_requirement_here,none,
1629+
"%0 %1 declared in header here",
1630+
(DescriptiveDeclKind, ValueDecl *))
1631+
1632+
ERROR(objc_implementation_multiple_matching_requirements,none,
1633+
"%0 %1 could match several different members declared in the header",
1634+
(DescriptiveDeclKind, ValueDecl *))
1635+
NOTE(objc_implementation_one_matched_requirement,none,
1636+
"%0 %1 (with selector %2) is a potential match%select{|; insert "
1637+
"'@objc(%4)' to use it}3",
1638+
(DescriptiveDeclKind, ValueDecl *, ObjCSelector, bool, StringRef))
1639+
16131640
ERROR(cdecl_not_at_top_level,none,
16141641
"@_cdecl can only be applied to global functions", ())
16151642
ERROR(cdecl_empty_name,none,

include/swift/AST/TypeCheckRequests.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4065,6 +4065,28 @@ class LocalDiscriminatorsRequest
40654065
bool isCached() const { return true; }
40664066
};
40674067

4068+
/// Checks that all of a class's \c \@objcImplementation extensions provide
4069+
/// complete and correct implementations for their corresponding interfaces.
4070+
/// This is done on all of a class's implementations at once to improve diagnostics.
4071+
class TypeCheckObjCImplementationRequest
4072+
: public SimpleRequest<TypeCheckObjCImplementationRequest,
4073+
evaluator::SideEffect(ExtensionDecl *),
4074+
RequestFlags::Cached> {
4075+
public:
4076+
using SimpleRequest::SimpleRequest;
4077+
4078+
private:
4079+
friend SimpleRequest;
4080+
4081+
// Evaluation.
4082+
evaluator::SideEffect
4083+
evaluate(Evaluator &evaluator, ExtensionDecl *ED) const;
4084+
4085+
public:
4086+
// Separate caching.
4087+
bool isCached() const { return true; }
4088+
};
4089+
40684090
void simple_display(llvm::raw_ostream &out, ASTNode node);
40694091
void simple_display(llvm::raw_ostream &out, Type value);
40704092
void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR);

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,3 +460,6 @@ SWIFT_REQUEST(TypeChecker, GetRuntimeDiscoverableAttributes,
460460
SWIFT_REQUEST(TypeChecker, LocalDiscriminatorsRequest,
461461
unsigned(DeclContext *),
462462
Cached, NoLocationInfo)
463+
SWIFT_REQUEST(TypeChecker, TypeCheckObjCImplementationRequest,
464+
unsigned(ExtensionDecl *),
465+
Cached, NoLocationInfo)

0 commit comments

Comments
 (0)