Skip to content

Commit 36284ba

Browse files
committed
Extend operator decls to allow any designated nominal type for lookup.
Rather than limiting this to protocols, allow any nominal type. Rename -enable-operator-designated-protocols to -enable-operator-designated-types to reflect the change.
1 parent f9a2d90 commit 36284ba

24 files changed

+120
-129
lines changed

include/swift/AST/Decl.h

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6383,43 +6383,45 @@ class OperatorDecl : public Decl {
63836383

63846384
Identifier name;
63856385

6386-
Identifier DesignatedProtocolName;
6387-
SourceLoc DesignatedProtocolNameLoc;
6388-
ProtocolDecl *DesignatedProtocol = nullptr;
6386+
Identifier DesignatedNominalTypeName;
6387+
SourceLoc DesignatedNominalTypeNameLoc;
6388+
NominalTypeDecl *DesignatedNominalType = nullptr;
63896389

63906390
public:
63916391
OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc,
63926392
Identifier Name, SourceLoc NameLoc,
6393-
Identifier DesignatedProtocolName = Identifier(),
6394-
SourceLoc DesignatedProtocolNameLoc = SourceLoc())
6393+
Identifier DesignatedNominalTypeName = Identifier(),
6394+
SourceLoc DesignatedNominalTypeNameLoc = SourceLoc())
63956395
: Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name),
6396-
DesignatedProtocolName(DesignatedProtocolName),
6397-
DesignatedProtocolNameLoc(DesignatedProtocolNameLoc) {}
6396+
DesignatedNominalTypeName(DesignatedNominalTypeName),
6397+
DesignatedNominalTypeNameLoc(DesignatedNominalTypeNameLoc) {}
63986398

63996399
OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc,
64006400
Identifier Name, SourceLoc NameLoc,
6401-
ProtocolDecl *DesignatedProtocol)
6401+
NominalTypeDecl *DesignatedNominalType)
64026402
: Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name),
6403-
DesignatedProtocol(DesignatedProtocol) {}
6403+
DesignatedNominalType(DesignatedNominalType) {}
64046404

64056405
SourceLoc getLoc() const { return NameLoc; }
64066406

64076407
SourceLoc getOperatorLoc() const { return OperatorLoc; }
64086408
SourceLoc getNameLoc() const { return NameLoc; }
64096409
Identifier getName() const { return name; }
64106410

6411-
Identifier getDesignatedProtocolName() const {
6412-
return DesignatedProtocolName;
6411+
Identifier getDesignatedNominalTypeName() const {
6412+
return DesignatedNominalTypeName;
64136413
}
64146414

6415-
SourceLoc getDesignatedProtocolNameLoc() const {
6416-
return DesignatedProtocolNameLoc;
6415+
SourceLoc getDesignatedNominalTypeNameLoc() const {
6416+
return DesignatedNominalTypeNameLoc;
64176417
}
64186418

6419-
ProtocolDecl *getDesignatedProtocol() const { return DesignatedProtocol; }
6419+
NominalTypeDecl *getDesignatedNominalType() const {
6420+
return DesignatedNominalType;
6421+
}
64206422

6421-
void setDesignatedProtocol(ProtocolDecl *protocol) {
6422-
DesignatedProtocol = protocol;
6423+
void setDesignatedNominalType(NominalTypeDecl *nominal) {
6424+
DesignatedNominalType = nominal;
64236425
}
64246426

64256427
static bool classof(const Decl *D) {
@@ -6455,9 +6457,9 @@ class InfixOperatorDecl : public OperatorDecl {
64556457
InfixOperatorDecl(DeclContext *DC, SourceLoc operatorLoc, Identifier name,
64566458
SourceLoc nameLoc, SourceLoc colonLoc,
64576459
Identifier firstIdentifier, SourceLoc firstIdentifierLoc,
6458-
ProtocolDecl *designatedProtocol)
6460+
NominalTypeDecl *designatedNominalType)
64596461
: OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc,
6460-
designatedProtocol),
6462+
designatedNominalType),
64616463
ColonLoc(colonLoc), FirstIdentifierLoc(firstIdentifierLoc),
64626464
FirstIdentifier(firstIdentifier) {}
64636465

@@ -6504,15 +6506,15 @@ class PrefixOperatorDecl : public OperatorDecl {
65046506
public:
65056507
PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
65066508
SourceLoc NameLoc,
6507-
Identifier DesignatedProtocolName = Identifier(),
6508-
SourceLoc DesignatedProtocolNameLoc = SourceLoc())
6509+
Identifier DesignatedNominalTypeName = Identifier(),
6510+
SourceLoc DesignatedNominalTypeNameLoc = SourceLoc())
65096511
: OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc,
6510-
DesignatedProtocolName, DesignatedProtocolNameLoc) {}
6512+
DesignatedNominalTypeName, DesignatedNominalTypeNameLoc) {}
65116513

65126514
PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
6513-
SourceLoc NameLoc, ProtocolDecl *DesignatedProtocol)
6515+
SourceLoc NameLoc, NominalTypeDecl *DesignatedNominalType)
65146516
: OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc,
6515-
DesignatedProtocol) {}
6517+
DesignatedNominalType) {}
65166518

65176519
SourceRange getSourceRange() const {
65186520
return { getOperatorLoc(), getNameLoc() };
@@ -6538,15 +6540,15 @@ class PostfixOperatorDecl : public OperatorDecl {
65386540
public:
65396541
PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
65406542
SourceLoc NameLoc,
6541-
Identifier DesignatedProtocolName = Identifier(),
6542-
SourceLoc DesignatedProtocolNameLoc = SourceLoc())
6543+
Identifier DesignatedNominalTypeName = Identifier(),
6544+
SourceLoc DesignatedNominalTypeNameLoc = SourceLoc())
65436545
: OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc,
6544-
DesignatedProtocolName, DesignatedProtocolNameLoc) {}
6546+
DesignatedNominalTypeName, DesignatedNominalTypeNameLoc) {}
65456547

65466548
PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
6547-
SourceLoc NameLoc, ProtocolDecl *DesignatedProtocol)
6549+
SourceLoc NameLoc, NominalTypeDecl *DesignatedNominalType)
65486550
: OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc,
6549-
DesignatedProtocol) {}
6551+
DesignatedNominalType) {}
65506552

65516553
SourceRange getSourceRange() const {
65526554
return { getOperatorLoc(), getNameLoc() };

include/swift/AST/DiagnosticsParse.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ ERROR(operator_decl_no_fixity,none,
432432
"operator must be declared as 'prefix', 'postfix', or 'infix'", ())
433433

434434
ERROR(operator_decl_trailing_comma,none,
435-
"expected designated protocol in operator declaration", ())
435+
"expected designated type in operator declaration", ())
436436

437437
// PrecedenceGroup
438438
ERROR(precedencegroup_not_infix,none,

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -706,10 +706,6 @@ 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))
712-
713709
ERROR(use_unresolved_identifier,none,
714710
"use of unresolved %select{identifier|operator}1 %0", (DeclName, bool))
715711
ERROR(use_unresolved_identifier_corrected,none,

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,12 +193,12 @@ namespace swift {
193193
/// Disable constraint system performance hacks.
194194
bool DisableConstraintSolverPerformanceHacks = false;
195195

196-
/// \brief Enable experimental operator protocol designator feature.
197-
bool EnableOperatorDesignatedProtocols = false;
196+
/// \brief Enable experimental operator designated types feature.
197+
bool EnableOperatorDesignatedTypes = false;
198198

199199
/// \brief Enable constraint solver support for experimental
200200
/// operator protocol designator feature.
201-
bool SolverEnableOperatorDesignatedProtocols = false;
201+
bool SolverEnableOperatorDesignatedTypes = false;
202202

203203
/// The maximum depth to which to test decl circularity.
204204
unsigned MaxCircularityDepth = 500;

include/swift/Option/FrontendOptions.td

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -373,13 +373,13 @@ def solver_disable_shrink :
373373
def disable_constraint_solver_performance_hacks : Flag<["-"], "disable-constraint-solver-performance-hacks">,
374374
HelpText<"Disable all the hacks in the constraint solver">;
375375

376-
def enable_operator_designated_protocols :
377-
Flag<["-"], "enable-operator-designated-protocols">,
378-
HelpText<"Enable operator designated protocols">;
376+
def enable_operator_designated_types :
377+
Flag<["-"], "enable-operator-designated-types">,
378+
HelpText<"Enable operator designated types">;
379379

380-
def solver_enable_operator_designated_protocols :
381-
Flag<["-"], "solver-enable-operator-designated-protocols">,
382-
HelpText<"Enable operator designated protocols in constraint solver">;
380+
def solver_enable_operator_designated_types :
381+
Flag<["-"], "solver-enable-operator-designated-types">,
382+
HelpText<"Enable operator designated types in constraint solver">;
383383

384384
def switch_checking_invocation_threshold_EQ : Joined<["-"],
385385
"switch-checking-invocation-threshold=">;

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
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 = 451; // Last change: pattern initializer text
58+
const uint16_t VERSION_MINOR = 452; // Last change: nominal types for operators
5959

6060
using DeclIDField = BCFixed<31>;
6161

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2949,8 +2949,8 @@ void PrintAST::visitPrefixOperatorDecl(PrefixOperatorDecl *decl) {
29492949
[&]{
29502950
Printer.printName(decl->getName());
29512951
});
2952-
if (!decl->getDesignatedProtocolName().empty())
2953-
Printer << " : " << decl->getDesignatedProtocolName();
2952+
if (!decl->getDesignatedNominalTypeName().empty())
2953+
Printer << " : " << decl->getDesignatedNominalTypeName();
29542954
}
29552955

29562956
void PrintAST::visitPostfixOperatorDecl(PostfixOperatorDecl *decl) {
@@ -2960,8 +2960,8 @@ void PrintAST::visitPostfixOperatorDecl(PostfixOperatorDecl *decl) {
29602960
[&]{
29612961
Printer.printName(decl->getName());
29622962
});
2963-
if (!decl->getDesignatedProtocolName().empty())
2964-
Printer << " : " << decl->getDesignatedProtocolName();
2963+
if (!decl->getDesignatedNominalTypeName().empty())
2964+
Printer << " : " << decl->getDesignatedNominalTypeName();
29652965
}
29662966

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

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,11 @@ 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);
164+
Opts.EnableOperatorDesignatedTypes |=
165+
Args.hasArg(OPT_enable_operator_designated_types);
166166

167-
Opts.SolverEnableOperatorDesignatedProtocols |=
168-
Args.hasArg(OPT_solver_enable_operator_designated_protocols);
167+
Opts.SolverEnableOperatorDesignatedTypes |=
168+
Args.hasArg(OPT_solver_enable_operator_designated_types);
169169

170170
if (auto A = Args.getLastArg(OPT_enable_deserialization_recovery,
171171
OPT_disable_deserialization_recovery)) {

lib/Parse/ParseDecl.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6503,11 +6503,12 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
65036503
if (Tok.is(tok::colon)) {
65046504
SyntaxParsingContext GroupCtxt(SyntaxContext, SyntaxKind::InfixOperatorGroup);
65056505
colonLoc = consumeToken();
6506-
if (Tok.is(tok::identifier)) {
6507-
firstIdentifierName = Context.getIdentifier(Tok.getText());
6508-
firstIdentifierNameLoc = consumeToken(tok::identifier);
65096506

6510-
if (Context.LangOpts.EnableOperatorDesignatedProtocols) {
6507+
if (Context.LangOpts.EnableOperatorDesignatedTypes) {
6508+
if (Tok.is(tok::identifier)) {
6509+
firstIdentifierName = Context.getIdentifier(Tok.getText());
6510+
firstIdentifierNameLoc = consumeToken(tok::identifier);
6511+
65116512
if (consumeIf(tok::comma)) {
65126513
if (isPrefix || isPostfix)
65136514
diagnose(colonLoc, diag::precedencegroup_not_infix)
@@ -6521,7 +6522,12 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
65216522
diagnose(otherTokLoc, diag::operator_decl_trailing_comma);
65226523
}
65236524
}
6524-
} else if (isPrefix || isPostfix) {
6525+
}
6526+
} else if (Tok.is(tok::identifier)) {
6527+
firstIdentifierName = Context.getIdentifier(Tok.getText());
6528+
firstIdentifierNameLoc = consumeToken(tok::identifier);
6529+
6530+
if (isPrefix || isPostfix) {
65256531
diagnose(colonLoc, diag::precedencegroup_not_infix)
65266532
.fixItRemove({colonLoc, firstIdentifierNameLoc});
65276533
}

lib/Sema/CSSolver.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,11 +1629,12 @@ static bool isOperatorBindOverload(Constraint *bindOverload) {
16291629
// Given a bind overload constraint for an operator, return the
16301630
// protocol designated as the first place to look for overloads of the
16311631
// operator.
1632-
static ProtocolDecl *getOperatorDesignatedProtocol(Constraint *bindOverload) {
1632+
static NominalTypeDecl *
1633+
getOperatorDesignatedNominalType(Constraint *bindOverload) {
16331634
auto choice = bindOverload->getOverloadChoice();
16341635
auto *funcDecl = cast<FuncDecl>(choice.getDecl());
16351636
auto *operatorDecl = funcDecl->getOperatorDecl();
1636-
return operatorDecl->getDesignatedProtocol();
1637+
return operatorDecl->getDesignatedNominalType();
16371638
}
16381639

16391640
void ConstraintSystem::partitionDisjunction(
@@ -1649,7 +1650,7 @@ void ConstraintSystem::partitionDisjunction(
16491650
};
16501651

16511652
if (!getASTContext().isSwiftVersionAtLeast(5) ||
1652-
!TC.getLangOpts().SolverEnableOperatorDesignatedProtocols ||
1653+
!TC.getLangOpts().SolverEnableOperatorDesignatedTypes ||
16531654
!isOperatorBindOverload(Choices[0])) {
16541655
originalOrdering();
16551656
return;
@@ -1720,21 +1721,21 @@ void ConstraintSystem::partitionDisjunction(
17201721

17211722
// Now collect the overload choices that are defined within the type
17221723
// that was designated in the operator declaration.
1723-
auto *designatedProtocol = getOperatorDesignatedProtocol(Choices[0]);
1724-
if (designatedProtocol) {
1724+
auto *designatedNominal = getOperatorDesignatedNominalType(Choices[0]);
1725+
if (designatedNominal) {
17251726
forEachChoice(Choices, [&](unsigned index, Constraint *constraint) -> bool {
17261727
auto *decl = constraint->getOverloadChoice().getDecl();
17271728
auto *funcDecl = cast<FuncDecl>(decl);
17281729

17291730
auto *parentDecl = funcDecl->getParent()->getAsDecl();
1730-
if (parentDecl == designatedProtocol) {
1731+
if (parentDecl == designatedNominal) {
17311732
definedInDesignatedType.push_back(index);
17321733
return true;
17331734
}
17341735

17351736
if (auto *extensionDecl = dyn_cast<ExtensionDecl>(parentDecl)) {
17361737
parentDecl = extensionDecl->getExtendedNominal();
1737-
if (parentDecl == designatedProtocol) {
1738+
if (parentDecl == designatedNominal) {
17381739
definedInExtensionOfDesignatedType.push_back(index);
17391740
return true;
17401741
}

lib/Sema/TypeCheckDecl.cpp

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,9 +2061,9 @@ PrecedenceGroupDecl *TypeChecker::lookupPrecedenceGroup(DeclContext *dc,
20612061
return group;
20622062
}
20632063

2064-
static void checkDesignatedProtocol(OperatorDecl *OD, Identifier name,
2065-
SourceLoc loc, TypeChecker &tc,
2066-
ASTContext &ctx) {
2064+
static void checkDesignatedTypes(OperatorDecl *OD, Identifier name,
2065+
SourceLoc loc, TypeChecker &tc,
2066+
ASTContext &ctx) {
20672067
auto *dc = OD->getDeclContext();
20682068
auto *TyR = new (ctx) SimpleIdentTypeRepr(loc, name);
20692069
TypeLoc typeLoc = TypeLoc(TyR);
@@ -2074,17 +2074,11 @@ static void checkDesignatedProtocol(OperatorDecl *OD, Identifier name,
20742074
}
20752075

20762076
if (!typeLoc.isError()) {
2077-
auto *decl = typeLoc.getType()->getNominalOrBoundGenericNominal();
2078-
if (!decl || !isa<ProtocolDecl>(decl)) {
2079-
tc.diagnose(typeLoc.getLoc(),
2080-
diag::operators_designated_protocol_not_a_protocol,
2081-
typeLoc.getType());
2082-
OD->setInvalid();
2083-
} else {
2084-
OD->setDesignatedProtocol(cast<ProtocolDecl>(decl));
2085-
// FIXME: verify this operator has a declaration within this
2086-
// protocol with the same arity and fixity
2087-
}
2077+
auto *decl = typeLoc.getType()->getAnyNominal();
2078+
assert(decl);
2079+
OD->setDesignatedNominalType(decl);
2080+
// FIXME: verify this operator has a declaration within this
2081+
// protocol with the same arity and fixity
20882082
}
20892083
}
20902084

@@ -2099,17 +2093,16 @@ void TypeChecker::validateDecl(OperatorDecl *OD) {
20992093

21002094
auto IOD = dyn_cast<InfixOperatorDecl>(OD);
21012095

2102-
auto enableOperatorDesignatedProtocols =
2103-
getLangOpts().EnableOperatorDesignatedProtocols;
2096+
auto enableOperatorDesignatedTypes =
2097+
getLangOpts().EnableOperatorDesignatedTypes;
21042098

21052099
// Pre- or post-fix operator?
21062100
if (!IOD) {
2107-
auto *protocol = OD->getDesignatedProtocol();
2108-
auto protocolId = OD->getDesignatedProtocolName();
2109-
if (!protocol && !protocolId.empty() &&
2110-
enableOperatorDesignatedProtocols) {
2111-
auto protocolIdLoc = OD->getDesignatedProtocolNameLoc();
2112-
checkDesignatedProtocol(OD, protocolId, protocolIdLoc, *this, Context);
2101+
auto *protocol = OD->getDesignatedNominalType();
2102+
auto protocolId = OD->getDesignatedNominalTypeName();
2103+
if (!protocol && !protocolId.empty() && enableOperatorDesignatedTypes) {
2104+
auto protocolIdLoc = OD->getDesignatedNominalTypeNameLoc();
2105+
checkDesignatedTypes(OD, protocolId, protocolIdLoc, *this, Context);
21132106
}
21142107
return;
21152108
}
@@ -2127,20 +2120,20 @@ void TypeChecker::validateDecl(OperatorDecl *OD) {
21272120
}
21282121

21292122
auto secondId = IOD->getSecondIdentifier();
2130-
auto *protocol = IOD->getDesignatedProtocol();
2131-
if (!protocol && enableOperatorDesignatedProtocols) {
2123+
auto *protocol = IOD->getDesignatedNominalType();
2124+
if (!protocol && enableOperatorDesignatedTypes) {
21322125
auto secondIdLoc = IOD->getSecondIdentifierLoc();
21332126
assert(secondId.empty() || !firstId.empty());
21342127

21352128
auto protocolId = group ? secondId : firstId;
21362129
auto protocolIdLoc = group ? secondIdLoc : firstIdLoc;
21372130
if (!protocolId.empty())
2138-
checkDesignatedProtocol(IOD, protocolId, protocolIdLoc, *this, Context);
2131+
checkDesignatedTypes(IOD, protocolId, protocolIdLoc, *this, Context);
21392132
}
21402133

21412134
if (!group && !IOD->isInvalid()) {
21422135
if (!firstId.empty() &&
2143-
(!secondId.empty() || !IOD->getDesignatedProtocol())) {
2136+
(!secondId.empty() || !IOD->getDesignatedNominalType())) {
21442137
diagnose(firstIdLoc, diag::unknown_precedence_group, firstId);
21452138
IOD->setInvalid();
21462139
}

0 commit comments

Comments
 (0)