Skip to content

Commit 27ed4a9

Browse files
authored
Merge pull request #31467 from hamishknight/mix-fix
2 parents ced7dc1 + 382fcd7 commit 27ed4a9

File tree

8 files changed

+93
-113
lines changed

8 files changed

+93
-113
lines changed

include/swift/AST/Decl.h

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7156,18 +7156,16 @@ class OperatorDecl : public Decl {
71567156

71577157
Identifier name;
71587158

7159-
ArrayRef<Identifier> Identifiers;
7160-
ArrayRef<SourceLoc> IdentifierLocs;
7159+
ArrayRef<Located<Identifier>> Identifiers;
71617160
ArrayRef<NominalTypeDecl *> DesignatedNominalTypes;
71627161
SourceLoc getLocFromSource() const { return NameLoc; }
71637162
friend class Decl;
71647163
public:
71657164
OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc,
71667165
Identifier Name, SourceLoc NameLoc,
7167-
ArrayRef<Identifier> Identifiers,
7168-
ArrayRef<SourceLoc> IdentifierLocs)
7166+
ArrayRef<Located<Identifier>> Identifiers)
71697167
: Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name),
7170-
Identifiers(Identifiers), IdentifierLocs(IdentifierLocs) {}
7168+
Identifiers(Identifiers) {}
71717169

71727170
OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc,
71737171
Identifier Name, SourceLoc NameLoc,
@@ -7202,14 +7200,10 @@ class OperatorDecl : public Decl {
72027200
///
72037201
/// \todo These two purposes really ought to be in separate properties and the
72047202
/// designated type list should be of TypeReprs instead of Identifiers.
7205-
ArrayRef<Identifier> getIdentifiers() const {
7203+
ArrayRef<Located<Identifier>> getIdentifiers() const {
72067204
return Identifiers;
72077205
}
72087206

7209-
ArrayRef<SourceLoc> getIdentifierLocs() const {
7210-
return IdentifierLocs;
7211-
}
7212-
72137207
ArrayRef<NominalTypeDecl *> getDesignatedNominalTypes() const {
72147208
return DesignatedNominalTypes;
72157209
}
@@ -7238,18 +7232,17 @@ class InfixOperatorDecl : public OperatorDecl {
72387232
public:
72397233
InfixOperatorDecl(DeclContext *DC, SourceLoc operatorLoc, Identifier name,
72407234
SourceLoc nameLoc, SourceLoc colonLoc,
7241-
ArrayRef<Identifier> identifiers,
7242-
ArrayRef<SourceLoc> identifierLocs)
7235+
ArrayRef<Located<Identifier>> identifiers)
72437236
: OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc,
7244-
identifiers, identifierLocs),
7237+
identifiers),
72457238
ColonLoc(colonLoc) {}
72467239

72477240
SourceLoc getEndLoc() const {
7248-
auto identifierLocs = getIdentifierLocs();
7249-
if (identifierLocs.empty())
7241+
auto identifiers = getIdentifiers();
7242+
if (identifiers.empty())
72507243
return getNameLoc();
72517244

7252-
return identifierLocs.back();
7245+
return identifiers.back().Loc;
72537246
}
72547247

72557248
SourceRange getSourceRange() const {
@@ -7280,10 +7273,9 @@ class PrefixOperatorDecl : public OperatorDecl {
72807273
public:
72817274
PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
72827275
SourceLoc NameLoc,
7283-
ArrayRef<Identifier> Identifiers,
7284-
ArrayRef<SourceLoc> IdentifierLocs)
7276+
ArrayRef<Located<Identifier>> Identifiers)
72857277
: OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc,
7286-
Identifiers, IdentifierLocs) {}
7278+
Identifiers) {}
72877279

72887280
PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
72897281
SourceLoc NameLoc,
@@ -7315,10 +7307,9 @@ class PostfixOperatorDecl : public OperatorDecl {
73157307
public:
73167308
PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
73177309
SourceLoc NameLoc,
7318-
ArrayRef<Identifier> Identifiers,
7319-
ArrayRef<SourceLoc> IdentifierLocs)
7310+
ArrayRef<Located<Identifier>> Identifiers)
73207311
: OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc,
7321-
Identifiers, IdentifierLocs) {}
7312+
Identifiers) {}
73227313

73237314
PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
73247315
SourceLoc NameLoc,

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1229,7 +1229,7 @@ namespace {
12291229
auto identifiers = OD->getIdentifiers();
12301230
for (auto index : indices(identifiers)) {
12311231
OS.indent(Indent + 2);
1232-
OS << "identifier #" << index << " " << identifiers[index];
1232+
OS << "identifier #" << index << " " << identifiers[index].Item;
12331233
if (index != identifiers.size() - 1)
12341234
OS << "\n";
12351235
}

lib/Parse/ParseDecl.cpp

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7530,8 +7530,7 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
75307530
// parse them both as identifiers here and sort it out in type
75317531
// checking.
75327532
SourceLoc colonLoc;
7533-
SmallVector<Identifier, 4> identifiers;
7534-
SmallVector<SourceLoc, 4> identifierLocs;
7533+
SmallVector<Located<Identifier>, 4> identifiers;
75357534
if (Tok.is(tok::colon)) {
75367535
SyntaxParsingContext GroupCtxt(SyntaxContext,
75377536
SyntaxKind::OperatorPrecedenceAndTypes);
@@ -7552,16 +7551,16 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
75527551
SyntaxKind::IdentifierList);
75537552

75547553
Identifier name;
7555-
identifierLocs.push_back(consumeIdentifier(&name));
7556-
identifiers.push_back(name);
7554+
auto loc = consumeIdentifier(&name);
7555+
identifiers.emplace_back(name, loc);
75577556

75587557
while (Tok.is(tok::comma)) {
75597558
auto comma = consumeToken();
75607559

75617560
if (Tok.is(tok::identifier)) {
75627561
Identifier name;
7563-
identifierLocs.push_back(consumeIdentifier(&name));
7564-
identifiers.push_back(name);
7562+
auto loc = consumeIdentifier(&name);
7563+
identifiers.emplace_back(name, loc);
75657564
} else {
75667565
if (Tok.isNot(tok::eof)) {
75677566
auto otherTokLoc = consumeToken();
@@ -7576,12 +7575,13 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
75767575
SyntaxParsingContext GroupCtxt(SyntaxContext,
75777576
SyntaxKind::IdentifierList);
75787577

7579-
identifiers.push_back(Context.getIdentifier(Tok.getText()));
7580-
identifierLocs.push_back(consumeToken(tok::identifier));
7578+
Identifier name;
7579+
auto nameLoc = consumeIdentifier(&name);
7580+
identifiers.emplace_back(name, nameLoc);
75817581

75827582
if (isPrefix || isPostfix) {
75837583
diagnose(colonLoc, diag::precedencegroup_not_infix)
7584-
.fixItRemove({colonLoc, identifierLocs.back()});
7584+
.fixItRemove({colonLoc, nameLoc});
75857585
}
75867586
// Nothing to complete here, simply consume the token.
75877587
if (Tok.is(tok::code_complete))
@@ -7598,7 +7598,7 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
75987598
auto Diag = diagnose(lBraceLoc, diag::deprecated_operator_body);
75997599
if (Tok.is(tok::r_brace)) {
76007600
SourceLoc lastGoodLoc =
7601-
!identifierLocs.empty() ? identifierLocs.back() : SourceLoc();
7601+
!identifiers.empty() ? identifiers.back().Loc : SourceLoc();
76027602
if (lastGoodLoc.isInvalid())
76037603
lastGoodLoc = NameLoc;
76047604
SourceLoc lastGoodLocEnd = Lexer::getLocForEndOfToken(SourceMgr,
@@ -7616,18 +7616,15 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
76167616
if (Attributes.hasAttribute<PrefixAttr>())
76177617
res = new (Context)
76187618
PrefixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc,
7619-
Context.AllocateCopy(identifiers),
7620-
Context.AllocateCopy(identifierLocs));
7619+
Context.AllocateCopy(identifiers));
76217620
else if (Attributes.hasAttribute<PostfixAttr>())
76227621
res = new (Context)
76237622
PostfixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc,
7624-
Context.AllocateCopy(identifiers),
7625-
Context.AllocateCopy(identifierLocs));
7623+
Context.AllocateCopy(identifiers));
76267624
else
76277625
res = new (Context)
76287626
InfixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc, colonLoc,
7629-
Context.AllocateCopy(identifiers),
7630-
Context.AllocateCopy(identifierLocs));
7627+
Context.AllocateCopy(identifiers));
76317628

76327629
diagnoseOperatorFixityAttributes(*this, Attributes, res);
76337630

lib/Sema/TypeCheckAccess.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,9 +2006,9 @@ class ExportabilityChecker : public DeclVisitor<ExportabilityChecker> {
20062006
// FIXME: Handle operator designated types (which also applies to prefix
20072007
// and postfix operators).
20082008
if (auto *precedenceGroup = IOD->getPrecedenceGroup()) {
2009-
if (!IOD->getIdentifierLocs().empty()) {
2009+
if (!IOD->getIdentifiers().empty()) {
20102010
checkPrecedenceGroup(precedenceGroup, IOD, IOD->getLoc(),
2011-
IOD->getIdentifierLocs().front());
2011+
IOD->getIdentifiers().front().Loc);
20122012
}
20132013
}
20142014
}

lib/Sema/TypeCheckDecl.cpp

Lines changed: 61 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,30 +1336,46 @@ lookupPrecedenceGroup(const PrecedenceGroupDescriptor &descriptor) {
13361336
}
13371337
}
13381338

1339+
static PrecedenceGroupDecl *lookupPrecedenceGroupForRelation(
1340+
DeclContext *dc, PrecedenceGroupDecl::Relation rel,
1341+
PrecedenceGroupDescriptor::PathDirection direction) {
1342+
auto &ctx = dc->getASTContext();
1343+
PrecedenceGroupDescriptor desc{dc, rel.Name, rel.NameLoc, direction};
1344+
auto result = ctx.evaluator(ValidatePrecedenceGroupRequest{desc});
1345+
if (!result) {
1346+
// Handle a cycle error specially. We don't want to default to an empty
1347+
// result, as we don't want to emit an error about not finding a precedence
1348+
// group.
1349+
using Error = CyclicalRequestError<ValidatePrecedenceGroupRequest>;
1350+
llvm::handleAllErrors(result.takeError(), [](const Error &E) {});
1351+
return nullptr;
1352+
}
1353+
if (!result.get()) {
1354+
ctx.Diags.diagnose(rel.NameLoc, diag::unknown_precedence_group, rel.Name);
1355+
}
1356+
return result.get();
1357+
}
1358+
13391359
void swift::validatePrecedenceGroup(PrecedenceGroupDecl *PGD) {
13401360
assert(PGD && "Cannot validate a null precedence group!");
13411361
if (PGD->isInvalid())
13421362
return;
13431363

13441364
auto &Diags = PGD->getASTContext().Diags;
1365+
auto *dc = PGD->getDeclContext();
13451366

13461367
// Validate the higherThan relationships.
13471368
bool addedHigherThan = false;
13481369
for (auto &rel : PGD->getMutableHigherThan()) {
13491370
if (rel.Group)
13501371
continue;
13511372

1352-
PrecedenceGroupDescriptor desc{PGD->getDeclContext(), rel.Name, rel.NameLoc,
1353-
PrecedenceGroupDescriptor::HigherThan};
1354-
auto group =
1355-
evaluateOrDefault(PGD->getASTContext().evaluator,
1356-
ValidatePrecedenceGroupRequest{desc}, nullptr);
1357-
if (group) {
1358-
rel.Group = group;
1373+
// TODO: Requestify the lookup of a relation's group.
1374+
rel.Group = lookupPrecedenceGroupForRelation(
1375+
dc, rel, PrecedenceGroupDescriptor::HigherThan);
1376+
if (rel.Group) {
13591377
addedHigherThan = true;
13601378
} else {
1361-
if (!lookupPrecedenceGroup(desc))
1362-
Diags.diagnose(rel.NameLoc, diag::unknown_precedence_group, rel.Name);
13631379
PGD->setInvalid();
13641380
}
13651381
}
@@ -1369,24 +1385,16 @@ void swift::validatePrecedenceGroup(PrecedenceGroupDecl *PGD) {
13691385
if (rel.Group)
13701386
continue;
13711387

1372-
auto dc = PGD->getDeclContext();
1373-
PrecedenceGroupDescriptor desc{PGD->getDeclContext(), rel.Name, rel.NameLoc,
1374-
PrecedenceGroupDescriptor::LowerThan};
1375-
auto group =
1376-
evaluateOrDefault(PGD->getASTContext().evaluator,
1377-
ValidatePrecedenceGroupRequest{desc}, nullptr);
1378-
bool hadError = false;
1379-
if (group) {
1380-
rel.Group = group;
1381-
} else {
1382-
hadError = true;
1383-
if (auto *rawGroup = lookupPrecedenceGroup(desc)) {
1384-
// We already know the lowerThan path is errant, try to use the results
1385-
// of a raw lookup to enforce the same-module restriction.
1386-
group = rawGroup;
1387-
} else {
1388-
Diags.diagnose(rel.NameLoc, diag::unknown_precedence_group, rel.Name);
1389-
}
1388+
auto *group = lookupPrecedenceGroupForRelation(
1389+
dc, rel, PrecedenceGroupDescriptor::LowerThan);
1390+
rel.Group = group;
1391+
1392+
// If we didn't find anything, try doing a raw lookup for the group before
1393+
// diagnosing the 'lowerThan' within the same-module restriction. This can
1394+
// allow us to diagnose even if we have a precedence group cycle.
1395+
if (!group) {
1396+
group = lookupPrecedenceGroup(PrecedenceGroupDescriptor{
1397+
dc, rel.Name, rel.NameLoc, PrecedenceGroupDescriptor::LowerThan});
13901398
}
13911399

13921400
if (group &&
@@ -1396,10 +1404,10 @@ void swift::validatePrecedenceGroup(PrecedenceGroupDecl *PGD) {
13961404
Diags.diagnose(group->getNameLoc(), diag::kind_declared_here,
13971405
DescriptiveDeclKind::PrecedenceGroup);
13981406
}
1399-
hadError = true;
1407+
PGD->setInvalid();
14001408
}
14011409

1402-
if (hadError)
1410+
if (!rel.Group)
14031411
PGD->setInvalid();
14041412
}
14051413

@@ -1441,18 +1449,13 @@ static NominalTypeDecl *resolveSingleNominalTypeDecl(
14411449
}
14421450

14431451
bool swift::checkDesignatedTypes(OperatorDecl *OD,
1444-
ArrayRef<Identifier> identifiers,
1445-
ArrayRef<SourceLoc> identifierLocs,
1446-
ASTContext &ctx) {
1447-
assert(identifiers.size() == identifierLocs.size());
1448-
1449-
SmallVector<NominalTypeDecl *, 1> designatedNominalTypes;
1452+
ArrayRef<Located<Identifier>> identifiers) {
1453+
auto &ctx = OD->getASTContext();
14501454
auto *DC = OD->getDeclContext();
14511455

1452-
for (auto index : indices(identifiers)) {
1453-
auto *decl = resolveSingleNominalTypeDecl(DC, identifierLocs[index],
1454-
identifiers[index], ctx);
1455-
1456+
SmallVector<NominalTypeDecl *, 1> designatedNominalTypes;
1457+
for (auto ident : identifiers) {
1458+
auto *decl = resolveSingleNominalTypeDecl(DC, ident.Loc, ident.Item, ctx);
14561459
if (!decl)
14571460
return true;
14581461

@@ -1471,63 +1474,55 @@ bool swift::checkDesignatedTypes(OperatorDecl *OD,
14711474
PrecedenceGroupDecl *
14721475
OperatorPrecedenceGroupRequest::evaluate(Evaluator &evaluator,
14731476
InfixOperatorDecl *IOD) const {
1477+
auto &ctx = IOD->getASTContext();
1478+
auto *dc = IOD->getDeclContext();
1479+
14741480
auto enableOperatorDesignatedTypes =
1475-
IOD->getASTContext().TypeCheckerOpts.EnableOperatorDesignatedTypes;
1481+
ctx.TypeCheckerOpts.EnableOperatorDesignatedTypes;
14761482

1477-
auto &Diags = IOD->getASTContext().Diags;
1483+
auto &Diags = ctx.Diags;
14781484
PrecedenceGroupDecl *group = nullptr;
14791485

14801486
auto identifiers = IOD->getIdentifiers();
1481-
auto identifierLocs = IOD->getIdentifierLocs();
1482-
14831487
if (!identifiers.empty()) {
1484-
group = TypeChecker::lookupPrecedenceGroup(
1485-
IOD->getDeclContext(), identifiers[0], identifierLocs[0]);
1488+
auto name = identifiers[0].Item;
1489+
auto loc = identifiers[0].Loc;
1490+
1491+
group = TypeChecker::lookupPrecedenceGroup(dc, name, loc);
14861492

14871493
if (group) {
14881494
identifiers = identifiers.slice(1);
1489-
identifierLocs = identifierLocs.slice(1);
14901495
} else {
14911496
// If we're either not allowing types, or we are allowing them
14921497
// and this identifier is not a type, emit an error as if it's
14931498
// a precedence group.
1494-
auto *DC = IOD->getDeclContext();
14951499
if (!(enableOperatorDesignatedTypes &&
1496-
resolveSingleNominalTypeDecl(DC, identifierLocs[0], identifiers[0],
1497-
IOD->getASTContext(),
1500+
resolveSingleNominalTypeDecl(dc, loc, name, ctx,
14981501
TypeResolutionFlags::SilenceErrors))) {
1499-
Diags.diagnose(identifierLocs[0], diag::unknown_precedence_group,
1500-
identifiers[0]);
1502+
Diags.diagnose(loc, diag::unknown_precedence_group, name);
15011503
identifiers = identifiers.slice(1);
1502-
identifierLocs = identifierLocs.slice(1);
15031504
}
15041505
}
15051506
}
15061507

1507-
if (!identifiers.empty() && !enableOperatorDesignatedTypes) {
1508-
assert(!group);
1509-
Diags.diagnose(identifierLocs[0], diag::unknown_precedence_group,
1510-
identifiers[0]);
1511-
identifiers = identifiers.slice(1);
1512-
identifierLocs = identifierLocs.slice(1);
1513-
assert(identifiers.empty() && identifierLocs.empty());
1514-
}
1508+
// Unless operator designed types are enabled, the parser will ensure that
1509+
// only one identifier is allowed in the clause, which we should have just
1510+
// handled.
1511+
assert(identifiers.empty() || enableOperatorDesignatedTypes);
15151512

15161513
if (!group) {
1517-
group = TypeChecker::lookupPrecedenceGroup(
1518-
IOD->getDeclContext(), IOD->getASTContext().Id_DefaultPrecedence,
1519-
SourceLoc());
1514+
group = TypeChecker::lookupPrecedenceGroup(dc, ctx.Id_DefaultPrecedence,
1515+
SourceLoc());
15201516
}
15211517

15221518
if (!group) {
15231519
Diags.diagnose(IOD->getLoc(), diag::missing_builtin_precedence_group,
1524-
IOD->getASTContext().Id_DefaultPrecedence);
1520+
ctx.Id_DefaultPrecedence);
15251521
}
15261522

15271523
auto nominalTypes = IOD->getDesignatedNominalTypes();
15281524
if (nominalTypes.empty() && enableOperatorDesignatedTypes) {
1529-
if (checkDesignatedTypes(IOD, identifiers, identifierLocs,
1530-
IOD->getASTContext())) {
1525+
if (checkDesignatedTypes(IOD, identifiers)) {
15311526
IOD->setInvalid();
15321527
}
15331528
}

0 commit comments

Comments
 (0)