Skip to content

Commit cc9c851

Browse files
committed
Add direct operator lookup requests
Introduce DirectOperatorLookupRequest & DirectPrecedenceGroupLookupRequest that lookup operator and precedence groups within a given file or module without looking through imports. These will eventually be used as the basis for the new operator lookup implementation, but for now just use them when querying lookup results from serialized module files.
1 parent 9656a04 commit cc9c851

File tree

7 files changed

+211
-55
lines changed

7 files changed

+211
-55
lines changed

include/swift/AST/FileUnit.h

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ class FileUnit : public DeclContext {
3030
#pragma clang diagnostic pop
3131
virtual void anchor();
3232

33+
friend class DirectOperatorLookupRequest;
34+
friend class DirectPrecedenceGroupLookupRequest;
35+
3336
// FIXME: Stick this in a PointerIntPair.
3437
const FileUnitKind Kind;
3538

@@ -107,6 +110,25 @@ class FileUnit : public DeclContext {
107110
const ModuleDecl *importedModule,
108111
SmallVectorImpl<Identifier> &spiGroups) const {};
109112

113+
protected:
114+
/// Look up an operator declaration. Do not call directly, use
115+
/// \c DirectOperatorLookupRequest instead.
116+
///
117+
/// \param name The operator name ("+", ">>", etc.)
118+
///
119+
/// \param fixity One of Prefix, Infix, or Postfix.
120+
virtual void
121+
lookupOperatorDirect(Identifier name, OperatorFixity fixity,
122+
TinyPtrVector<OperatorDecl *> &results) const {}
123+
124+
/// Look up a precedence group. Do not call directly, use
125+
/// \c DirectPrecedenceGroupLookupRequest instead.
126+
///
127+
/// \param name The precedence group name.
128+
virtual void lookupPrecedenceGroupDirect(
129+
Identifier name, TinyPtrVector<PrecedenceGroupDecl *> &results) const {}
130+
131+
public:
110132
/// Returns the comment attached to the given declaration.
111133
///
112134
/// This function is an implementation detail for comment serialization.
@@ -342,23 +364,6 @@ class LoadedFile : public FileUnit {
342364
return StringRef();
343365
}
344366

345-
/// Look up an operator declaration.
346-
///
347-
/// \param name The operator name ("+", ">>", etc.)
348-
///
349-
/// \param fixity One of Prefix, Infix, or Postfix.
350-
virtual OperatorDecl *lookupOperator(Identifier name,
351-
OperatorFixity fixity) const {
352-
return nullptr;
353-
}
354-
355-
/// Look up a precedence group.
356-
///
357-
/// \param name The precedence group name.
358-
virtual PrecedenceGroupDecl *lookupPrecedenceGroup(Identifier name) const {
359-
return nullptr;
360-
}
361-
362367
/// Returns the Swift module that overlays a Clang module.
363368
virtual ModuleDecl *getOverlayModule() const { return nullptr; }
364369

include/swift/AST/NameLookupRequests.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,41 @@ using LookupInfixOperatorRequest = LookupOperatorRequest<InfixOperatorDecl>;
597597
using LookupPostfixOperatorRequest = LookupOperatorRequest<PostfixOperatorDecl>;
598598
using LookupPrecedenceGroupRequest = LookupOperatorRequest<PrecedenceGroupDecl>;
599599

600+
/// Looks up an operator in a given file or module without looking through
601+
/// imports.
602+
class DirectOperatorLookupRequest
603+
: public SimpleRequest<DirectOperatorLookupRequest,
604+
TinyPtrVector<OperatorDecl *>(
605+
OperatorLookupDescriptor, OperatorFixity),
606+
CacheKind::Uncached> {
607+
public:
608+
using SimpleRequest::SimpleRequest;
609+
610+
private:
611+
friend SimpleRequest;
612+
613+
llvm::Expected<TinyPtrVector<OperatorDecl *>>
614+
evaluate(Evaluator &evaluator, OperatorLookupDescriptor descriptor,
615+
OperatorFixity fixity) const;
616+
};
617+
618+
/// Looks up an precedencegroup in a given file or module without looking
619+
/// through imports.
620+
class DirectPrecedenceGroupLookupRequest
621+
: public SimpleRequest<DirectPrecedenceGroupLookupRequest,
622+
TinyPtrVector<PrecedenceGroupDecl *>(
623+
OperatorLookupDescriptor),
624+
CacheKind::Uncached> {
625+
public:
626+
using SimpleRequest::SimpleRequest;
627+
628+
private:
629+
friend SimpleRequest;
630+
631+
llvm::Expected<TinyPtrVector<PrecedenceGroupDecl *>>
632+
evaluate(Evaluator &evaluator, OperatorLookupDescriptor descriptor) const;
633+
};
634+
600635
#define SWIFT_TYPEID_ZONE NameLookup
601636
#define SWIFT_TYPEID_HEADER "swift/AST/NameLookupTypeIDZone.def"
602637
#include "swift/Basic/DefineTypeIDZone.h"

include/swift/AST/NameLookupTypeIDZone.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ SWIFT_REQUEST(NameLookup, CustomAttrNominalRequest,
2424
SWIFT_REQUEST(NameLookup, DirectLookupRequest,
2525
TinyPtrVector<ValueDecl *>(DirectLookupDescriptor), Uncached,
2626
NoLocationInfo)
27+
SWIFT_REQUEST(NameLookup, DirectOperatorLookupRequest,
28+
TinyPtrVector<OperatorDecl *>(OperatorLookupDescriptor,
29+
OperatorFixity),
30+
Uncached, NoLocationInfo)
31+
SWIFT_REQUEST(NameLookup, DirectPrecedenceGroupLookupRequest,
32+
TinyPtrVector<PrecedenceGroupDecl *>(OperatorLookupDescriptor),
33+
Uncached, NoLocationInfo)
2734
SWIFT_REQUEST(NameLookup, ExpandASTScopeRequest,
2835
ast_scope::ASTScopeImpl* (ast_scope::ASTScopeImpl*, ast_scope::ScopeCreator*),
2936
SeparatelyCached,

include/swift/AST/SourceFile.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,16 @@ class SourceFile final : public FileUnit {
436436
ObjCSelector selector,
437437
SmallVectorImpl<AbstractFunctionDecl *> &results) const override;
438438

439+
protected:
440+
virtual void
441+
lookupOperatorDirect(Identifier name, OperatorFixity fixity,
442+
TinyPtrVector<OperatorDecl *> &results) const override;
443+
444+
virtual void lookupPrecedenceGroupDirect(
445+
Identifier name,
446+
TinyPtrVector<PrecedenceGroupDecl *> &results) const override;
447+
448+
public:
439449
virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const override;
440450

441451
virtual void

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -328,12 +328,16 @@ class SerializedASTFile final : public LoadedFile {
328328
lookupNestedType(Identifier name,
329329
const NominalTypeDecl *parent) const override;
330330

331-
virtual OperatorDecl *lookupOperator(Identifier name,
332-
OperatorFixity fixity) const override;
331+
protected:
332+
virtual void
333+
lookupOperatorDirect(Identifier name, OperatorFixity fixity,
334+
TinyPtrVector<OperatorDecl *> &results) const override;
333335

334-
virtual PrecedenceGroupDecl *
335-
lookupPrecedenceGroup(Identifier name) const override;
336+
virtual void lookupPrecedenceGroupDirect(
337+
Identifier name,
338+
TinyPtrVector<PrecedenceGroupDecl *> &results) const override;
336339

340+
public:
337341
virtual void lookupVisibleDecls(ModuleDecl::AccessPathTy accessPath,
338342
VisibleDeclConsumer &consumer,
339343
NLKind lookupKind) const override;

lib/AST/Module.cpp

Lines changed: 120 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -945,39 +945,50 @@ namespace {
945945
template <>
946946
struct OperatorLookup<PrefixOperatorDecl> {
947947
constexpr static auto map_ptr = &SourceFile::PrefixOperators;
948-
template <typename T>
949-
static PrefixOperatorDecl *lookup(T &container, Identifier name) {
950-
return cast_or_null<PrefixOperatorDecl>(
951-
container.lookupOperator(name, OperatorFixity::Prefix));
948+
static PrefixOperatorDecl *lookup(Evaluator &eval,
949+
const OperatorLookupDescriptor &desc) {
950+
// We can return the first prefix operator. All prefix operators of the
951+
// same name are equivalent.
952+
DirectOperatorLookupRequest req{desc, OperatorFixity::Prefix};
953+
auto results = evaluateOrDefault(eval, req, {});
954+
return results.empty() ? nullptr : cast<PrefixOperatorDecl>(results[0]);
952955
}
953956
};
954957

955958
template <>
956959
struct OperatorLookup<InfixOperatorDecl> {
957960
constexpr static auto map_ptr = &SourceFile::InfixOperators;
958-
template <typename T>
959-
static InfixOperatorDecl *lookup(T &container, Identifier name) {
960-
return cast_or_null<InfixOperatorDecl>(
961-
container.lookupOperator(name, OperatorFixity::Infix));
961+
static InfixOperatorDecl *lookup(Evaluator &eval,
962+
const OperatorLookupDescriptor &desc) {
963+
// Return the first result if it exists.
964+
DirectOperatorLookupRequest req{desc, OperatorFixity::Infix};
965+
auto results = evaluateOrDefault(eval, req, {});
966+
return results.empty() ? nullptr : cast<InfixOperatorDecl>(results[0]);
962967
}
963968
};
964969

965970
template <>
966971
struct OperatorLookup<PostfixOperatorDecl> {
967972
constexpr static auto map_ptr = &SourceFile::PostfixOperators;
968-
template <typename T>
969-
static PostfixOperatorDecl *lookup(T &container, Identifier name) {
970-
return cast_or_null<PostfixOperatorDecl>(
971-
container.lookupOperator(name, OperatorFixity::Postfix));
973+
static PostfixOperatorDecl *lookup(Evaluator &eval,
974+
const OperatorLookupDescriptor &desc) {
975+
// We can return the first postfix operator. All postfix operators of the
976+
// same name are equivalent.
977+
DirectOperatorLookupRequest req{desc, OperatorFixity::Postfix};
978+
auto results = evaluateOrDefault(eval, req, {});
979+
return results.empty() ? nullptr : cast<PostfixOperatorDecl>(results[0]);
972980
}
973981
};
974982

975983
template <>
976984
struct OperatorLookup<PrecedenceGroupDecl> {
977985
constexpr static auto map_ptr = &SourceFile::PrecedenceGroups;
978-
template <typename T>
979-
static PrecedenceGroupDecl *lookup(T &container, Identifier name) {
980-
return container.lookupPrecedenceGroup(name);
986+
static PrecedenceGroupDecl *lookup(Evaluator &eval,
987+
const OperatorLookupDescriptor &desc) {
988+
// Return the first result if it exists.
989+
auto results =
990+
evaluateOrDefault(eval, DirectPrecedenceGroupLookupRequest{desc}, {});
991+
return results.empty() ? nullptr : results[0];
981992
}
982993
};
983994
} // end anonymous namespace
@@ -1014,7 +1025,8 @@ void SourceFile::setSyntaxRoot(syntax::SourceFileSyntax &&Root) {
10141025

10151026
template<typename OP_DECL>
10161027
static Optional<OP_DECL *>
1017-
lookupOperatorDeclForName(ModuleDecl *M, SourceLoc Loc, Identifier Name);
1028+
lookupOperatorDeclForName(ModuleDecl *M, SourceLoc Loc, Identifier Name,
1029+
bool isCascading);
10181030

10191031
template<typename OP_DECL>
10201032
using ImportedOperatorsMap = llvm::SmallDenseMap<OP_DECL*, bool, 16>;
@@ -1063,7 +1075,8 @@ checkOperatorConflicts(const SourceFile &SF, SourceLoc loc,
10631075
template <typename OP_DECL>
10641076
static Optional<OP_DECL *>
10651077
lookupOperatorDeclForName(const FileUnit &File, SourceLoc Loc,
1066-
Identifier Name, bool includePrivate) {
1078+
Identifier Name, bool includePrivate,
1079+
bool isCascading) {
10671080
switch (File.getKind()) {
10681081
case FileUnitKind::Builtin:
10691082
// The Builtin module declares no operators.
@@ -1072,8 +1085,13 @@ lookupOperatorDeclForName(const FileUnit &File, SourceLoc Loc,
10721085
break;
10731086
case FileUnitKind::SerializedAST:
10741087
case FileUnitKind::ClangModule:
1075-
case FileUnitKind::DWARFModule:
1076-
return OperatorLookup<OP_DECL>::lookup(cast<LoadedFile>(File), Name);
1088+
case FileUnitKind::DWARFModule: {
1089+
auto &eval = File.getASTContext().evaluator;
1090+
auto desc = OperatorLookupDescriptor::forFile(const_cast<FileUnit *>(&File),
1091+
Name, isCascading,
1092+
/*diagLoc*/ SourceLoc());
1093+
return OperatorLookup<OP_DECL>::lookup(eval, desc);
1094+
}
10771095
}
10781096

10791097
auto &SF = cast<SourceFile>(File);
@@ -1102,7 +1120,8 @@ lookupOperatorDeclForName(const FileUnit &File, SourceLoc Loc,
11021120
continue;
11031121

11041122
Optional<OP_DECL *> maybeOp =
1105-
lookupOperatorDeclForName<OP_DECL>(imported.module.second, Loc, Name);
1123+
lookupOperatorDeclForName<OP_DECL>(imported.module.second, Loc, Name,
1124+
isCascading);
11061125
if (!maybeOp)
11071126
return None;
11081127

@@ -1135,10 +1154,12 @@ lookupOperatorDeclForName(const FileUnit &File, SourceLoc Loc,
11351154

11361155
template<typename OP_DECL>
11371156
static Optional<OP_DECL *>
1138-
lookupOperatorDeclForName(ModuleDecl *M, SourceLoc Loc, Identifier Name) {
1157+
lookupOperatorDeclForName(ModuleDecl *M, SourceLoc Loc, Identifier Name,
1158+
bool isCascading) {
11391159
OP_DECL *result = nullptr;
11401160
for (const FileUnit *File : M->getFiles()) {
1141-
auto next = lookupOperatorDeclForName<OP_DECL>(*File, Loc, Name, false);
1161+
auto next = lookupOperatorDeclForName<OP_DECL>(*File, Loc, Name, false,
1162+
isCascading);
11421163
if (!next.hasValue())
11431164
return next;
11441165

@@ -1155,9 +1176,10 @@ template <typename OperatorType>
11551176
llvm::Expected<OperatorType *> LookupOperatorRequest<OperatorType>::evaluate(
11561177
Evaluator &evaluator, OperatorLookupDescriptor desc) const {
11571178
auto *file = desc.fileOrModule.get<FileUnit *>();
1158-
auto result = lookupOperatorDeclForName<OperatorType>(*file, desc.diagLoc,
1159-
desc.name,
1160-
/*includePrivate*/ true);
1179+
auto result =
1180+
lookupOperatorDeclForName<OperatorType>(*file, desc.diagLoc, desc.name,
1181+
/*includePrivate*/ true,
1182+
desc.isCascading);
11611183
if (!result.hasValue())
11621184
return nullptr;
11631185

@@ -1167,16 +1189,17 @@ llvm::Expected<OperatorType *> LookupOperatorRequest<OperatorType>::evaluate(
11671189
}
11681190
if (!result.getValue()) {
11691191
result = lookupOperatorDeclForName<OperatorType>(file->getParentModule(),
1170-
desc.diagLoc, desc.name);
1192+
desc.diagLoc, desc.name,
1193+
desc.isCascading);
11711194
}
11721195
return result.hasValue() ? result.getValue() : nullptr;
11731196
}
11741197

1175-
11761198
#define LOOKUP_OPERATOR(Kind) \
11771199
Kind##Decl *ModuleDecl::lookup##Kind(Identifier name, SourceLoc loc) { \
11781200
auto result = \
1179-
lookupOperatorDeclForName<Kind##Decl>(this, loc, name); \
1201+
lookupOperatorDeclForName<Kind##Decl>(this, loc, name, \
1202+
/*isCascading*/ false); \
11801203
return result ? *result : nullptr; \
11811204
} \
11821205
template llvm::Expected<Kind##Decl *> \
@@ -1189,6 +1212,75 @@ LOOKUP_OPERATOR(PostfixOperator)
11891212
LOOKUP_OPERATOR(PrecedenceGroup)
11901213
#undef LOOKUP_OPERATOR
11911214

1215+
llvm::Expected<TinyPtrVector<OperatorDecl *>>
1216+
DirectOperatorLookupRequest::evaluate(Evaluator &evaluator,
1217+
OperatorLookupDescriptor descriptor,
1218+
OperatorFixity fixity) const {
1219+
// Query each file.
1220+
// TODO: Module-level caching.
1221+
TinyPtrVector<OperatorDecl *> results;
1222+
for (auto *file : descriptor.getFiles())
1223+
file->lookupOperatorDirect(descriptor.name, fixity, results);
1224+
1225+
return std::move(results);
1226+
}
1227+
1228+
void SourceFile::lookupOperatorDirect(
1229+
Identifier name, OperatorFixity fixity,
1230+
TinyPtrVector<OperatorDecl *> &results) const {
1231+
OperatorDecl *op = nullptr;
1232+
switch (fixity) {
1233+
case OperatorFixity::Infix: {
1234+
auto result = InfixOperators.find(name);
1235+
if (result != InfixOperators.end())
1236+
op = result->second.getPointer();
1237+
break;
1238+
}
1239+
case OperatorFixity::Postfix: {
1240+
auto result = PostfixOperators.find(name);
1241+
if (result != PostfixOperators.end())
1242+
op = result->second.getPointer();
1243+
break;
1244+
}
1245+
case OperatorFixity::Prefix: {
1246+
auto result = PrefixOperators.find(name);
1247+
if (result != PrefixOperators.end())
1248+
op = result->second.getPointer();
1249+
break;
1250+
}
1251+
}
1252+
1253+
// We currently can use the operator maps to cache lookup results from other
1254+
// modules. Make sure we only return results from the source file.
1255+
if (op && op->getDeclContext()->getParentSourceFile() == this)
1256+
results.push_back(op);
1257+
}
1258+
1259+
llvm::Expected<TinyPtrVector<PrecedenceGroupDecl *>>
1260+
DirectPrecedenceGroupLookupRequest::evaluate(
1261+
Evaluator &evaluator, OperatorLookupDescriptor descriptor) const {
1262+
// Query each file.
1263+
// TODO: Module-level caching.
1264+
TinyPtrVector<PrecedenceGroupDecl *> results;
1265+
for (auto *file : descriptor.getFiles())
1266+
file->lookupPrecedenceGroupDirect(descriptor.name, results);
1267+
1268+
return std::move(results);
1269+
}
1270+
1271+
void SourceFile::lookupPrecedenceGroupDirect(
1272+
Identifier name, TinyPtrVector<PrecedenceGroupDecl *> &results) const {
1273+
auto result = PrecedenceGroups.find(name);
1274+
if (result == PrecedenceGroups.end())
1275+
return;
1276+
1277+
// We currently can use the operator maps to cache lookup results from other
1278+
// modules. Make sure we only return results from the source file.
1279+
auto *group = result->second.getPointer();
1280+
if (group->getDeclContext()->getParentSourceFile() == this)
1281+
results.push_back(group);
1282+
}
1283+
11921284
void ModuleDecl::getImportedModules(SmallVectorImpl<ImportedModule> &modules,
11931285
ModuleDecl::ImportFilter filter) const {
11941286
FORWARD(getImportedModules, (modules, filter));

0 commit comments

Comments
 (0)