Skip to content

Commit a327c91

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 59d436f commit a327c91

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
@@ -1625,6 +1625,33 @@ ERROR(objc_implementation_wrong_swift_name,none,
16251625
"mean %2?",
16261626
(ObjCSelector, DescriptiveDeclKind, DeclName))
16271627

1628+
ERROR(objc_implementation_missing_impl,none,
1629+
"extension for %select{main class interface|category %0}0 should "
1630+
"provide implementation for %1 %2",
1631+
(Identifier, DescriptiveDeclKind, ValueDecl *))
1632+
1633+
ERROR(objc_implementation_class_or_instance_mismatch,none,
1634+
"%0 %1 does not match %2 declared in header",
1635+
(DescriptiveDeclKind, ValueDecl *, DescriptiveDeclKind))
1636+
1637+
ERROR(objc_implementation_multiple_matching_candidates,none,
1638+
"found multiple implementations that could match %0 %1 with selector %2",
1639+
(DescriptiveDeclKind, ValueDecl *, ObjCSelector))
1640+
NOTE(objc_implementation_candidate_impl_here,none,
1641+
"%0 %1 is a potential match%select{|; insert '@objc(%3)' to use it}2",
1642+
(DescriptiveDeclKind, ValueDecl *, bool, StringRef))
1643+
NOTE(objc_implementation_requirement_here,none,
1644+
"%0 %1 declared in header here",
1645+
(DescriptiveDeclKind, ValueDecl *))
1646+
1647+
ERROR(objc_implementation_multiple_matching_requirements,none,
1648+
"%0 %1 could match several different members declared in the header",
1649+
(DescriptiveDeclKind, ValueDecl *))
1650+
NOTE(objc_implementation_one_matched_requirement,none,
1651+
"%0 %1 (with selector %2) is a potential match%select{|; insert "
1652+
"'@objc(%4)' to use it}3",
1653+
(DescriptiveDeclKind, ValueDecl *, ObjCSelector, bool, StringRef))
1654+
16281655
ERROR(cdecl_not_at_top_level,none,
16291656
"@_cdecl can only be applied to global functions", ())
16301657
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
@@ -466,3 +466,6 @@ SWIFT_REQUEST(TypeChecker, GetRuntimeDiscoverableAttributes,
466466
SWIFT_REQUEST(TypeChecker, LocalDiscriminatorsRequest,
467467
unsigned(DeclContext *),
468468
Cached, NoLocationInfo)
469+
SWIFT_REQUEST(TypeChecker, TypeCheckObjCImplementationRequest,
470+
unsigned(ExtensionDecl *),
471+
Cached, NoLocationInfo)

0 commit comments

Comments
 (0)