Skip to content

Commit 57cd250

Browse files
committed
Change "operator infix" to "infix operator" for consistency with the rest of the declaration
modifiers and with the func implementations of the operators. This resolves the rest of: <rdar://problem/17527000> change operator declarations from "operator prefix" to "prefix operator" & make operator a keyword Swift SVN r19931
1 parent 8991456 commit 57cd250

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+285
-294
lines changed

docs/LangRef.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,7 +1517,7 @@ <h4 id="expr-assign">Assignment operator</h4>
15171517

15181518
<pre class="example">
15191519
// Not valid Swift code
1520-
operator infix = {
1520+
infix operator = {
15211521
precedence 90
15221522
associativity right
15231523
}
@@ -1561,7 +1561,7 @@ <h4 id="expr-ternary">Ternary operator</h4>
15611561

15621562
<pre class="example">
15631563
// Not valid Swift code
1564-
operator infix ?...: {
1564+
infix operator ?...: {
15651565
precedence 100
15661566
associativity right
15671567
}
@@ -1598,7 +1598,7 @@ <h4 id="expr-cast">Cast operators</h4>
15981598

15991599
<pre class="example">
16001600
// Not valid Swift code
1601-
operator infix as {
1601+
infix operator as {
16021602
precedence 95
16031603
associativity none
16041604
}

include/swift/AST/Decl.h

Lines changed: 12 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4477,20 +4477,18 @@ class OperatorDecl : public Decl {
44774477
/// Declares the behavior of an infix operator. For example:
44784478
///
44794479
/// \code
4480-
/// operator infix /+/ {
4480+
/// infix operator /+/ {
44814481
/// associativity left
44824482
/// precedence 123
44834483
/// }
44844484
/// \endcode
44854485
class InfixOperatorDecl : public OperatorDecl {
4486-
SourceLoc InfixLoc,
4487-
AssociativityLoc, AssociativityValueLoc,
4486+
SourceLoc AssociativityLoc, AssociativityValueLoc,
44884487
PrecedenceLoc, PrecedenceValueLoc;
44894488

44904489
public:
44914490
InfixOperatorDecl(DeclContext *DC,
44924491
SourceLoc OperatorLoc,
4493-
SourceLoc InfixLoc,
44944492
Identifier Name,
44954493
SourceLoc NameLoc,
44964494
SourceLoc LBraceLoc,
@@ -4506,7 +4504,6 @@ class InfixOperatorDecl : public OperatorDecl {
45064504
NameLoc,
45074505
LBraceLoc,
45084506
RBraceLoc),
4509-
InfixLoc(InfixLoc),
45104507
AssociativityLoc(AssociativityLoc),
45114508
AssociativityValueLoc(AssociativityValueLoc),
45124509
PrecedenceLoc(PrecedenceLoc),
@@ -4520,7 +4517,6 @@ class InfixOperatorDecl : public OperatorDecl {
45204517
}
45214518
}
45224519

4523-
SourceLoc getInfixLoc() const { return InfixLoc; }
45244520
SourceLoc getAssociativityLoc() const { return AssociativityLoc; }
45254521
SourceLoc getAssociativityValueLoc() const { return AssociativityValueLoc; }
45264522
SourceLoc getPrecedenceLoc() const { return PrecedenceLoc; }
@@ -4554,28 +4550,16 @@ class InfixOperatorDecl : public OperatorDecl {
45544550
/// Declares the behavior of a prefix operator. For example:
45554551
///
45564552
/// \code
4557-
/// operator prefix /+/ {}
4553+
/// prefix operator /+/ {}
45584554
/// \endcode
45594555
class PrefixOperatorDecl : public OperatorDecl {
4560-
SourceLoc PrefixLoc;
45614556
public:
4562-
PrefixOperatorDecl(DeclContext *DC,
4563-
SourceLoc OperatorLoc,
4564-
SourceLoc PrefixLoc,
4565-
Identifier Name,
4566-
SourceLoc NameLoc,
4567-
SourceLoc LBraceLoc,
4557+
PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
4558+
SourceLoc NameLoc, SourceLoc LBraceLoc,
45684559
SourceLoc RBraceLoc)
45694560
: OperatorDecl(DeclKind::PrefixOperator, DC,
4570-
OperatorLoc,
4571-
Name,
4572-
NameLoc,
4573-
LBraceLoc,
4574-
RBraceLoc),
4575-
PrefixLoc(PrefixLoc) {}
4576-
4577-
SourceLoc getPrefixLoc() const { return PrefixLoc; }
4578-
4561+
OperatorLoc, Name, NameLoc, LBraceLoc, RBraceLoc) {}
4562+
45794563
/// True if this decl's attributes conflict with those declared by another
45804564
/// PrefixOperatorDecl.
45814565
bool conflictsWith(PrefixOperatorDecl *other) {
@@ -4590,28 +4574,16 @@ class PrefixOperatorDecl : public OperatorDecl {
45904574
/// Declares the behavior of a postfix operator. For example:
45914575
///
45924576
/// \code
4593-
/// operator postfix /+/ {}
4577+
/// postfix operator /+/ {}
45944578
/// \endcode
45954579
class PostfixOperatorDecl : public OperatorDecl {
4596-
SourceLoc PostfixLoc;
45974580
public:
4598-
PostfixOperatorDecl(DeclContext *DC,
4599-
SourceLoc OperatorLoc,
4600-
SourceLoc PostfixLoc,
4601-
Identifier Name,
4602-
SourceLoc NameLoc,
4603-
SourceLoc LBraceLoc,
4581+
PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
4582+
SourceLoc NameLoc, SourceLoc LBraceLoc,
46044583
SourceLoc RBraceLoc)
4605-
: OperatorDecl(DeclKind::PostfixOperator, DC,
4606-
OperatorLoc,
4607-
Name,
4608-
NameLoc,
4609-
LBraceLoc,
4610-
RBraceLoc),
4611-
PostfixLoc(PostfixLoc) {}
4584+
: OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name,
4585+
NameLoc, LBraceLoc, RBraceLoc) {}
46124586

4613-
SourceLoc getPostfixLoc() const { return PostfixLoc; }
4614-
46154587
/// True if this decl's attributes conflict with those declared by another
46164588
/// PostfixOperatorDecl.
46174589
bool conflictsWith(PostfixOperatorDecl *other) {

include/swift/AST/DiagnosticsParse.def

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,11 +352,19 @@ ERROR(opened_destructor_expected_rparen,attribute_parsing,none,
352352
ERROR(destructor_params,decl_parsing,none,
353353
"deinitializer does not have a parameter clause", ())
354354

355+
356+
// FIXME: Remove this.
357+
ERROR(operator_fixity_moved,decl_parsing,PointsToFirstBadToken,
358+
"%0 moved to before the 'operator' declaration", (StringRef))
359+
360+
355361
// Operator
356362
ERROR(operator_decl_inner_scope,decl_parsing,none,
357363
"'operator' may only be declared at file scope", ())
358364
ERROR(expected_operator_name_after_operator,decl_parsing,PointsToFirstBadToken,
359-
"expected operator name after fixity in 'operator' declaration", ())
365+
"expected operator name in operator declaration", ())
366+
ERROR(operator_decl_no_fixity,decl_parsing,none,
367+
"operator must be declared as 'prefix', 'postfix', or 'infix'", ())
360368
ERROR(expected_lbrace_after_operator,decl_parsing,PointsToFirstBadToken,
361369
"expected '{' after operator name in 'operator' declaration", ())
362370
ERROR(expected_operator_attribute,decl_parsing,none,

include/swift/AST/DiagnosticsSema.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,7 @@ ERROR(broken_int_hashable_conformance,sema_tcd,none,
815815
ERROR(broken_int_integer_literal_convertible_conformance,sema_tcd,none,
816816
"Int type is broken: does not conform to IntegerLiteralConvertible", ())
817817
ERROR(broken_equatable_eq_operator,sema_tcd,none,
818-
"Equatable protocol is broken: no operator infix declaration for '=='", ())
818+
"Equatable protocol is broken: no infix operator declaration for '=='", ())
819819

820820
// Dynamic Self
821821
ERROR(dynamic_self_non_method,sema_tcd,none,

include/swift/Parse/Parser.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -732,15 +732,12 @@ class Parser {
732732
ParserResult<OperatorDecl> parseDeclOperator(ParseDeclOptions Flags,
733733
DeclAttributes &Attributes);
734734
ParserResult<OperatorDecl> parseDeclPrefixOperator(SourceLoc OperatorLoc,
735-
SourceLoc PrefixLoc,
736735
Identifier Name,
737736
SourceLoc NameLoc);
738737
ParserResult<OperatorDecl> parseDeclPostfixOperator(SourceLoc OperatorLoc,
739-
SourceLoc PostfixLoc,
740738
Identifier Name,
741739
SourceLoc NameLoc);
742740
ParserResult<OperatorDecl> parseDeclInfixOperator(SourceLoc OperatorLoc,
743-
SourceLoc InfixLoc,
744741
Identifier Name,
745742
SourceLoc NameLoc);
746743

lib/AST/ASTPrinter.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,7 +1329,7 @@ void PrintAST::visitDestructorDecl(DestructorDecl *decl) {
13291329
}
13301330

13311331
void PrintAST::visitInfixOperatorDecl(InfixOperatorDecl *decl) {
1332-
Printer << "operator infix ";
1332+
Printer << "infix operator ";
13331333
recordDeclLoc(decl);
13341334
Printer.printName(decl->getName());
13351335
Printer << " {";
@@ -1363,7 +1363,7 @@ void PrintAST::visitInfixOperatorDecl(InfixOperatorDecl *decl) {
13631363
}
13641364

13651365
void PrintAST::visitPrefixOperatorDecl(PrefixOperatorDecl *decl) {
1366-
Printer << "operator prefix ";
1366+
Printer << "prefix operator ";
13671367
recordDeclLoc(decl);
13681368
Printer.printName(decl->getName());
13691369
Printer << " {";
@@ -1372,7 +1372,7 @@ void PrintAST::visitPrefixOperatorDecl(PrefixOperatorDecl *decl) {
13721372
}
13731373

13741374
void PrintAST::visitPostfixOperatorDecl(PostfixOperatorDecl *decl) {
1375-
Printer << "operator postfix ";
1375+
Printer << "postfix operator ";
13761376
recordDeclLoc(decl);
13771377
Printer.printName(decl->getName());
13781378
Printer << " {";

lib/IDE/SyntaxModel.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -556,20 +556,6 @@ bool ModelASTWalker::walkToDeclPre(Decl *D) {
556556
if (!passNonTokenNode({ SyntaxNodeKind::Keyword,
557557
CharSourceRange(OperD->getOperatorLoc(), strlen("operator")) }))
558558
return false;
559-
560-
if (auto Infix = dyn_cast<InfixOperatorDecl>(D)) {
561-
if (!passNonTokenNode({ SyntaxNodeKind::Keyword,
562-
CharSourceRange(Infix->getInfixLoc(), strlen("infix")) }))
563-
return false;
564-
} else if (auto Prefix = dyn_cast<PrefixOperatorDecl>(D)) {
565-
if (!passNonTokenNode({ SyntaxNodeKind::Keyword,
566-
CharSourceRange(Prefix->getPrefixLoc(), strlen("prefix")) }))
567-
return false;
568-
} else if (auto Postfix = dyn_cast<PostfixOperatorDecl>(D)) {
569-
if (!passNonTokenNode({ SyntaxNodeKind::Keyword,
570-
CharSourceRange(Postfix->getPostfixLoc(), strlen("postfix")) }))
571-
return false;
572-
}
573559
}
574560

575561
return true;

lib/Parse/ParseDecl.cpp

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4094,16 +4094,27 @@ Parser::parseDeclOperator(ParseDeclOptions Flags, DeclAttributes &Attributes) {
40944094

40954095
if (Attributes.hasNonVirtualAttributes())
40964096
diagnose(Attributes.AtLoc, diag::operator_attributes);
4097-
4098-
auto kind = llvm::StringSwitch<Optional<DeclKind>>(Tok.getText())
4099-
.Case("prefix", DeclKind::PrefixOperator)
4100-
.Case("postfix", DeclKind::PostfixOperator)
4101-
.Case("infix", DeclKind::InfixOperator)
4102-
.Default(Nothing);
4103-
4104-
assert(kind && "no fixity after 'operator'?!");
41054097

4106-
SourceLoc KindLoc = consumeToken(tok::identifier);
4098+
// Check to see if this is declared with the old syntax to help with migration
4099+
// FIXME: Remove this.
4100+
if (Tok.is(tok::identifier)) {
4101+
DeclAttribute *attr = nullptr;
4102+
if (Tok.getText() == "infix")
4103+
attr = new (Context) InfixAttr(/*implicit*/false);
4104+
else if (Tok.getText() == "postfix")
4105+
attr = new (Context) PostfixAttr(/*implicit*/false);
4106+
else if (Tok.getText() == "prefix")
4107+
attr = new (Context) PrefixAttr(/*implicit*/false);
4108+
4109+
if (attr) {
4110+
diagnose(Tok, diag::operator_fixity_moved, Tok.getText())
4111+
.fixItInsert(OperatorLoc, Tok.getText().str() + " ")
4112+
.fixItRemove(Tok.getLoc());
4113+
4114+
Attributes.add(attr);
4115+
consumeToken(tok::identifier);
4116+
}
4117+
}
41074118

41084119
if (!Tok.isAnyOperator() && !Tok.is(tok::exclaim_postfix)) {
41094120
diagnose(Tok, diag::expected_operator_name_after_operator);
@@ -4121,20 +4132,16 @@ Parser::parseDeclOperator(ParseDeclOptions Flags, DeclAttributes &Attributes) {
41214132
}
41224133

41234134
ParserResult<OperatorDecl> Result;
4124-
switch (*kind) {
4125-
case DeclKind::PrefixOperator:
4126-
Result = parseDeclPrefixOperator(OperatorLoc, KindLoc, Name, NameLoc);
4127-
break;
4128-
case DeclKind::PostfixOperator:
4129-
Result = parseDeclPostfixOperator(OperatorLoc, KindLoc, Name, NameLoc);
4130-
break;
4131-
case DeclKind::InfixOperator:
4132-
Result = parseDeclInfixOperator(OperatorLoc, KindLoc, Name, NameLoc);
4133-
break;
4134-
default:
4135-
llvm_unreachable("impossible");
4135+
if (Attributes.hasAttribute<PrefixAttr>())
4136+
Result = parseDeclPrefixOperator(OperatorLoc, Name, NameLoc);
4137+
else if (Attributes.hasAttribute<PostfixAttr>())
4138+
Result = parseDeclPostfixOperator(OperatorLoc, Name, NameLoc);
4139+
else {
4140+
if (!Attributes.hasAttribute<InfixAttr>())
4141+
diagnose(OperatorLoc, diag::operator_decl_no_fixity);
4142+
Result = parseDeclInfixOperator(OperatorLoc, Name, NameLoc);
41364143
}
4137-
4144+
41384145
if (Tok.is(tok::r_brace))
41394146
consumeToken();
41404147

@@ -4147,8 +4154,8 @@ Parser::parseDeclOperator(ParseDeclOptions Flags, DeclAttributes &Attributes) {
41474154
}
41484155

41494156
ParserResult<OperatorDecl>
4150-
Parser::parseDeclPrefixOperator(SourceLoc OperatorLoc, SourceLoc PrefixLoc,
4151-
Identifier Name, SourceLoc NameLoc) {
4157+
Parser::parseDeclPrefixOperator(SourceLoc OperatorLoc, Identifier Name,
4158+
SourceLoc NameLoc) {
41524159
SourceLoc LBraceLoc = consumeToken(tok::l_brace);
41534160

41544161
while (!Tok.is(tok::r_brace)) {
@@ -4164,12 +4171,12 @@ Parser::parseDeclPrefixOperator(SourceLoc OperatorLoc, SourceLoc PrefixLoc,
41644171
SourceLoc RBraceLoc = Tok.getLoc();
41654172

41664173
return makeParserResult(
4167-
new (Context) PrefixOperatorDecl(CurDeclContext, OperatorLoc, PrefixLoc,
4174+
new (Context) PrefixOperatorDecl(CurDeclContext, OperatorLoc,
41684175
Name, NameLoc, LBraceLoc, RBraceLoc));
41694176
}
41704177

41714178
ParserResult<OperatorDecl>
4172-
Parser::parseDeclPostfixOperator(SourceLoc OperatorLoc, SourceLoc PostfixLoc,
4179+
Parser::parseDeclPostfixOperator(SourceLoc OperatorLoc,
41734180
Identifier Name, SourceLoc NameLoc) {
41744181
SourceLoc LBraceLoc = consumeToken(tok::l_brace);
41754182

@@ -4187,13 +4194,12 @@ Parser::parseDeclPostfixOperator(SourceLoc OperatorLoc, SourceLoc PostfixLoc,
41874194

41884195
return makeParserResult(
41894196
new (Context) PostfixOperatorDecl(CurDeclContext, OperatorLoc,
4190-
PostfixLoc, Name, NameLoc, LBraceLoc,
4191-
RBraceLoc));
4197+
Name, NameLoc, LBraceLoc, RBraceLoc));
41924198
}
41934199

41944200
ParserResult<OperatorDecl>
4195-
Parser::parseDeclInfixOperator(SourceLoc OperatorLoc, SourceLoc InfixLoc,
4196-
Identifier Name, SourceLoc NameLoc) {
4201+
Parser::parseDeclInfixOperator(SourceLoc OperatorLoc, Identifier Name,
4202+
SourceLoc NameLoc) {
41974203
SourceLoc LBraceLoc = consumeToken(tok::l_brace);
41984204

41994205
// Initialize InfixData with default attributes:
@@ -4269,7 +4275,7 @@ Parser::parseDeclInfixOperator(SourceLoc OperatorLoc, SourceLoc InfixLoc,
42694275
SourceLoc RBraceLoc = Tok.getLoc();
42704276

42714277
return makeParserResult(new (Context) InfixOperatorDecl(
4272-
CurDeclContext, OperatorLoc, InfixLoc, Name, NameLoc, LBraceLoc,
4278+
CurDeclContext, OperatorLoc, Name, NameLoc, LBraceLoc,
42734279
AssociativityLoc, AssociativityValueLoc, PrecedenceLoc,
42744280
PrecedenceValueLoc, RBraceLoc, InfixData(precedence, associativity)));
42754281
}

lib/Sema/TypeCheckAttr.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -636,8 +636,31 @@ void AttributeChecker::visitFinalAttr(FinalAttr *attr) {
636636
}
637637
}
638638

639+
/// Return true if this is a builtin operator that cannot be defined in user
640+
/// code.
641+
static bool isBuiltinOperator(StringRef name, DeclAttribute *attr) {
642+
return ((isa<PrefixAttr>(attr) && name == "&") || // prefix &
643+
(isa<PostfixAttr>(attr) && name == "!") || // postfix !
644+
(isa<PostfixAttr>(attr) && name == "?")); // postfix ?
645+
}
646+
639647
void AttributeChecker::checkOperatorAttribute(DeclAttribute *attr) {
640-
// Operators may only be defined as functions.
648+
// Check out the operator attributes. They may be attached to an operator
649+
// declaration or a function.
650+
if (auto *OD = dyn_cast<OperatorDecl>(D)) {
651+
// Reject attempts to define builtin operators.
652+
if (isBuiltinOperator(OD->getName().str(), attr)) {
653+
TC.diagnose(D->getStartLoc(), diag::redefining_builtin_operator,
654+
attr->getAttrName(), OD->getName().str());
655+
attr->setInvalid();
656+
return;
657+
}
658+
659+
// Otherwise, the attribute is always ok on an operator.
660+
return;
661+
}
662+
663+
// Operators implementations may only be defined as functions.
641664
auto *FD = dyn_cast<FuncDecl>(D);
642665
if (!FD) {
643666
TC.diagnose(D->getLoc(), diag::operator_not_func);
@@ -655,9 +678,7 @@ void AttributeChecker::checkOperatorAttribute(DeclAttribute *attr) {
655678
}
656679

657680
// Reject attempts to define builtin operators.
658-
if ((isa<PrefixAttr>(attr) && FD->getName().str() == "&") || // prefix &
659-
(isa<PostfixAttr>(attr) && FD->getName().str() == "!") || // postfix !
660-
(isa<PostfixAttr>(attr) && FD->getName().str() == "?")) { // postfix ?
681+
if (isBuiltinOperator(FD->getName().str(), attr)) {
661682
TC.diagnose(D->getStartLoc(), diag::redefining_builtin_operator,
662683
attr->getAttrName(), FD->getName().str());
663684
attr->setInvalid();

0 commit comments

Comments
 (0)