Skip to content

Commit a2f1d35

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 43e48ef commit a2f1d35

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
@@ -1620,6 +1620,33 @@ ERROR(objc_implementation_wrong_swift_name,none,
16201620
"mean %2?",
16211621
(ObjCSelector, DescriptiveDeclKind, DeclName))
16221622

1623+
ERROR(objc_implementation_missing_impl,none,
1624+
"extension for %select{main class interface|category %0}0 should "
1625+
"provide implementation for %1 %2",
1626+
(Identifier, DescriptiveDeclKind, ValueDecl *))
1627+
1628+
ERROR(objc_implementation_class_or_instance_mismatch,none,
1629+
"%0 %1 does not match %2 declared in header",
1630+
(DescriptiveDeclKind, ValueDecl *, DescriptiveDeclKind))
1631+
1632+
ERROR(objc_implementation_multiple_matching_candidates,none,
1633+
"found multiple implementations that could match %0 %1 with selector %2",
1634+
(DescriptiveDeclKind, ValueDecl *, ObjCSelector))
1635+
NOTE(objc_implementation_candidate_impl_here,none,
1636+
"%0 %1 is a potential match%select{|; insert '@objc(%3)' to use it}2",
1637+
(DescriptiveDeclKind, ValueDecl *, bool, StringRef))
1638+
NOTE(objc_implementation_requirement_here,none,
1639+
"%0 %1 declared in header here",
1640+
(DescriptiveDeclKind, ValueDecl *))
1641+
1642+
ERROR(objc_implementation_multiple_matching_requirements,none,
1643+
"%0 %1 could match several different members declared in the header",
1644+
(DescriptiveDeclKind, ValueDecl *))
1645+
NOTE(objc_implementation_one_matched_requirement,none,
1646+
"%0 %1 (with selector %2) is a potential match%select{|; insert "
1647+
"'@objc(%4)' to use it}3",
1648+
(DescriptiveDeclKind, ValueDecl *, ObjCSelector, bool, StringRef))
1649+
16231650
ERROR(cdecl_not_at_top_level,none,
16241651
"@_cdecl can only be applied to global functions", ())
16251652
ERROR(cdecl_empty_name,none,

include/swift/AST/TypeCheckRequests.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4166,6 +4166,28 @@ class LocalDiscriminatorsRequest
41664166
bool isCached() const { return true; }
41674167
};
41684168

4169+
/// Checks that all of a class's \c \@objcImplementation extensions provide
4170+
/// complete and correct implementations for their corresponding interfaces.
4171+
/// This is done on all of a class's implementations at once to improve diagnostics.
4172+
class TypeCheckObjCImplementationRequest
4173+
: public SimpleRequest<TypeCheckObjCImplementationRequest,
4174+
evaluator::SideEffect(ExtensionDecl *),
4175+
RequestFlags::Cached> {
4176+
public:
4177+
using SimpleRequest::SimpleRequest;
4178+
4179+
private:
4180+
friend SimpleRequest;
4181+
4182+
// Evaluation.
4183+
evaluator::SideEffect
4184+
evaluate(Evaluator &evaluator, ExtensionDecl *ED) const;
4185+
4186+
public:
4187+
// Separate caching.
4188+
bool isCached() const { return true; }
4189+
};
4190+
41694191
void simple_display(llvm::raw_ostream &out, ASTNode node);
41704192
void simple_display(llvm::raw_ostream &out, Type value);
41714193
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
@@ -469,3 +469,6 @@ SWIFT_REQUEST(TypeChecker, LocalDiscriminatorsRequest,
469469
SWIFT_REQUEST(TypeChecker, IsNonUserModuleRequest,
470470
bool(ModuleDecl *),
471471
Cached, NoLocationInfo)
472+
SWIFT_REQUEST(TypeChecker, TypeCheckObjCImplementationRequest,
473+
unsigned(ExtensionDecl *),
474+
Cached, NoLocationInfo)

0 commit comments

Comments
 (0)