Skip to content

Commit e8b678d

Browse files
committed
---
yaml --- r: 347515 b: refs/heads/master c: 6e3a6eb h: refs/heads/master i: 347513: 6227ae6 347511: cabb6df
1 parent b1d4725 commit e8b678d

31 files changed

+734
-146
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 93bd2c1e122be93b71299c319f6cc708f1a50ed6
2+
refs/heads/master: 6e3a6ebd32e301ecda9d499896786d28bb659ab9
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/include/swift/AST/Decl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ enum class DescriptiveDeclKind : uint8_t {
139139
GenericClass,
140140
GenericType,
141141
Subscript,
142+
StaticSubscript,
143+
ClassSubscript,
142144
Constructor,
143145
Destructor,
144146
LocalFunction,

trunk/include/swift/AST/DiagnosticsCommon.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ ERROR(class_func_not_in_class,none,
8484
ERROR(class_var_not_in_class,none,
8585
"class properties are only allowed within classes; "
8686
"use 'static' to declare a %select{static|requirement fulfilled by either a static or class}0 property", (bool))
87+
ERROR(class_subscript_not_in_class,none,
88+
"class subscripts are only allowed within classes; "
89+
"use 'static' to declare a %select{static|requirement fulfilled by either a static or class}0 subscript", (bool))
8790

8891
// FIXME: Used by both the parser and the type-checker.
8992
ERROR(func_decl_without_brace,PointsToFirstBadToken,

trunk/include/swift/AST/DiagnosticsParse.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,6 @@ ERROR(expected_lbrace_subscript_protocol,PointsToFirstBadToken,
392392
"{ get set } specifier", ())
393393
ERROR(subscript_without_get,none,
394394
"subscript declarations must have a getter", ())
395-
ERROR(subscript_static,none,
396-
"subscript cannot be marked %0", (StaticSpellingKind))
397395

398396
// initializer
399397
ERROR(invalid_nested_init,none,

trunk/include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3646,6 +3646,8 @@ ERROR(objc_invalid_on_var,none,
36463646
ERROR(objc_invalid_on_subscript,none,
36473647
"subscript cannot be %" OBJC_ATTR_SELECT "0 because its type "
36483648
"cannot be represented in Objective-C", (unsigned))
3649+
ERROR(objc_invalid_on_static_subscript,none,
3650+
"%0 cannot be %" OBJC_ATTR_SELECT "1", (DescriptiveDeclKind, unsigned))
36493651
ERROR(objc_invalid_with_generic_params,none,
36503652
"method cannot be %" OBJC_ATTR_SELECT "0 because it has generic "
36513653
"parameters", (unsigned))

trunk/include/swift/Parse/Parser.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,8 @@ class Parser {
10061006
DeclAttributes &Attributes);
10071007

10081008
ParserResult<SubscriptDecl>
1009-
parseDeclSubscript(ParseDeclOptions Flags, DeclAttributes &Attributes,
1009+
parseDeclSubscript(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
1010+
ParseDeclOptions Flags, DeclAttributes &Attributes,
10101011
SmallVectorImpl<Decl *> &Decls);
10111012

10121013
ParserResult<ConstructorDecl>

trunk/lib/AST/ASTPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2874,6 +2874,9 @@ void PrintAST::visitSubscriptDecl(SubscriptDecl *decl) {
28742874
printDocumentationComment(decl);
28752875
printAttributes(decl);
28762876
printAccess(decl);
2877+
if (!Options.SkipIntroducerKeywords && decl->isStatic() &&
2878+
Options.PrintStaticKeyword)
2879+
printStaticKeyword(decl->getCorrectStaticSpelling());
28772880
printContextIfNeeded(decl);
28782881
recordDeclLoc(decl, [&]{
28792882
Printer << "subscript";

trunk/lib/AST/Decl.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ DescriptiveDeclKind Decl::getDescriptiveKind() const {
150150
TRIVIAL_KIND(GenericTypeParam);
151151
TRIVIAL_KIND(AssociatedType);
152152
TRIVIAL_KIND(Protocol);
153-
TRIVIAL_KIND(Subscript);
154153
TRIVIAL_KIND(Constructor);
155154
TRIVIAL_KIND(Destructor);
156155
TRIVIAL_KIND(EnumElement);
@@ -188,6 +187,18 @@ DescriptiveDeclKind Decl::getDescriptiveKind() const {
188187
}
189188
}
190189

190+
case DeclKind::Subscript: {
191+
auto subscript = cast<SubscriptDecl>(this);
192+
switch (subscript->getCorrectStaticSpelling()) {
193+
case StaticSpellingKind::None:
194+
return DescriptiveDeclKind::Subscript;
195+
case StaticSpellingKind::KeywordStatic:
196+
return DescriptiveDeclKind::StaticSubscript;
197+
case StaticSpellingKind::KeywordClass:
198+
return DescriptiveDeclKind::ClassSubscript;
199+
}
200+
}
201+
191202
case DeclKind::Accessor: {
192203
auto accessor = cast<AccessorDecl>(this);
193204

@@ -279,6 +290,8 @@ StringRef Decl::getDescriptiveKindName(DescriptiveDeclKind K) {
279290
ENTRY(GenericClass, "generic class");
280291
ENTRY(GenericType, "generic type");
281292
ENTRY(Subscript, "subscript");
293+
ENTRY(StaticSubscript, "static subscript");
294+
ENTRY(ClassSubscript, "class subscript");
282295
ENTRY(Constructor, "initializer");
283296
ENTRY(Destructor, "deinitializer");
284297
ENTRY(LocalFunction, "local function");

trunk/lib/Parse/ParseDecl.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2870,13 +2870,10 @@ Parser::parseDecl(ParseDeclOptions Flags,
28702870
break;
28712871
case tok::kw_subscript: {
28722872
DeclParsingContext.setCreateSyntax(SyntaxKind::SubscriptDecl);
2873-
if (StaticLoc.isValid()) {
2874-
diagnose(Tok, diag::subscript_static, StaticSpelling)
2875-
.fixItRemove(SourceRange(StaticLoc));
2876-
StaticLoc = SourceLoc();
2877-
}
28782873
llvm::SmallVector<Decl *, 4> Entries;
2879-
DeclResult = parseDeclSubscript(Flags, Attributes, Entries);
2874+
DeclResult = parseDeclSubscript(StaticLoc, StaticSpelling, Flags,
2875+
Attributes, Entries);
2876+
StaticLoc = SourceLoc(); // we handled static if present.
28802877
if (DeclResult.hasCodeCompletion() && isCodeCompletionFirstPass())
28812878
break;
28822879
std::for_each(Entries.begin(), Entries.end(), Handler);
@@ -6277,9 +6274,26 @@ parseDeclProtocol(ParseDeclOptions Flags, DeclAttributes &Attributes) {
62776274
/// attribute-list? 'subscript' parameter-clause '->' type
62786275
/// \endverbatim
62796276
ParserResult<SubscriptDecl>
6280-
Parser::parseDeclSubscript(ParseDeclOptions Flags,
6277+
Parser::parseDeclSubscript(SourceLoc StaticLoc,
6278+
StaticSpellingKind StaticSpelling,
6279+
ParseDeclOptions Flags,
62816280
DeclAttributes &Attributes,
62826281
SmallVectorImpl<Decl *> &Decls) {
6282+
assert(StaticLoc.isInvalid() || StaticSpelling != StaticSpellingKind::None);
6283+
6284+
if (StaticLoc.isValid()) {
6285+
if (Flags.contains(PD_InStruct) || Flags.contains(PD_InEnum) ||
6286+
Flags.contains(PD_InProtocol)) {
6287+
if (StaticSpelling == StaticSpellingKind::KeywordClass) {
6288+
diagnose(Tok, diag::class_subscript_not_in_class,
6289+
Flags.contains(PD_InProtocol))
6290+
.fixItReplace(StaticLoc, "static");
6291+
6292+
StaticSpelling = StaticSpellingKind::KeywordStatic;
6293+
}
6294+
}
6295+
}
6296+
62836297
ParserStatus Status;
62846298
SourceLoc SubscriptLoc = consumeToken(tok::kw_subscript);
62856299

@@ -6354,7 +6368,7 @@ Parser::parseDeclSubscript(ParseDeclOptions Flags,
63546368
DeclName name = DeclName(Context, DeclBaseName::createSubscript(),
63556369
argumentNames);
63566370
auto *Subscript = new (Context) SubscriptDecl(name,
6357-
SourceLoc(), StaticSpellingKind::None,
6371+
StaticLoc, StaticSpelling,
63586372
SubscriptLoc, Indices.get(),
63596373
ArrowLoc, ElementTy.get(),
63606374
CurDeclContext,
@@ -6402,7 +6416,7 @@ Parser::parseDeclSubscript(ParseDeclOptions Flags,
64026416
} else {
64036417
Status |= parseGetSet(Flags, GenericParams,
64046418
Indices.get(), ElementTy.get(),
6405-
accessors, Subscript, /*StaticLoc=*/SourceLoc());
6419+
accessors, Subscript, StaticLoc);
64066420
}
64076421

64086422
bool Invalid = false;
@@ -6413,7 +6427,7 @@ Parser::parseDeclSubscript(ParseDeclOptions Flags,
64136427
}
64146428

64156429
accessors.record(*this, Subscript, (Invalid || !Status.isSuccess()),
6416-
Flags, /*static*/ SourceLoc(), Attributes,
6430+
Flags, StaticLoc, Attributes,
64176431
ElementTy.get(), Indices.get(), Decls);
64186432

64196433
// No need to setLocalDiscriminator because subscripts cannot

trunk/lib/Sema/CSApply.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,12 @@ namespace {
13761376

13771377
auto &tc = cs.getTypeChecker();
13781378
auto baseTy = cs.getType(base)->getRValueType();
1379+
1380+
bool baseIsInstance = true;
1381+
if (auto baseMeta = baseTy->getAs<AnyMetatypeType>()) {
1382+
baseIsInstance = false;
1383+
baseTy = baseMeta->getInstanceType();
1384+
}
13791385

13801386
// Check whether the base is 'super'.
13811387
bool isSuper = base->isSuperExpr();
@@ -1461,9 +1467,22 @@ namespace {
14611467
auto openedBaseType =
14621468
getBaseType(openedFullFnType, /*wantsRValue*/ false);
14631469
auto containerTy = solution.simplifyType(openedBaseType);
1464-
base = coerceObjectArgumentToType(
1465-
base, containerTy, subscript, AccessSemantics::Ordinary,
1466-
locator.withPathElement(ConstraintLocator::MemberRefBase));
1470+
1471+
if (baseIsInstance) {
1472+
base = coerceObjectArgumentToType(
1473+
base, containerTy, subscript, AccessSemantics::Ordinary,
1474+
locator.withPathElement(ConstraintLocator::MemberRefBase));
1475+
} else {
1476+
base = coerceToType(base,
1477+
MetatypeType::get(containerTy),
1478+
locator.withPathElement(
1479+
ConstraintLocator::MemberRefBase));
1480+
1481+
if (!base)
1482+
return nullptr;
1483+
1484+
base = cs.coerceToRValue(base);
1485+
}
14671486
if (!base)
14681487
return nullptr;
14691488

trunk/lib/Sema/MiscDiagnostics.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
422422
// Allow references to types as a part of:
423423
// - member references T.foo, T.Type, T.self, etc.
424424
// - constructor calls T()
425+
// - Subscripts T[]
425426
if (auto *ParentExpr = Parent.getAsExpr()) {
426427
// This is an exhaustive list of the accepted syntactic forms.
427428
if (isa<ErrorExpr>(ParentExpr) ||
@@ -433,7 +434,8 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
433434
isa<UnresolvedDotExpr>(ParentExpr) ||
434435
isa<DotSyntaxBaseIgnoredExpr>(ParentExpr) ||
435436
isa<UnresolvedSpecializeExpr>(ParentExpr) ||
436-
isa<OpenExistentialExpr>(ParentExpr)) {
437+
isa<OpenExistentialExpr>(ParentExpr) ||
438+
isa<SubscriptExpr>(ParentExpr)) {
437439
return;
438440
}
439441
}

trunk/lib/Sema/TypeCheckDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4081,7 +4081,7 @@ void TypeChecker::validateDecl(ValueDecl *D) {
40814081
// Member subscripts need some special validation logic.
40824082
if (SD->getDeclContext()->isTypeContext()) {
40834083
// If this is a class member, mark it final if the class is final.
4084-
inferFinalAndDiagnoseIfNeeded(*this, SD, StaticSpellingKind::None);
4084+
inferFinalAndDiagnoseIfNeeded(*this, SD, SD->getStaticSpelling());
40854085
}
40864086

40874087
// Perform accessor-related validation.

trunk/lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,16 @@ bool swift::isRepresentableInObjC(const SubscriptDecl *SD, ObjCReason Reason) {
827827
if (checkObjCInForeignClassContext(SD, Reason))
828828
return false;
829829

830+
// ObjC doesn't support class subscripts.
831+
if (!SD->isInstanceMember()) {
832+
if (Diagnose) {
833+
SD->diagnose(diag::objc_invalid_on_static_subscript,
834+
SD->getDescriptiveKind(), Reason);
835+
describeObjCReason(SD, Reason);
836+
}
837+
return true;
838+
}
839+
830840
if (!SD->hasInterfaceType()) {
831841
SD->getASTContext().getLazyResolver()->resolveDeclSignature(
832842
const_cast<SubscriptDecl *>(SD));

trunk/lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,6 +1684,7 @@ static bool checkSingleOverride(ValueDecl *override, ValueDecl *base) {
16841684
switch (baseKind) {
16851685
case DescriptiveDeclKind::StaticProperty:
16861686
case DescriptiveDeclKind::StaticMethod:
1687+
case DescriptiveDeclKind::StaticSubscript:
16871688
override->diagnose(diag::override_static, baseKind);
16881689
break;
16891690
default:

trunk/test/ClangImporter/Inputs/custom-modules/ObjCSubscripts.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,10 @@
6060
@interface KeySubscriptReversedOverrideSetter : KeySubscriptReversedBase
6161
- (void)setObject:(id)object forKeyedSubscript:(NSString *)key;
6262
@end
63+
64+
@interface NoClassSubscript : NSObject
65+
+ (id)objectAtIndexedSubscript:(int)i;
66+
+ (void)setObject:(id)obj atIndexedSubscript:(int)i;
67+
+ (id)objectForKeyedSubscript:(NSString *)subscript;
68+
+ (void)setObject:(id)object forKeyedSubscript:(NSString *)key;
69+
@end
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %build-clang-importer-objc-overlays
3+
4+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -typecheck -I %S/Inputs/custom-modules %s -verify
5+
6+
// REQUIRES: objc_interop
7+
8+
import ObjCSubscripts
9+
10+
func testClass() {
11+
_ = NoClassSubscript[0] // expected-error{{value of type 'NoClassSubscript.Type' has no subscripts}}
12+
NoClassSubscript[0] = "" // expected-error{{value of type 'NoClassSubscript.Type' has no subscripts}}
13+
14+
_ = NoClassSubscript["foo"] // expected-error{{value of type 'NoClassSubscript.Type' has no subscripts}}
15+
NoClassSubscript["foo"] = "" // expected-error{{value of type 'NoClassSubscript.Type' has no subscripts}}
16+
}
17+
18+
func testInstance(x: NoClassSubscript) {
19+
_ = x[0] // expected-error{{value of type 'NoClassSubscript' has no subscripts}}
20+
x[0] = "" // expected-error{{value of type 'NoClassSubscript' has no subscripts}}
21+
22+
_ = x["foo"] // expected-error{{value of type 'NoClassSubscript' has no subscripts}}
23+
x["foo"] = "" // expected-error{{value of type 'NoClassSubscript' has no subscripts}}
24+
}
25+
26+
func testClassMethods() {
27+
_ = NoClassSubscript.object(atIndexedSubscript: 0)
28+
NoClassSubscript.setObject("", atIndexedSubscript: 0)
29+
30+
_ = NoClassSubscript.object(forKeyedSubscript: "foo")
31+
NoClassSubscript.setObject("", forKeyedSubscript: "foo")
32+
}

trunk/test/Constraints/subscript.swift

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ protocol IntToStringSubscript {
1111
subscript (i : Int) -> String { get }
1212
}
1313

14-
class LameDictionary {
14+
class FauxDictionary {
1515
subscript (i : Int) -> String {
1616
get {
1717
return String(i)
1818
}
1919
}
2020
}
2121

22-
func archetypeSubscript<T : IntToStringSubscript, U : LameDictionary>(_ t: T, u: U)
22+
func archetypeSubscript<T : IntToStringSubscript, U : FauxDictionary>(_ t: T, u: U)
2323
-> String {
2424
// Subscript an archetype.
2525
if false { return t[17] }
@@ -33,6 +33,39 @@ func existentialSubscript(_ a: IntToStringSubscript) -> String {
3333
return a[17]
3434
}
3535

36+
// Static of above:
37+
38+
// Subscript of archetype.
39+
protocol IntToStringStaticSubscript {
40+
static subscript (i : Int) -> String { get }
41+
}
42+
43+
class FauxStaticDictionary {
44+
static subscript (i : Int) -> String {
45+
get {
46+
return String(i)
47+
}
48+
}
49+
}
50+
51+
func archetypeStaticSubscript<
52+
T : IntToStringStaticSubscript, U : FauxStaticDictionary
53+
>(_ t: T.Type, u: U.Type) -> String {
54+
// Subscript an archetype.
55+
if false { return t[17] }
56+
57+
// Subscript an archetype for which the subscript operator is in a base class.
58+
return u[17]
59+
}
60+
61+
// Subscript of existential type.
62+
func existentialStaticSubscript(
63+
_ a: IntToStringStaticSubscript.Type
64+
) -> String {
65+
return a[17]
66+
}
67+
68+
3669
class MyDictionary<Key, Value> {
3770
subscript (key : Key) -> Value {
3871
get {}

trunk/test/IDE/print_ast_tc_decls.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,13 @@ struct d0100_FooStruct {
172172
}
173173
}
174174
// PASS_COMMON-NEXT: {{^}} subscript(i: Int, j: Int) -> Double { get }{{$}}
175+
176+
static subscript(i: Int) -> Double {
177+
get {
178+
return Double(i)
179+
}
180+
}
181+
// PASS_COMMON-NEXT: {{^}} static subscript(i: Int) -> Double { get }{{$}}
175182

176183
func bodyNameVoidFunc1(a: Int, b x: Float) {}
177184
// PASS_COMMON-NEXT: {{^}} func bodyNameVoidFunc1(a: Int, b x: Float){{$}}

0 commit comments

Comments
 (0)