Skip to content

Rip designated types out of the AST #38728

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 21 additions & 60 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -7276,22 +7276,13 @@ class OperatorDecl : public Decl {

Identifier name;

ArrayRef<Located<Identifier>> Identifiers;
ArrayRef<NominalTypeDecl *> DesignatedNominalTypes;
SourceLoc getLocFromSource() const { return NameLoc; }
friend class Decl;
public:
OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc,
Identifier Name, SourceLoc NameLoc,
ArrayRef<Located<Identifier>> Identifiers)
: Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name),
Identifiers(Identifiers) {}

OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc,
Identifier Name, SourceLoc NameLoc,
ArrayRef<NominalTypeDecl *> DesignatedNominalTypes)
: Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name),
DesignatedNominalTypes(DesignatedNominalTypes) {}
Identifier Name, SourceLoc NameLoc)
: Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name)
{}

/// Retrieve the operator's fixity, corresponding to the concrete subclass
/// of the OperatorDecl.
Expand All @@ -7318,25 +7309,6 @@ class OperatorDecl : public Decl {
// OperatorDecls.
DeclBaseName getBaseName() const { return name; }

/// Get the list of identifiers after the colon in the operator declaration.
///
/// This list includes the names of designated types. For infix operators, the
/// first item in the list is a precedence group instead.
///
/// \todo These two purposes really ought to be in separate properties and the
/// designated type list should be of TypeReprs instead of Identifiers.
ArrayRef<Located<Identifier>> getIdentifiers() const {
return Identifiers;
}

ArrayRef<NominalTypeDecl *> getDesignatedNominalTypes() const {
return DesignatedNominalTypes;
}

void setDesignatedNominalTypes(ArrayRef<NominalTypeDecl *> nominalTypes) {
DesignatedNominalTypes = nominalTypes;
}

static bool classof(const Decl *D) {
// Workaround: http://llvm.org/PR35906
if (DeclKind::Last_Decl == DeclKind::Last_OperatorDecl)
Expand All @@ -7352,22 +7324,23 @@ class OperatorDecl : public Decl {
/// infix operator /+/ : AdditionPrecedence, Numeric
/// \endcode
class InfixOperatorDecl : public OperatorDecl {
SourceLoc ColonLoc;
SourceLoc ColonLoc, PrecedenceGroupLoc;
Identifier PrecedenceGroupName;

public:
InfixOperatorDecl(DeclContext *DC, SourceLoc operatorLoc, Identifier name,
SourceLoc nameLoc, SourceLoc colonLoc,
ArrayRef<Located<Identifier>> identifiers)
: OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc,
identifiers),
ColonLoc(colonLoc) {}
Identifier precedenceGroupName,
SourceLoc precedenceGroupLoc)
: OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc),
ColonLoc(colonLoc), PrecedenceGroupLoc(precedenceGroupLoc),
PrecedenceGroupName(precedenceGroupName) {}

SourceLoc getEndLoc() const {
auto identifiers = getIdentifiers();
if (identifiers.empty())
return getNameLoc();
if (getPrecedenceGroupLoc().isValid())
return getPrecedenceGroupLoc();

return identifiers.back().Loc;
return getNameLoc();
}

SourceRange getSourceRange() const {
Expand All @@ -7376,6 +7349,8 @@ class InfixOperatorDecl : public OperatorDecl {

SourceLoc getColonLoc() const { return ColonLoc; }

Identifier getPrecedenceGroupName() const { return PrecedenceGroupName; }
SourceLoc getPrecedenceGroupLoc() const { return PrecedenceGroupLoc; }
PrecedenceGroupDecl *getPrecedenceGroup() const;

static bool classof(const Decl *D) {
Expand All @@ -7391,16 +7366,9 @@ class InfixOperatorDecl : public OperatorDecl {
class PrefixOperatorDecl : public OperatorDecl {
public:
PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
SourceLoc NameLoc,
ArrayRef<Located<Identifier>> Identifiers)
: OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc,
Identifiers) {}

PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
SourceLoc NameLoc,
ArrayRef<NominalTypeDecl *> designatedNominalTypes)
: OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc,
designatedNominalTypes) {}
SourceLoc NameLoc)
: OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc)
{}

SourceRange getSourceRange() const {
return { getOperatorLoc(), getNameLoc() };
Expand All @@ -7419,16 +7387,9 @@ class PrefixOperatorDecl : public OperatorDecl {
class PostfixOperatorDecl : public OperatorDecl {
public:
PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
SourceLoc NameLoc,
ArrayRef<Located<Identifier>> Identifiers)
: OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc,
Identifiers) {}

PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
SourceLoc NameLoc,
ArrayRef<NominalTypeDecl *> designatedNominalTypes)
: OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc,
designatedNominalTypes) {}
SourceLoc NameLoc)
: OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc)
{}

SourceRange getSourceRange() const {
return { getOperatorLoc(), getNameLoc() };
Expand Down
9 changes: 5 additions & 4 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -435,11 +435,12 @@ ERROR(deprecated_operator_body_use_group,PointsToFirstBadToken,
"use a precedence group instead", ())
ERROR(operator_decl_no_fixity,none,
"operator must be declared as 'prefix', 'postfix', or 'infix'", ())
ERROR(operator_decl_expected_precedencegroup, none,
"expected precedence group name after ':' in operator declaration", ())

ERROR(operator_decl_expected_type,none,
"expected designated type in operator declaration", ())
ERROR(operator_decl_trailing_comma,none,
"trailing comma in operator declaration", ())
WARNING(operator_decl_remove_designated_types,none,
"designated types are no longer used by the compiler; please remove "
"the designated type list from this operator declaration", ())

// PrecedenceGroup
ERROR(precedencegroup_not_infix,none,
Expand Down
24 changes: 2 additions & 22 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1145,43 +1145,23 @@ namespace {
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}

void printOperatorIdentifiers(OperatorDecl *OD) {
auto identifiers = OD->getIdentifiers();
for (auto index : indices(identifiers)) {
OS.indent(Indent + 2);
OS << "identifier #" << index << " " << identifiers[index].Item;
if (index != identifiers.size() - 1)
OS << "\n";
}
}

void visitInfixOperatorDecl(InfixOperatorDecl *IOD) {
printCommon(IOD, "infix_operator_decl");
OS << " " << IOD->getName();
if (!IOD->getIdentifiers().empty()) {
OS << "\n";
printOperatorIdentifiers(IOD);
}
if (!IOD->getPrecedenceGroupName().empty())
OS << " precedence_group_name=" << IOD->getPrecedenceGroupName();
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}

void visitPrefixOperatorDecl(PrefixOperatorDecl *POD) {
printCommon(POD, "prefix_operator_decl");
OS << " " << POD->getName();
if (!POD->getIdentifiers().empty()) {
OS << "\n";
printOperatorIdentifiers(POD);
}
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}

void visitPostfixOperatorDecl(PostfixOperatorDecl *POD) {
printCommon(POD, "postfix_operator_decl");
OS << " " << POD->getName();
if (!POD->getIdentifiers().empty()) {
OS << "\n";
printOperatorIdentifiers(POD);
}
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}

Expand Down
27 changes: 0 additions & 27 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3776,15 +3776,6 @@ void PrintAST::visitInfixOperatorDecl(InfixOperatorDecl *decl) {
});
if (auto *group = decl->getPrecedenceGroup())
Printer << " : " << group->getName();
auto designatedNominalTypes = decl->getDesignatedNominalTypes();
auto first = true;
for (auto typeDecl : designatedNominalTypes) {
if (first && !decl->getPrecedenceGroup())
Printer << " : " << typeDecl->getName();
else
Printer << ", " << typeDecl->getName();
first = false;
}
}

void PrintAST::visitPrecedenceGroupDecl(PrecedenceGroupDecl *decl) {
Expand Down Expand Up @@ -3853,15 +3844,6 @@ void PrintAST::visitPrefixOperatorDecl(PrefixOperatorDecl *decl) {
[&]{
Printer.printName(decl->getName());
});
auto designatedNominalTypes = decl->getDesignatedNominalTypes();
auto first = true;
for (auto typeDecl : designatedNominalTypes) {
if (first)
Printer << " : " << typeDecl->getName();
else
Printer << ", " << typeDecl->getName();
first = false;
}
}

void PrintAST::visitPostfixOperatorDecl(PostfixOperatorDecl *decl) {
Expand All @@ -3871,15 +3853,6 @@ void PrintAST::visitPostfixOperatorDecl(PostfixOperatorDecl *decl) {
[&]{
Printer.printName(decl->getName());
});
auto designatedNominalTypes = decl->getDesignatedNominalTypes();
auto first = true;
for (auto typeDecl : designatedNominalTypes) {
if (first)
Printer << " : " << typeDecl->getName();
else
Printer << ", " << typeDecl->getName();
first = false;
}
}

void PrintAST::visitModuleDecl(ModuleDecl *decl) { }
Expand Down
76 changes: 34 additions & 42 deletions lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8115,8 +8115,8 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
// designated protocol. These both look like identifiers, so we
// parse them both as identifiers here and sort it out in type
// checking.
SourceLoc colonLoc;
SmallVector<Located<Identifier>, 4> identifiers;
SourceLoc colonLoc, groupLoc;
Identifier groupName;
if (Tok.is(tok::colon)) {
SyntaxParsingContext GroupCtxt(SyntaxContext,
SyntaxKind::OperatorPrecedenceAndTypes);
Expand All @@ -8131,43 +8131,40 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
return makeParserCodeCompletionResult<OperatorDecl>();
}

if (Context.TypeCheckerOpts.EnableOperatorDesignatedTypes) {
if (Tok.is(tok::identifier)) {
SyntaxParsingContext GroupCtxt(SyntaxContext,
SyntaxKind::IdentifierList);
SyntaxParsingContext ListCtxt(SyntaxContext, SyntaxKind::IdentifierList);

Identifier name;
auto loc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/false);
identifiers.emplace_back(name, loc);
(void)parseIdentifier(groupName, groupLoc,
diag::operator_decl_expected_precedencegroup,
/*diagnoseDollarPrefix=*/false);

while (Tok.is(tok::comma)) {
auto comma = consumeToken();
if (Context.TypeCheckerOpts.EnableOperatorDesignatedTypes) {
// Designated types have been removed; consume the list (mainly for source
// compatibility with old swiftinterfaces) and emit a warning.

if (Tok.is(tok::identifier)) {
Identifier name;
auto loc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/false);
identifiers.emplace_back(name, loc);
} else {
if (Tok.isNot(tok::eof)) {
auto otherTokLoc = consumeToken();
diagnose(otherTokLoc, diag::operator_decl_expected_type);
} else {
diagnose(comma, diag::operator_decl_trailing_comma);
}
}
}
// These SourceLocs point to the ends of the designated type list. If
// `typesEndLoc` never becomes valid, we didn't find any designated types.
SourceLoc typesStartLoc = Tok.getLoc();
SourceLoc typesEndLoc;

if (isPrefix || isPostfix) {
// These have no precedence group, so we already parsed the first entry
// in the designated types list. Retroactively include it in the range.
typesStartLoc = colonLoc;
typesEndLoc = groupLoc;
}
} else if (Tok.is(tok::identifier)) {
SyntaxParsingContext GroupCtxt(SyntaxContext,
SyntaxKind::IdentifierList);

Identifier name;
auto nameLoc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/false);
identifiers.emplace_back(name, nameLoc);
while (consumeIf(tok::comma, typesEndLoc)) {
if (Tok.isNot(tok::eof))
typesEndLoc = consumeToken();
}

if (typesEndLoc.isValid())
diagnose(typesStartLoc, diag::operator_decl_remove_designated_types)
.fixItRemove({typesStartLoc, typesEndLoc});
} else {
if (isPrefix || isPostfix) {
diagnose(colonLoc, diag::precedencegroup_not_infix)
.fixItRemove({colonLoc, nameLoc});
.fixItRemove({colonLoc, groupLoc});
}
// Nothing to complete here, simply consume the token.
if (Tok.is(tok::code_complete))
Expand All @@ -8183,10 +8180,7 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
} else {
auto Diag = diagnose(lBraceLoc, diag::deprecated_operator_body);
if (Tok.is(tok::r_brace)) {
SourceLoc lastGoodLoc =
!identifiers.empty() ? identifiers.back().Loc : SourceLoc();
if (lastGoodLoc.isInvalid())
lastGoodLoc = NameLoc;
SourceLoc lastGoodLoc = groupLoc.isValid() ? groupLoc : NameLoc;
SourceLoc lastGoodLocEnd = Lexer::getLocForEndOfToken(SourceMgr,
lastGoodLoc);
SourceLoc rBraceEnd = Lexer::getLocForEndOfToken(SourceMgr, Tok.getLoc());
Expand All @@ -8199,18 +8193,16 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
}

OperatorDecl *res;
if (Attributes.hasAttribute<PrefixAttr>())
if (isPrefix)
res = new (Context)
PrefixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc,
Context.AllocateCopy(identifiers));
else if (Attributes.hasAttribute<PostfixAttr>())
PrefixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc);
else if (isPostfix)
res = new (Context)
PostfixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc,
Context.AllocateCopy(identifiers));
PostfixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc);
else
res = new (Context)
InfixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc, colonLoc,
Context.AllocateCopy(identifiers));
groupName, groupLoc);

diagnoseOperatorFixityAttributes(*this, Attributes, res);

Expand Down
6 changes: 2 additions & 4 deletions lib/Sema/TypeCheckAccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1874,12 +1874,10 @@ class DeclAvailabilityChecker : public DeclVisitor<DeclAvailabilityChecker> {
}

void visitInfixOperatorDecl(InfixOperatorDecl *IOD) {
// FIXME: Handle operator designated types (which also applies to prefix
// and postfix operators).
if (auto *precedenceGroup = IOD->getPrecedenceGroup()) {
if (!IOD->getIdentifiers().empty()) {
if (!IOD->getPrecedenceGroupName().empty()) {
checkPrecedenceGroup(precedenceGroup, IOD, IOD->getLoc(),
IOD->getIdentifiers().front().Loc);
IOD->getPrecedenceGroupLoc());
}
}
}
Expand Down
Loading