Skip to content

Commit 7033412

Browse files
committed
Add support for multiple designated types for an operator declaration.
Add parsing, type checking, serialization, and deserialization support for specifying multiple types as "designated" for operator lookup for a given operator declaration. The constraint solver still considers only the first type when deciding the order to attempt the elements of a disjunction, so this doesn't really change behavior yet.
1 parent e252970 commit 7033412

File tree

11 files changed

+205
-135
lines changed

11 files changed

+205
-135
lines changed

include/swift/AST/Decl.h

Lines changed: 21 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6382,7 +6382,7 @@ class OperatorDecl : public Decl {
63826382

63836383
ArrayRef<Identifier> Identifiers;
63846384
ArrayRef<SourceLoc> IdentifierLocs;
6385-
NominalTypeDecl *DesignatedNominalType = nullptr;
6385+
ArrayRef<NominalTypeDecl *> DesignatedNominalTypes;
63866386

63876387
public:
63886388
OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc,
@@ -6394,9 +6394,9 @@ class OperatorDecl : public Decl {
63946394

63956395
OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc,
63966396
Identifier Name, SourceLoc NameLoc,
6397-
NominalTypeDecl *DesignatedNominalType)
6397+
ArrayRef<NominalTypeDecl *> DesignatedNominalTypes)
63986398
: Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name),
6399-
DesignatedNominalType(DesignatedNominalType) {}
6399+
DesignatedNominalTypes(DesignatedNominalTypes) {}
64006400

64016401
SourceLoc getLoc() const { return NameLoc; }
64026402

@@ -6420,12 +6420,12 @@ class OperatorDecl : public Decl {
64206420
return !IdentifierLocs.empty() ? IdentifierLocs[0] : SourceLoc();
64216421
}
64226422

6423-
NominalTypeDecl *getDesignatedNominalType() const {
6424-
return DesignatedNominalType;
6423+
ArrayRef<NominalTypeDecl *> getDesignatedNominalTypes() const {
6424+
return DesignatedNominalTypes;
64256425
}
64266426

6427-
void setDesignatedNominalType(NominalTypeDecl *nominal) {
6428-
DesignatedNominalType = nominal;
6427+
void setDesignatedNominalTypes(ArrayRef<NominalTypeDecl *> nominalTypes) {
6428+
DesignatedNominalTypes = nominalTypes;
64296429
}
64306430

64316431
static bool classof(const Decl *D) {
@@ -6458,40 +6458,24 @@ class InfixOperatorDecl : public OperatorDecl {
64586458
InfixOperatorDecl(DeclContext *DC, SourceLoc operatorLoc, Identifier name,
64596459
SourceLoc nameLoc, SourceLoc colonLoc,
64606460
PrecedenceGroupDecl *precedenceGroup,
6461-
NominalTypeDecl *designatedNominalType)
6461+
ArrayRef<NominalTypeDecl *> designatedNominalTypes)
64626462
: OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc,
6463-
designatedNominalType),
6463+
designatedNominalTypes),
64646464
ColonLoc(colonLoc), PrecedenceGroup(precedenceGroup) {}
64656465

64666466
SourceLoc getEndLoc() const {
6467-
if (!getSecondIdentifier().empty())
6468-
return getSecondIdentifierLoc();
6469-
if (!getFirstIdentifier().empty())
6470-
return getFirstIdentifierLoc();
6471-
return getNameLoc();
6467+
auto identifierLocs = getIdentifierLocs();
6468+
if (identifierLocs.empty())
6469+
return getNameLoc();
6470+
6471+
return identifierLocs.back();
64726472
}
6473+
64736474
SourceRange getSourceRange() const {
64746475
return { getOperatorLoc(), getEndLoc() };
64756476
}
64766477

64776478
SourceLoc getColonLoc() const { return ColonLoc; }
6478-
SourceLoc getFirstIdentifierLoc() const {
6479-
auto identifierLocs = getIdentifierLocs();
6480-
return !identifierLocs.empty() ? identifierLocs[0] : SourceLoc();
6481-
}
6482-
SourceLoc getSecondIdentifierLoc() const {
6483-
auto identifierLocs = getIdentifierLocs();
6484-
return identifierLocs.size() > 1 ? identifierLocs[1] : SourceLoc();
6485-
}
6486-
6487-
Identifier getFirstIdentifier() const {
6488-
auto identifiers = getIdentifiers();
6489-
return !identifiers.empty() ? identifiers[0] : Identifier();
6490-
}
6491-
Identifier getSecondIdentifier() const {
6492-
auto identifiers = getIdentifiers();
6493-
return identifiers.size() > 1 ? identifiers[1] : Identifier();
6494-
}
64956479

64966480
PrecedenceGroupDecl *getPrecedenceGroup() const { return PrecedenceGroup; }
64976481
void setPrecedenceGroup(PrecedenceGroupDecl *PGD) {
@@ -6524,9 +6508,10 @@ class PrefixOperatorDecl : public OperatorDecl {
65246508
Identifiers, IdentifierLocs) {}
65256509

65266510
PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
6527-
SourceLoc NameLoc, NominalTypeDecl *DesignatedNominalType)
6511+
SourceLoc NameLoc,
6512+
ArrayRef<NominalTypeDecl *> designatedNominalTypes)
65286513
: OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc,
6529-
DesignatedNominalType) {}
6514+
designatedNominalTypes) {}
65306515

65316516
SourceRange getSourceRange() const {
65326517
return { getOperatorLoc(), getNameLoc() };
@@ -6558,9 +6543,10 @@ class PostfixOperatorDecl : public OperatorDecl {
65586543
Identifiers, IdentifierLocs) {}
65596544

65606545
PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
6561-
SourceLoc NameLoc, NominalTypeDecl *DesignatedNominalType)
6546+
SourceLoc NameLoc,
6547+
ArrayRef<NominalTypeDecl *> designatedNominalTypes)
65626548
: OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc,
6563-
DesignatedNominalType) {}
6549+
designatedNominalTypes) {}
65646550

65656551
SourceRange getSourceRange() const {
65666552
return { getOperatorLoc(), getNameLoc() };

include/swift/AST/DiagnosticsParse.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
//===--- DiagnosticsParse.def - Diagnostics Text ----------------*- C++ -*-===//
23
//
34
// This source file is part of the Swift.org open source project
@@ -431,8 +432,10 @@ ERROR(deprecated_operator_body_use_group,PointsToFirstBadToken,
431432
ERROR(operator_decl_no_fixity,none,
432433
"operator must be declared as 'prefix', 'postfix', or 'infix'", ())
433434

434-
ERROR(operator_decl_trailing_comma,none,
435+
ERROR(operator_decl_expected_type,none,
435436
"expected designated type in operator declaration", ())
437+
ERROR(operator_decl_trailing_comma,none,
438+
"trailing comma in operator declaration", ())
436439

437440
// PrecedenceGroup
438441
ERROR(precedencegroup_not_infix,none,

include/swift/Serialization/ModuleFormat.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
5757
/// Don't worry about adhering to the 80-column limit for this line.
58-
const uint16_t VERSION_MINOR = 452; // Last change: nominal types for operators
58+
const uint16_t VERSION_MINOR = 453; // Last change: multiple nominal types for operators
5959

6060
using DeclIDField = BCFixed<31>;
6161

@@ -1099,7 +1099,7 @@ namespace decls_block {
10991099
Code, // ID field
11001100
IdentifierIDField, // name
11011101
DeclContextIDField, // context decl
1102-
DeclIDField // protocol
1102+
BCArray<DeclIDField> // designated types
11031103
>;
11041104

11051105
using PrefixOperatorLayout = UnaryOperatorLayout<PREFIX_OPERATOR_DECL>;
@@ -1110,7 +1110,7 @@ namespace decls_block {
11101110
IdentifierIDField, // name
11111111
DeclContextIDField,// context decl
11121112
DeclIDField, // precedence group
1113-
DeclIDField // protocol
1113+
BCArray<DeclIDField> // designated types
11141114
>;
11151115

11161116
using PrecedenceGroupLayout = BCRecordLayout<

lib/AST/ASTDumper.cpp

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,30 +1169,43 @@ namespace {
11691169
PrintWithColorRAII(OS, ParenthesisColor) << ')';
11701170
}
11711171

1172+
void printOperatorIdentifiers(OperatorDecl *OD) {
1173+
auto identifiers = OD->getIdentifiers();
1174+
for (auto index : indices(identifiers)) {
1175+
OS.indent(Indent + 2);
1176+
OS << "identifier #" << index << " " << identifiers[index];
1177+
if (index != identifiers.size() - 1)
1178+
OS << "\n";
1179+
}
1180+
}
1181+
11721182
void visitInfixOperatorDecl(InfixOperatorDecl *IOD) {
1173-
printCommon(IOD, "infix_operator_decl ");
1174-
OS << IOD->getName() << "\n";
1175-
OS.indent(Indent+2);
1176-
if (!IOD->getFirstIdentifier().empty())
1177-
OS << "first identifier " << IOD->getFirstIdentifier();
1178-
else
1179-
OS << "first identifier <null>";
1180-
if (!IOD->getSecondIdentifier().empty())
1181-
OS << "second identifier " << IOD->getSecondIdentifier();
1182-
else
1183-
OS << "second identifier <null>";
1183+
printCommon(IOD, "infix_operator_decl");
1184+
OS << " " << IOD->getName();
1185+
if (!IOD->getIdentifiers().empty()) {
1186+
OS << "\n";
1187+
printOperatorIdentifiers(IOD);
1188+
}
11841189
PrintWithColorRAII(OS, ParenthesisColor) << ')';
11851190
}
11861191

11871192
void visitPrefixOperatorDecl(PrefixOperatorDecl *POD) {
1188-
printCommon(POD, "prefix_operator_decl ");
1189-
OS << POD->getName();
1193+
printCommon(POD, "prefix_operator_decl");
1194+
OS << " " << POD->getName();
1195+
if (!POD->getIdentifiers().empty()) {
1196+
OS << "\n";
1197+
printOperatorIdentifiers(POD);
1198+
}
11901199
PrintWithColorRAII(OS, ParenthesisColor) << ')';
11911200
}
11921201

11931202
void visitPostfixOperatorDecl(PostfixOperatorDecl *POD) {
1194-
printCommon(POD, "postfix_operator_decl ");
1195-
OS << POD->getName();
1203+
printCommon(POD, "postfix_operator_decl");
1204+
OS << " " << POD->getName();
1205+
if (!POD->getIdentifiers().empty()) {
1206+
OS << "\n";
1207+
printOperatorIdentifiers(POD);
1208+
}
11961209
PrintWithColorRAII(OS, ParenthesisColor) << ')';
11971210
}
11981211

lib/AST/ASTPrinter.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2875,8 +2875,9 @@ void PrintAST::visitInfixOperatorDecl(InfixOperatorDecl *decl) {
28752875
});
28762876
if (auto *group = decl->getPrecedenceGroup())
28772877
Printer << " : " << group->getName();
2878-
if (!decl->getSecondIdentifier().empty())
2879-
Printer << ", " << decl->getSecondIdentifier();
2878+
auto designatedNominalTypes = decl->getDesignatedNominalTypes();
2879+
for (auto typeDecl : designatedNominalTypes)
2880+
Printer << ", " << typeDecl->getName();
28802881
}
28812882

28822883
void PrintAST::visitPrecedenceGroupDecl(PrecedenceGroupDecl *decl) {

lib/Parse/ParseDecl.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6508,17 +6508,19 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
65086508
identifiers.push_back(Context.getIdentifier(Tok.getText()));
65096509
identifierLocs.push_back(consumeToken(tok::identifier));
65106510

6511-
if (consumeIf(tok::comma)) {
6512-
if (isPrefix || isPostfix)
6513-
diagnose(colonLoc, diag::precedencegroup_not_infix)
6514-
.fixItRemove({colonLoc, identifierLocs.back()});
6511+
while (Tok.is(tok::comma)) {
6512+
auto comma = consumeToken();
65156513

65166514
if (Tok.is(tok::identifier)) {
65176515
identifiers.push_back(Context.getIdentifier(Tok.getText()));
65186516
identifierLocs.push_back(consumeToken(tok::identifier));
65196517
} else {
6520-
auto otherTokLoc = consumeToken();
6521-
diagnose(otherTokLoc, diag::operator_decl_trailing_comma);
6518+
if (Tok.isNot(tok::eof)) {
6519+
auto otherTokLoc = consumeToken();
6520+
diagnose(otherTokLoc, diag::operator_decl_expected_type);
6521+
} else {
6522+
diagnose(comma, diag::operator_decl_trailing_comma);
6523+
}
65226524
}
65236525
}
65246526
}

lib/Sema/CSSolver.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1634,7 +1634,8 @@ getOperatorDesignatedNominalType(Constraint *bindOverload) {
16341634
auto choice = bindOverload->getOverloadChoice();
16351635
auto *funcDecl = cast<FuncDecl>(choice.getDecl());
16361636
auto *operatorDecl = funcDecl->getOperatorDecl();
1637-
return operatorDecl->getDesignatedNominalType();
1637+
auto designatedTypes = operatorDecl->getDesignatedNominalTypes();
1638+
return !designatedTypes.empty() ? designatedTypes[0] : nullptr;
16381639
}
16391640

16401641
void ConstraintSystem::partitionDisjunction(

0 commit comments

Comments
 (0)