Skip to content

Commit 1e7dae3

Browse files
authored
Merge pull request #19145 from rudkx/parse-designated-protocol
Add support for parsing designated protocols in operator declarations.
2 parents f22864e + 039d10b commit 1e7dae3

File tree

12 files changed

+308
-92
lines changed

12 files changed

+308
-92
lines changed

include/swift/AST/Decl.h

Lines changed: 72 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -6270,22 +6270,49 @@ class OperatorDecl : public Decl {
62706270

62716271
Identifier name;
62726272

6273+
Identifier DesignatedProtocolName;
6274+
SourceLoc DesignatedProtocolNameLoc;
6275+
TypeLoc DesignatedProtocolTypeLoc;
6276+
62736277
public:
6274-
OperatorDecl(DeclKind kind,
6275-
DeclContext *DC,
6276-
SourceLoc OperatorLoc,
6277-
Identifier Name,
6278-
SourceLoc NameLoc)
6279-
: Decl(kind, DC),
6280-
OperatorLoc(OperatorLoc), NameLoc(NameLoc),
6281-
name(Name) {}
6282-
6278+
OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc,
6279+
Identifier Name, SourceLoc NameLoc,
6280+
Identifier DesignatedProtocolName = Identifier(),
6281+
SourceLoc DesignatedProtocolNameLoc = SourceLoc())
6282+
: Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name),
6283+
DesignatedProtocolName(DesignatedProtocolName),
6284+
DesignatedProtocolNameLoc(DesignatedProtocolNameLoc) {}
6285+
62836286
SourceLoc getLoc() const { return NameLoc; }
62846287

62856288
SourceLoc getOperatorLoc() const { return OperatorLoc; }
62866289
SourceLoc getNameLoc() const { return NameLoc; }
62876290
Identifier getName() const { return name; }
6288-
6291+
6292+
Identifier getDesignatedProtocolName() const {
6293+
return DesignatedProtocolName;
6294+
}
6295+
6296+
void setDesignatedProtocolName(Identifier name) {
6297+
DesignatedProtocolName = name;
6298+
}
6299+
6300+
SourceLoc getDesignatedProtocolNameLoc() const {
6301+
return DesignatedProtocolNameLoc;
6302+
}
6303+
6304+
void setDesignatedProtocolNameLoc(SourceLoc loc) {
6305+
DesignatedProtocolNameLoc = loc;
6306+
}
6307+
6308+
TypeLoc getDesignatedProtocolTypeLoc() const {
6309+
return DesignatedProtocolTypeLoc;
6310+
}
6311+
6312+
void setDesignatedProtocolTypeLoc(TypeLoc typeLoc) {
6313+
DesignatedProtocolTypeLoc = typeLoc;
6314+
}
6315+
62896316
static bool classof(const Decl *D) {
62906317
// Workaround: http://llvm.org/PR35906
62916318
if (DeclKind::Last_Decl == DeclKind::Last_OperatorDecl)
@@ -6298,39 +6325,42 @@ class OperatorDecl : public Decl {
62986325
/// Declares the behavior of an infix operator. For example:
62996326
///
63006327
/// \code
6301-
/// infix operator /+/ : AdditivePrecedence
6328+
/// infix operator /+/ : AdditionPrecedence, Numeric
63026329
/// \endcode
63036330
class InfixOperatorDecl : public OperatorDecl {
6304-
SourceLoc ColonLoc, PrecedenceGroupNameLoc;
6305-
Identifier PrecedenceGroupName;
6331+
SourceLoc ColonLoc, FirstIdentifierLoc, SecondIdentifierLoc;
6332+
Identifier FirstIdentifier, SecondIdentifier;
63066333
PrecedenceGroupDecl *PrecedenceGroup = nullptr;
63076334

63086335
public:
6309-
InfixOperatorDecl(DeclContext *DC,
6310-
SourceLoc operatorLoc,
6311-
Identifier name,
6312-
SourceLoc nameLoc,
6313-
SourceLoc colonLoc,
6314-
Identifier precedenceGroupName,
6315-
SourceLoc precedenceGroupNameLoc)
6316-
: OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc),
6317-
ColonLoc(colonLoc), PrecedenceGroupNameLoc(precedenceGroupNameLoc),
6318-
PrecedenceGroupName(precedenceGroupName) {
6319-
}
6336+
InfixOperatorDecl(DeclContext *DC, SourceLoc operatorLoc, Identifier name,
6337+
SourceLoc nameLoc, SourceLoc colonLoc,
6338+
Identifier firstIdentifier, SourceLoc firstIdentifierLoc,
6339+
Identifier secondIdentifier = Identifier(),
6340+
SourceLoc secondIdentifierLoc = SourceLoc())
6341+
: OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc),
6342+
ColonLoc(colonLoc), FirstIdentifierLoc(firstIdentifierLoc),
6343+
SecondIdentifierLoc(secondIdentifierLoc),
6344+
FirstIdentifier(firstIdentifier), SecondIdentifier(secondIdentifier) {}
63206345

63216346
SourceLoc getEndLoc() const {
6322-
if (PrecedenceGroupName.empty())
6323-
return getNameLoc();
6324-
return PrecedenceGroupNameLoc;
6347+
if (!SecondIdentifier.empty())
6348+
return SecondIdentifierLoc;
6349+
if (!FirstIdentifier.empty())
6350+
return FirstIdentifierLoc;
6351+
return getNameLoc();
63256352
}
63266353
SourceRange getSourceRange() const {
63276354
return { getOperatorLoc(), getEndLoc() };
63286355
}
6329-
6356+
63306357
SourceLoc getColonLoc() const { return ColonLoc; }
6331-
SourceLoc getPrecedenceGroupNameLoc() const { return PrecedenceGroupNameLoc; }
6358+
SourceLoc getFirstIdentifierLoc() const { return FirstIdentifierLoc; }
6359+
SourceLoc getSecondIdentifierLoc() const { return SecondIdentifierLoc; }
6360+
6361+
Identifier getFirstIdentifier() const { return FirstIdentifier; }
6362+
Identifier getSecondIdentifier() const { return SecondIdentifier; }
63326363

6333-
Identifier getPrecedenceGroupName() const { return PrecedenceGroupName; }
63346364
PrecedenceGroupDecl *getPrecedenceGroup() const { return PrecedenceGroup; }
63356365
void setPrecedenceGroup(PrecedenceGroupDecl *PGD) {
63366366
PrecedenceGroup = PGD;
@@ -6355,8 +6385,11 @@ class InfixOperatorDecl : public OperatorDecl {
63556385
class PrefixOperatorDecl : public OperatorDecl {
63566386
public:
63576387
PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
6358-
SourceLoc NameLoc)
6359-
: OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc) {}
6388+
SourceLoc NameLoc,
6389+
Identifier DesignatedProtocolName = Identifier(),
6390+
SourceLoc DesignatedProtocolNameLoc = SourceLoc())
6391+
: OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc,
6392+
DesignatedProtocolName, DesignatedProtocolNameLoc) {}
63606393

63616394
SourceRange getSourceRange() const {
63626395
return { getOperatorLoc(), getNameLoc() };
@@ -6381,9 +6414,12 @@ class PrefixOperatorDecl : public OperatorDecl {
63816414
class PostfixOperatorDecl : public OperatorDecl {
63826415
public:
63836416
PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
6384-
SourceLoc NameLoc)
6385-
: OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc) {}
6386-
6417+
SourceLoc NameLoc,
6418+
Identifier DesignatedProtocolName = Identifier(),
6419+
SourceLoc DesignatedProtocolNameLoc = SourceLoc())
6420+
: OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc,
6421+
DesignatedProtocolName, DesignatedProtocolNameLoc) {}
6422+
63876423
SourceRange getSourceRange() const {
63886424
return { getOperatorLoc(), getNameLoc() };
63896425
}

include/swift/AST/DiagnosticsParse.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -431,6 +431,9 @@ ERROR(deprecated_operator_body_use_group,PointsToFirstBadToken,
431431
ERROR(operator_decl_no_fixity,none,
432432
"operator must be declared as 'prefix', 'postfix', or 'infix'", ())
433433

434+
ERROR(operator_decl_trailing_comma,none,
435+
"expected designated protocol in operator declaration", ())
436+
434437
// PrecedenceGroup
435438
ERROR(precedencegroup_not_infix,none,
436439
"only infix operators may declare a precedence", ())

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,9 @@ ERROR(unspaced_unary_operator,none,
706706
"unary operators must not be juxtaposed; parenthesize inner expression",
707707
())
708708

709+
ERROR(operators_designated_protocol_not_a_protocol,none,
710+
"type %0 unexpected; expected a protocol type",
711+
(Type))
709712

710713
ERROR(use_unresolved_identifier,none,
711714
"use of unresolved %select{identifier|operator}1 %0", (DeclName, bool))

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ namespace swift {
203203
/// \brief Enable experimental property behavior feature.
204204
bool EnableExperimentalPropertyBehaviors = false;
205205

206+
/// \brief Enable experimental operator protocol designator feature.
207+
bool EnableOperatorDesignatedProtocols = false;
208+
206209
/// \brief Staging flag for treating inout parameters as Thread Sanitizer
207210
/// accesses.
208211
bool DisableTsanInoutInstrumentation = false;

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,10 @@ def enable_experimental_property_behaviors :
309309
Flag<["-"], "enable-experimental-property-behaviors">,
310310
HelpText<"Enable experimental property behaviors">;
311311

312+
def enable_operator_designated_protocols :
313+
Flag<["-"], "enable-operator-designated-protocols">,
314+
HelpText<"Enable operator designated protocols">;
315+
312316
def enable_deserialization_recovery :
313317
Flag<["-"], "enable-deserialization-recovery">,
314318
HelpText<"Attempt to recover from missing xrefs (etc) in swiftmodules">;

lib/AST/ASTDumper.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -1177,8 +1177,14 @@ namespace {
11771177
printCommon(IOD, "infix_operator_decl ");
11781178
OS << IOD->getName() << "\n";
11791179
OS.indent(Indent+2);
1180-
OS << "precedence " << IOD->getPrecedenceGroupName();
1181-
if (!IOD->getPrecedenceGroup()) OS << " <null>";
1180+
if (!IOD->getFirstIdentifier().empty())
1181+
OS << "first identifier " << IOD->getFirstIdentifier();
1182+
else
1183+
OS << "first identifier <null>";
1184+
if (!IOD->getSecondIdentifier().empty())
1185+
OS << "second identifier " << IOD->getSecondIdentifier();
1186+
else
1187+
OS << "second identifier <null>";
11821188
PrintWithColorRAII(OS, ParenthesisColor) << ')';
11831189
}
11841190

lib/AST/ASTPrinter.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2825,9 +2825,10 @@ void PrintAST::visitInfixOperatorDecl(InfixOperatorDecl *decl) {
28252825
[&]{
28262826
Printer.printName(decl->getName());
28272827
});
2828-
if (!decl->getPrecedenceGroupName().empty()) {
2829-
Printer << " : " << decl->getPrecedenceGroupName();
2830-
}
2828+
if (!decl->getFirstIdentifier().empty())
2829+
Printer << " : " << decl->getFirstIdentifier();
2830+
if (!decl->getSecondIdentifier().empty())
2831+
Printer << ", " << decl->getSecondIdentifier();
28312832
}
28322833

28332834
void PrintAST::visitPrecedenceGroupDecl(PrecedenceGroupDecl *decl) {
@@ -2900,6 +2901,8 @@ void PrintAST::visitPrefixOperatorDecl(PrefixOperatorDecl *decl) {
29002901
[&]{
29012902
Printer.printName(decl->getName());
29022903
});
2904+
if (!decl->getDesignatedProtocolName().empty())
2905+
Printer << " : " << decl->getDesignatedProtocolName();
29032906
}
29042907

29052908
void PrintAST::visitPostfixOperatorDecl(PostfixOperatorDecl *decl) {
@@ -2909,6 +2912,8 @@ void PrintAST::visitPostfixOperatorDecl(PostfixOperatorDecl *decl) {
29092912
[&]{
29102913
Printer.printName(decl->getName());
29112914
});
2915+
if (!decl->getDesignatedProtocolName().empty())
2916+
Printer << " : " << decl->getDesignatedProtocolName();
29122917
}
29132918

29142919
void PrintAST::visitModuleDecl(ModuleDecl *decl) { }

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
161161
Opts.EnableExperimentalPropertyBehaviors |=
162162
Args.hasArg(OPT_enable_experimental_property_behaviors);
163163

164+
Opts.EnableOperatorDesignatedProtocols |=
165+
Args.hasArg(OPT_enable_operator_designated_protocols);
166+
164167
if (auto A = Args.getLastArg(OPT_enable_deserialization_recovery,
165168
OPT_disable_deserialization_recovery)) {
166169
Opts.EnableDeserializationRecovery

lib/Parse/ParseDecl.cpp

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -6426,21 +6426,41 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
64266426
bool isPrefix = Attributes.hasAttribute<PrefixAttr>();
64276427
bool isInfix = Attributes.hasAttribute<InfixAttr>();
64286428
bool isPostfix = Attributes.hasAttribute<PostfixAttr>();
6429-
6430-
// Parse (or diagnose) a specified precedence group.
6429+
6430+
// Parse (or diagnose) a specified precedence group and/or
6431+
// designated protocol. These both look like identifiers, so we
6432+
// parse them both as identifiers here and sort it out in type
6433+
// checking.
64316434
SourceLoc colonLoc;
6432-
Identifier precedenceGroupName;
6433-
SourceLoc precedenceGroupNameLoc;
6435+
Identifier firstIdentifierName;
6436+
SourceLoc firstIdentifierNameLoc;
6437+
Identifier secondIdentifierName;
6438+
SourceLoc secondIdentifierNameLoc;
64346439
if (Tok.is(tok::colon)) {
64356440
SyntaxParsingContext GroupCtxt(SyntaxContext, SyntaxKind::InfixOperatorGroup);
64366441
colonLoc = consumeToken();
64376442
if (Tok.is(tok::identifier)) {
6438-
precedenceGroupName = Context.getIdentifier(Tok.getText());
6439-
precedenceGroupNameLoc = consumeToken(tok::identifier);
6440-
6441-
if (isPrefix || isPostfix)
6443+
firstIdentifierName = Context.getIdentifier(Tok.getText());
6444+
firstIdentifierNameLoc = consumeToken(tok::identifier);
6445+
6446+
if (Context.LangOpts.EnableOperatorDesignatedProtocols) {
6447+
if (consumeIf(tok::comma)) {
6448+
if (isPrefix || isPostfix)
6449+
diagnose(colonLoc, diag::precedencegroup_not_infix)
6450+
.fixItRemove({colonLoc, firstIdentifierNameLoc});
6451+
6452+
if (Tok.is(tok::identifier)) {
6453+
secondIdentifierName = Context.getIdentifier(Tok.getText());
6454+
secondIdentifierNameLoc = consumeToken(tok::identifier);
6455+
} else {
6456+
auto otherTokLoc = consumeToken();
6457+
diagnose(otherTokLoc, diag::operator_decl_trailing_comma);
6458+
}
6459+
}
6460+
} else if (isPrefix || isPostfix) {
64426461
diagnose(colonLoc, diag::precedencegroup_not_infix)
6443-
.fixItRemove({colonLoc, precedenceGroupNameLoc});
6462+
.fixItRemove({colonLoc, firstIdentifierNameLoc});
6463+
}
64446464
}
64456465
}
64466466

@@ -6452,7 +6472,7 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
64526472
} else {
64536473
auto Diag = diagnose(lBraceLoc, diag::deprecated_operator_body);
64546474
if (Tok.is(tok::r_brace)) {
6455-
SourceLoc lastGoodLoc = precedenceGroupNameLoc;
6475+
SourceLoc lastGoodLoc = firstIdentifierNameLoc;
64566476
if (lastGoodLoc.isInvalid())
64576477
lastGoodLoc = NameLoc;
64586478
SourceLoc lastGoodLocEnd = Lexer::getLocForEndOfToken(SourceMgr,
@@ -6468,17 +6488,19 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
64686488

64696489
OperatorDecl *res;
64706490
if (Attributes.hasAttribute<PrefixAttr>())
6471-
res = new (Context) PrefixOperatorDecl(CurDeclContext, OperatorLoc,
6472-
Name, NameLoc);
6491+
res = new (Context)
6492+
PrefixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc,
6493+
firstIdentifierName, firstIdentifierNameLoc);
64736494
else if (Attributes.hasAttribute<PostfixAttr>())
6474-
res = new (Context) PostfixOperatorDecl(CurDeclContext, OperatorLoc,
6475-
Name, NameLoc);
6495+
res = new (Context)
6496+
PostfixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc,
6497+
firstIdentifierName, firstIdentifierNameLoc);
64766498
else
6477-
res = new (Context) InfixOperatorDecl(CurDeclContext, OperatorLoc,
6478-
Name, NameLoc, colonLoc,
6479-
precedenceGroupName,
6480-
precedenceGroupNameLoc);
6481-
6499+
res = new (Context)
6500+
InfixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc, colonLoc,
6501+
firstIdentifierName, firstIdentifierNameLoc,
6502+
secondIdentifierName, secondIdentifierNameLoc);
6503+
64826504
diagnoseOperatorFixityAttributes(*this, Attributes, res);
64836505

64846506
res->getAttrs() = Attributes;

0 commit comments

Comments
 (0)