Skip to content

Commit def1af6

Browse files
authored
Merge pull request swiftlang#23358 from brentdax/a-type-is-a-set-of-its-instances
Add static and class subscripts
2 parents cfc03f8 + 7ae331d commit def1af6

28 files changed

+708
-35
lines changed

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,

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,

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,

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))

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>

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";

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");

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

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

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
}

0 commit comments

Comments
 (0)