Skip to content

Commit fc23740

Browse files
committed
Merge pull request #1170 from tkremenek/Swift2.2-selector
[Swift 2.2] pull in SE-0022 into swift-2.2-branch.
2 parents f247c49 + 4dbefd8 commit fc23740

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1343
-51
lines changed

CHANGELOG.md

+23
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,29 @@ Latest
142142

143143
For more information, see [SE-0020](https://github.com/apple/swift-evolution/blob/master/proposals/0020-if-swift-version.md).
144144

145+
* The Objective-C selector of a Swift method can now be determined
146+
directly with the #selector expression, e.g.,:
147+
148+
let sel = #selector(insertSubview(_:aboveSubview:)) // sel has type Selector
149+
150+
Along with this change, the use of string literals as selectors has
151+
been deprecated, e.g.,
152+
153+
let sel: Selector = "insertSubview:aboveSubview:"
154+
155+
Generally, such string literals should be replaced with uses of
156+
`#selector`, and the compiler will provide Fix-Its that use
157+
`#selector`. In cases where they is not possible (e.g., when referring
158+
to the getter of a property), one can still directly construct
159+
selectors, e.g.,:
160+
161+
let sel = Selector("propertyName")
162+
163+
Note that the compiler is now checking the string literals used to
164+
construct Selectors to ensure that they are well-formed Objective-C
165+
selectors and that there is an '@objc' method with that selector.
166+
167+
145168
2015-09-17 [Xcode 7.1, Swift 2.1]
146169
----------
147170

docs/SIL.rst

+5-1
Original file line numberDiff line numberDiff line change
@@ -2452,14 +2452,18 @@ string_literal
24522452
sil-instruction ::= 'string_literal' encoding string-literal
24532453
encoding ::= 'utf8'
24542454
encoding ::= 'utf16'
2455+
encoding ::= 'objc_selector'
24552456

24562457
%1 = string_literal "asdf"
24572458
// %1 has type $Builtin.RawPointer
24582459

24592460
Creates a reference to a string in the global string table. The result
24602461
is a pointer to the data. The referenced string is always null-terminated. The
24612462
string literal value is specified using Swift's string
2462-
literal syntax (though ``\()`` interpolations are not allowed).
2463+
literal syntax (though ``\()`` interpolations are not allowed). When
2464+
the encoding is ``objc_selector``, the string literal produces a
2465+
reference to a UTF-8-encoded Objective-C selector in the Objective-C
2466+
method name segment.
24632467

24642468
Dynamic Dispatch
24652469
~~~~~~~~~~~~~~~~

include/swift/AST/DeclContext.h

+6
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,12 @@ class alignas(1 << DeclContextAlignInBits) DeclContext {
405405
LazyResolver *typeResolver,
406406
SmallVectorImpl<ValueDecl *> &decls) const;
407407

408+
/// Look up all Objective-C methods with the given selector visible
409+
/// in the enclosing module.
410+
void lookupAllObjCMethods(
411+
ObjCSelector selector,
412+
SmallVectorImpl<AbstractFunctionDecl *> &results) const;
413+
408414
/// Return the ASTContext for a specified DeclContext by
409415
/// walking up to the enclosing module and returning its ASTContext.
410416
ASTContext &getASTContext() const;

include/swift/AST/DiagnosticsParse.def

+8
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,14 @@ ERROR(expected_type_after_as,none,
10171017
ERROR(string_interpolation_extra,none,
10181018
"extra tokens after interpolated string expression", ())
10191019

1020+
// Selector expressions.
1021+
ERROR(expr_selector_expected_lparen,PointsToFirstBadToken,
1022+
"expected '(' following '#selector'", ())
1023+
ERROR(expr_selector_expected_expr,PointsToFirstBadToken,
1024+
"expected expression naming a method within '#selector(...)'", ())
1025+
ERROR(expr_selector_expected_rparen,PointsToFirstBadToken,
1026+
"expected ')' to complete '#selector' expression", ())
1027+
10201028
//------------------------------------------------------------------------------
10211029
// Attribute-parsing diagnostics
10221030
//------------------------------------------------------------------------------

include/swift/AST/DiagnosticsSIL.def

+3
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ ERROR(unsupported_c_function_pointer_conversion,none,
8888
"C function pointer signature %0 is not compatible with expected type %1",
8989
(Type, Type))
9090

91+
ERROR(objc_selector_malformed,none,"the type ObjectiveC.Selector is malformed",
92+
())
93+
9194
// Definite initialization diagnostics.
9295
NOTE(variable_defined_here,none,
9396
"%select{variable|constant}0 defined here", (bool))

include/swift/AST/DiagnosticsSema.def

+31-1
Original file line numberDiff line numberDiff line change
@@ -336,8 +336,38 @@ ERROR(noescape_functiontype_mismatch,none,
336336
"invalid conversion from non-escaping function of type %0 to "
337337
"potentially escaping function type %1", (Type, Type))
338338

339+
// Selector expressions.
340+
ERROR(expr_selector_no_objc_runtime,none,
341+
"'#selector' can only be used with the Objective-C runtime", ())
342+
ERROR(expr_selector_module_missing,none,
343+
"import the 'ObjectiveC' module to use '#selector'", ())
344+
ERROR(expr_selector_no_declaration,none,
345+
"argument of '#selector' does not refer to an initializer or method", ())
346+
ERROR(expr_selector_property,none,
347+
"argument of '#selector' cannot refer to a property", ())
348+
ERROR(expr_selector_not_method_or_init,none,
349+
"argument of '#selector' does not refer to a method or initializer", ())
350+
ERROR(expr_selector_not_objc,none,
351+
"argument of '#selector' refers to %select{a method|an initializer}0 "
352+
"that is not exposed to Objective-C",
353+
(bool))
354+
NOTE(expr_selector_make_objc,none,
355+
"add '@objc' to expose this %select{method|initializer}0 to Objective-C",
356+
(bool))
339357

340-
358+
// Selectors-as-string-literals.
359+
WARNING(selector_literal_invalid,none,
360+
"string literal is not a valid Objective-C selector", ())
361+
WARNING(selector_literal_undeclared,none,
362+
"no method declared with Objective-C selector %0", (ObjCSelector))
363+
WARNING(selector_literal_deprecated,none,
364+
"use of string literal for Objective-C selectors is deprecated; "
365+
"use '#selector' or explicitly construct a 'Selector'", ())
366+
WARNING(selector_literal_deprecated_suggest,none,
367+
"use of string literal for Objective-C selectors is deprecated; "
368+
"use '#selector' instead", ())
369+
WARNING(selector_construction_suggest,none,
370+
"use '#selector' instead of explicitly constructing a 'Selector'", ())
341371

342372
ERROR(cannot_return_value_from_void_func,none,
343373
"unexpected non-void return value in void function", ())

include/swift/AST/Expr.h

+38
Original file line numberDiff line numberDiff line change
@@ -3679,6 +3679,44 @@ class EditorPlaceholderExpr : public Expr {
36793679
void setSemanticExpr(Expr *SE) { SemanticExpr = SE; }
36803680
};
36813681

3682+
/// Produces the Objective-C selector of the referenced method.
3683+
///
3684+
/// \code
3685+
/// #selector(UIView.insertSubview(_:aboveSubview:))
3686+
/// \endcode
3687+
class ObjCSelectorExpr : public Expr {
3688+
SourceLoc KeywordLoc;
3689+
SourceLoc LParenLoc;
3690+
Expr *SubExpr;
3691+
SourceLoc RParenLoc;
3692+
AbstractFunctionDecl *Method = nullptr;
3693+
3694+
public:
3695+
ObjCSelectorExpr(SourceLoc keywordLoc, SourceLoc lParenLoc,
3696+
Expr *subExpr, SourceLoc rParenLoc)
3697+
: Expr(ExprKind::ObjCSelector, /*Implicit=*/false),
3698+
KeywordLoc(keywordLoc), LParenLoc(lParenLoc), SubExpr(subExpr),
3699+
RParenLoc(rParenLoc) { }
3700+
3701+
Expr *getSubExpr() const { return SubExpr; }
3702+
void setSubExpr(Expr *expr) { SubExpr = expr; }
3703+
3704+
/// Retrieve the Objective-C method to which this expression refers.
3705+
AbstractFunctionDecl *getMethod() const { return Method; }
3706+
3707+
/// Set the Objective-C method to which this expression refers.
3708+
void setMethod(AbstractFunctionDecl *method) { Method = method; }
3709+
3710+
SourceLoc getLoc() const { return KeywordLoc; }
3711+
SourceRange getSourceRange() const {
3712+
return SourceRange(KeywordLoc, RParenLoc);
3713+
}
3714+
3715+
static bool classof(const Expr *E) {
3716+
return E->getKind() == ExprKind::ObjCSelector;
3717+
}
3718+
};
3719+
36823720
#undef SWIFT_FORWARD_SOURCE_LOCS_TO
36833721

36843722
} // end namespace swift

include/swift/AST/ExprNodes.def

+1
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ EXPR(DefaultValue, Expr)
155155
EXPR(CodeCompletion, Expr)
156156
UNCHECKED_EXPR(UnresolvedPattern, Expr)
157157
EXPR(EditorPlaceholder, Expr)
158+
EXPR(ObjCSelector, Expr)
158159

159160
#undef EXPR_RANGE
160161
#undef UNCHECKED_EXPR

include/swift/AST/KnownIdentifiers.def

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ IDENTIFIER_(OptionalNilComparisonType)
5050
IDENTIFIER(Protocol)
5151
IDENTIFIER(rawValue)
5252
IDENTIFIER(RawValue)
53+
IDENTIFIER(Selector)
5354
IDENTIFIER(self)
5455
IDENTIFIER(Self)
5556
IDENTIFIER(setObject)

include/swift/AST/Module.h

+28
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,11 @@ class ModuleDecl : public TypeDecl, public DeclContext {
409409
DeclContext *container, DeclName name,
410410
Identifier privateDiscriminator) const;
411411

412+
/// Find all Objective-C methods with the given selector.
413+
void lookupObjCMethods(
414+
ObjCSelector selector,
415+
SmallVectorImpl<AbstractFunctionDecl *> &results) const;
416+
412417
/// \sa getImportedModules
413418
enum class ImportFilter {
414419
All,
@@ -639,6 +644,11 @@ class FileUnit : public DeclContext {
639644
DeclName name,
640645
SmallVectorImpl<ValueDecl*> &results) const {}
641646

647+
/// Find all Objective-C methods with the given selector.
648+
virtual void lookupObjCMethods(
649+
ObjCSelector selector,
650+
SmallVectorImpl<AbstractFunctionDecl *> &results) const = 0;
651+
642652
/// Returns the comment attached to the given declaration.
643653
///
644654
/// This function is an implementation detail for comment serialization.
@@ -804,6 +814,10 @@ class DerivedFileUnit final : public FileUnit {
804814

805815
void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const override;
806816

817+
void lookupObjCMethods(
818+
ObjCSelector selector,
819+
SmallVectorImpl<AbstractFunctionDecl *> &results) const override;
820+
807821
Identifier
808822
getDiscriminatorForPrivateValue(const ValueDecl *D) const override {
809823
llvm_unreachable("no private decls in the derived file unit");
@@ -903,6 +917,11 @@ class SourceFile final : public FileUnit {
903917
/// complete, we diagnose.
904918
std::map<DeclAttrKind, const DeclAttribute *> AttrsRequiringFoundation;
905919

920+
/// A mapping from Objective-C selectors to the methods that have
921+
/// those selectors.
922+
llvm::DenseMap<ObjCSelector, llvm::TinyPtrVector<AbstractFunctionDecl *>>
923+
ObjCMethods;
924+
906925
template <typename T>
907926
using OperatorMap = llvm::DenseMap<Identifier,llvm::PointerIntPair<T,1,bool>>;
908927

@@ -959,6 +978,10 @@ class SourceFile final : public FileUnit {
959978
lookupClassMember(ModuleDecl::AccessPathTy accessPath, DeclName name,
960979
SmallVectorImpl<ValueDecl*> &results) const override;
961980

981+
void lookupObjCMethods(
982+
ObjCSelector selector,
983+
SmallVectorImpl<AbstractFunctionDecl *> &results) const override;
984+
962985
virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const override;
963986

964987
virtual void
@@ -1120,6 +1143,11 @@ class BuiltinUnit final : public FileUnit {
11201143
NLKind lookupKind,
11211144
SmallVectorImpl<ValueDecl*> &result) const override;
11221145

1146+
/// Find all Objective-C methods with the given selector.
1147+
void lookupObjCMethods(
1148+
ObjCSelector selector,
1149+
SmallVectorImpl<AbstractFunctionDecl *> &results) const override;
1150+
11231151
Identifier
11241152
getDiscriminatorForPrivateValue(const ValueDecl *D) const override {
11251153
llvm_unreachable("no private values in the Builtin module");

include/swift/ClangImporter/ClangModule.h

+4
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ class ClangModuleUnit final : public LoadedFile {
7373
lookupClassMember(ModuleDecl::AccessPathTy accessPath, DeclName name,
7474
SmallVectorImpl<ValueDecl*> &decls) const override;
7575

76+
void lookupObjCMethods(
77+
ObjCSelector selector,
78+
SmallVectorImpl<AbstractFunctionDecl *> &results) const override;
79+
7680
virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const override;
7781

7882
virtual void getDisplayDecls(SmallVectorImpl<Decl*> &results) const override;

include/swift/Parse/Parser.h

+1
Original file line numberDiff line numberDiff line change
@@ -1097,6 +1097,7 @@ class Parser {
10971097
bool isExprBasic);
10981098
ParserResult<Expr> parseExprPostfix(Diag<> ID, bool isExprBasic);
10991099
ParserResult<Expr> parseExprUnary(Diag<> ID, bool isExprBasic);
1100+
ParserResult<Expr> parseExprSelector();
11001101
ParserResult<Expr> parseExprSuper();
11011102
ParserResult<Expr> parseExprConfiguration();
11021103
Expr *parseExprStringLiteral();

include/swift/Parse/Token.h

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ enum class tok {
4444
pound_endif,
4545
pound_line,
4646
pound_available,
47+
pound_selector,
4748
comment,
4849

4950
#define KEYWORD(X) kw_ ## X,

include/swift/SIL/SILInstruction.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -1254,7 +1254,9 @@ class StringLiteralInst : public LiteralInst {
12541254
public:
12551255
enum class Encoding {
12561256
UTF8,
1257-
UTF16
1257+
UTF16,
1258+
/// UTF-8 encoding of an Objective-C selector.
1259+
ObjCSelector,
12581260
};
12591261

12601262
private:

include/swift/Serialization/ModuleFile.h

+5
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,11 @@ class ModuleFile : public LazyMemberLoader {
553553
DeclName name,
554554
SmallVectorImpl<ValueDecl*> &results);
555555

556+
/// Find all Objective-C methods with the given selector.
557+
void lookupObjCMethods(
558+
ObjCSelector selector,
559+
SmallVectorImpl<AbstractFunctionDecl *> &results);
560+
556561
/// Reports all link-time dependencies.
557562
void collectLinkLibraries(Module::LinkLibraryCallback callback) const;
558563

include/swift/Serialization/SerializedModuleLoader.h

+5
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,11 @@ class SerializedASTFile final : public LoadedFile {
131131
lookupClassMember(Module::AccessPathTy accessPath, DeclName name,
132132
SmallVectorImpl<ValueDecl*> &decls) const override;
133133

134+
/// Find all Objective-C methods with the given selector.
135+
void lookupObjCMethods(
136+
ObjCSelector selector,
137+
SmallVectorImpl<AbstractFunctionDecl *> &results) const override;
138+
134139
Optional<BriefAndRawComment> getCommentForDecl(const Decl *D) const override;
135140

136141
virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const override;

lib/AST/ASTDumper.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -2161,6 +2161,16 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
21612161
}
21622162
OS << ')';
21632163
}
2164+
void visitObjCSelectorExpr(ObjCSelectorExpr *E) {
2165+
printCommon(E, "objc_selector_expr") << " decl=";
2166+
if (auto method = E->getMethod())
2167+
method->dumpRef(OS);
2168+
else
2169+
OS << "<unresolved>";
2170+
OS << '\n';
2171+
printRec(E->getSubExpr());
2172+
OS << ')';
2173+
}
21642174
};
21652175

21662176
} // end anonymous namespace.

lib/AST/ASTWalker.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,14 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
811811
return E;
812812
}
813813

814+
Expr *visitObjCSelectorExpr(ObjCSelectorExpr *E) {
815+
Expr *sub = doIt(E->getSubExpr());
816+
if (!sub) return nullptr;
817+
818+
E->setSubExpr(sub);
819+
return E;
820+
}
821+
814822
//===--------------------------------------------------------------------===//
815823
// Everything Else
816824
//===--------------------------------------------------------------------===//

lib/AST/Expr.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ void Expr::propagateLValueAccessKind(AccessKind accessKind,
314314
NON_LVALUE_EXPR(Assign)
315315
NON_LVALUE_EXPR(DefaultValue)
316316
NON_LVALUE_EXPR(CodeCompletion)
317+
NON_LVALUE_EXPR(ObjCSelector)
317318

318319
#define UNCHECKED_EXPR(KIND, BASE) \
319320
NON_LVALUE_EXPR(KIND)
@@ -487,6 +488,7 @@ bool Expr::canAppendCallParentheses() const {
487488
case ExprKind::StringLiteral:
488489
case ExprKind::InterpolatedStringLiteral:
489490
case ExprKind::MagicIdentifierLiteral:
491+
case ExprKind::ObjCSelector:
490492
return true;
491493

492494
case ExprKind::ObjectLiteral:

0 commit comments

Comments
 (0)