Skip to content

Commit 8ff0e9a

Browse files
authored
Merge pull request #64968 from DougGregor/name-lookup-excluding-macros-in-macro-resolution
2 parents f327f23 + 527a4cd commit 8ff0e9a

12 files changed

+253
-25
lines changed

include/swift/AST/Decl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3835,6 +3835,8 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
38353835
/// Whether to include @_implements members.
38363836
/// Used by conformance-checking to find special @_implements members.
38373837
IncludeAttrImplements = 1 << 0,
3838+
/// Whether to exclude members of macro expansions.
3839+
ExcludeMacroExpansions = 1 << 1,
38383840
};
38393841

38403842
/// Find all of the declarations with the given name within this nominal type

include/swift/AST/Evaluator.h

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,18 @@ class Evaluator {
208208
/// is treated as a stack and is used to detect cycles.
209209
llvm::SetVector<ActiveRequest> activeRequests;
210210

211+
/// How many `ResolveMacroRequest` requests are active.
212+
///
213+
/// This allows us to quickly determine whether there is any
214+
/// `ResolveMacroRequest` active in the active request stack.
215+
/// It saves us from a linear scan through `activeRequests` when
216+
/// we need to determine this information.
217+
///
218+
/// Why on earth would we need to determine this information?
219+
/// Please see the extended comment that goes with the constructor
220+
/// of `UnqualifiedLookupRequest`.
221+
unsigned numActiveResolveMacroRequests = 0;
222+
211223
/// A cache that stores the results of requests.
212224
evaluator::RequestCache cache;
213225

@@ -324,6 +336,16 @@ class Evaluator {
324336
return activeRequests.count(ActiveRequest(request));
325337
}
326338

339+
/// Determine whether there is any active "resolve macro" request
340+
/// on the request stack.
341+
///
342+
/// Why on earth would we need to determine this information?
343+
/// Please see the extended comment that goes with the constructor
344+
/// of `UnqualifiedLookupRequest`.
345+
bool hasActiveResolveMacroRequest() const {
346+
return numActiveResolveMacroRequests > 0;
347+
}
348+
327349
private:
328350
/// Diagnose a cycle detected in the evaluation of the given
329351
/// request.
@@ -337,6 +359,10 @@ class Evaluator {
337359
/// request to the \c activeRequests stack.
338360
bool checkDependency(const ActiveRequest &request);
339361

362+
/// Note that we have finished this request, popping it from the
363+
/// \c activeRequests stack.
364+
void finishedRequest(const ActiveRequest &request);
365+
340366
/// Produce the result of the request without caching.
341367
template<typename Request>
342368
llvm::Expected<typename Request::OutputType>
@@ -366,8 +392,7 @@ class Evaluator {
366392

367393
// Make sure we remove this from the set of active requests once we're
368394
// done.
369-
assert(activeRequests.back() == activeReq);
370-
activeRequests.pop_back();
395+
finishedRequest(activeReq);
371396

372397
return std::move(result);
373398
}

include/swift/AST/NameLookupRequests.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ class UnqualifiedLookupRequest
430430
RequestFlags::Uncached |
431431
RequestFlags::DependencySink> {
432432
public:
433-
using SimpleRequest::SimpleRequest;
433+
UnqualifiedLookupRequest(UnqualifiedLookupDescriptor);
434434

435435
private:
436436
friend SimpleRequest;
@@ -456,7 +456,10 @@ class LookupInModuleRequest
456456
NLOptions),
457457
RequestFlags::Uncached | RequestFlags::DependencySink> {
458458
public:
459-
using SimpleRequest::SimpleRequest;
459+
LookupInModuleRequest(
460+
const DeclContext *, DeclName, NLKind,
461+
namelookup::ResolutionKind, const DeclContext *,
462+
NLOptions);
460463

461464
private:
462465
friend SimpleRequest;
@@ -504,7 +507,9 @@ class ModuleQualifiedLookupRequest
504507
RequestFlags::Uncached |
505508
RequestFlags::DependencySink> {
506509
public:
507-
using SimpleRequest::SimpleRequest;
510+
ModuleQualifiedLookupRequest(const DeclContext *,
511+
ModuleDecl *, DeclNameRef,
512+
NLOptions);
508513

509514
private:
510515
friend SimpleRequest;
@@ -528,7 +533,9 @@ class QualifiedLookupRequest
528533
DeclNameRef, NLOptions),
529534
RequestFlags::Uncached> {
530535
public:
531-
using SimpleRequest::SimpleRequest;
536+
QualifiedLookupRequest(const DeclContext *,
537+
SmallVector<NominalTypeDecl *, 4>,
538+
DeclNameRef, NLOptions);
532539

533540
private:
534541
friend SimpleRequest;
@@ -579,7 +586,7 @@ class DirectLookupRequest
579586
TinyPtrVector<ValueDecl *>(DirectLookupDescriptor),
580587
RequestFlags::Uncached|RequestFlags::DependencySink> {
581588
public:
582-
using SimpleRequest::SimpleRequest;
589+
DirectLookupRequest(DirectLookupDescriptor);
583590

584591
private:
585592
friend SimpleRequest;

lib/AST/Evaluator.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/AST/Evaluator.h"
1818
#include "swift/AST/DeclContext.h"
1919
#include "swift/AST/DiagnosticEngine.h"
20+
#include "swift/AST/TypeCheckRequests.h" // for ResolveMacroRequest
2021
#include "swift/Basic/LangOptions.h"
2122
#include "swift/Basic/Range.h"
2223
#include "swift/Basic/SourceManager.h"
@@ -61,14 +62,25 @@ Evaluator::Evaluator(DiagnosticEngine &diags, const LangOptions &opts)
6162

6263
bool Evaluator::checkDependency(const ActiveRequest &request) {
6364
// Record this as an active request.
64-
if (activeRequests.insert(request))
65+
if (activeRequests.insert(request)) {
66+
if (request.getAs<ResolveMacroRequest>())
67+
++numActiveResolveMacroRequests;
6568
return false;
69+
}
6670

6771
// Diagnose cycle.
6872
diagnoseCycle(request);
6973
return true;
7074
}
7175

76+
void Evaluator::finishedRequest(const ActiveRequest &request) {
77+
if (request.getAs<ResolveMacroRequest>())
78+
--numActiveResolveMacroRequests;
79+
80+
assert(activeRequests.back() == request);
81+
activeRequests.pop_back();
82+
}
83+
7284
void Evaluator::diagnoseCycle(const ActiveRequest &request) {
7385
if (debugDumpCycles) {
7486
const auto printIndent = [](llvm::raw_ostream &OS, unsigned indent) {

lib/AST/Module.cpp

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@ class swift::SourceLookupCache {
174174

175175
using AuxiliaryDeclMap = llvm::DenseMap<DeclName, TinyPtrVector<MissingDecl *>>;
176176
AuxiliaryDeclMap TopLevelAuxiliaryDecls;
177+
178+
/// Top-level macros that produce arbitrary names.
179+
SmallVector<MissingDecl *, 4> TopLevelArbitraryMacros;
180+
177181
SmallVector<Decl *, 4> MayHaveAuxiliaryDecls;
178182
void populateAuxiliaryDeclCache();
179183

@@ -352,26 +356,46 @@ void SourceLookupCache::populateAuxiliaryDeclCache() {
352356
for (auto attrConst : decl->getAttrs().getAttributes<CustomAttr>()) {
353357
auto *attr = const_cast<CustomAttr *>(attrConst);
354358
UnresolvedMacroReference macroRef(attr);
359+
bool introducesArbitraryNames = false;
355360
namelookup::forEachPotentialResolvedMacro(
356361
decl->getDeclContext()->getModuleScopeContext(),
357362
macroRef.getMacroName(), MacroRole::Peer,
358363
[&](MacroDecl *macro, const MacroRoleAttr *roleAttr) {
364+
// First check for arbitrary names.
365+
if (roleAttr->hasNameKind(MacroIntroducedDeclNameKind::Arbitrary)) {
366+
introducesArbitraryNames = true;
367+
}
368+
359369
macro->getIntroducedNames(MacroRole::Peer,
360370
dyn_cast<ValueDecl>(decl),
361371
introducedNames[attr]);
362372
});
373+
374+
// Record this macro where appropriate.
375+
if (introducesArbitraryNames)
376+
TopLevelArbitraryMacros.push_back(MissingDecl::forUnexpandedMacro(attr, decl));
363377
}
364378

365379
if (auto *med = dyn_cast<MacroExpansionDecl>(decl)) {
366380
UnresolvedMacroReference macroRef(med);
381+
bool introducesArbitraryNames = false;
367382
namelookup::forEachPotentialResolvedMacro(
368383
decl->getDeclContext()->getModuleScopeContext(),
369384
macroRef.getMacroName(), MacroRole::Declaration,
370385
[&](MacroDecl *macro, const MacroRoleAttr *roleAttr) {
386+
// First check for arbitrary names.
387+
if (roleAttr->hasNameKind(MacroIntroducedDeclNameKind::Arbitrary)) {
388+
introducesArbitraryNames = true;
389+
}
390+
371391
macro->getIntroducedNames(MacroRole::Declaration,
372392
/*attachedTo*/ nullptr,
373393
introducedNames[med]);
374394
});
395+
396+
// Record this macro where appropriate.
397+
if (introducesArbitraryNames)
398+
TopLevelArbitraryMacros.push_back(MissingDecl::forUnexpandedMacro(med, decl));
375399
}
376400

377401
// Add macro-introduced names to the top-level auxiliary decl cache as
@@ -440,15 +464,30 @@ void SourceLookupCache::lookupValue(DeclName Name, NLKind LookupKind,
440464
? UniqueMacroNamePlaceholder
441465
: Name;
442466
auto auxDecls = TopLevelAuxiliaryDecls.find(keyName);
443-
if (auxDecls == TopLevelAuxiliaryDecls.end())
467+
468+
// Check macro expansions that could produce this name.
469+
SmallVector<MissingDecl *, 4> unexpandedDecls;
470+
if (auxDecls != TopLevelAuxiliaryDecls.end()) {
471+
unexpandedDecls.insert(
472+
unexpandedDecls.end(), auxDecls->second.begin(), auxDecls->second.end());
473+
}
474+
475+
// Check macro expansions that can produce arbitrary names.
476+
unexpandedDecls.insert(
477+
unexpandedDecls.end(),
478+
TopLevelArbitraryMacros.begin(), TopLevelArbitraryMacros.end());
479+
480+
if (unexpandedDecls.empty())
444481
return;
445482

446-
for (auto *unexpandedDecl : auxDecls->second) {
447-
// Add expanded peers and freestanding declarations to the result.
483+
// Add matching expanded peers and freestanding declarations to the results.
484+
SmallPtrSet<ValueDecl *, 4> macroExpandedDecls;
485+
for (auto *unexpandedDecl : unexpandedDecls) {
448486
unexpandedDecl->forEachMacroExpandedDecl(
449487
[&](ValueDecl *decl) {
450488
if (decl->getName().matchesRef(Name)) {
451-
Result.push_back(decl);
489+
if (macroExpandedDecls.insert(decl).second)
490+
Result.push_back(decl);
452491
}
453492
});
454493
}

lib/AST/NameLookup.cpp

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1713,13 +1713,24 @@ void NominalTypeDecl::prepareLookupTable() {
17131713
}
17141714

17151715
static TinyPtrVector<ValueDecl *>
1716-
maybeFilterOutAttrImplements(TinyPtrVector<ValueDecl *> decls,
1717-
DeclName name,
1718-
bool includeAttrImplements) {
1719-
if (includeAttrImplements)
1716+
maybeFilterOutUnwantedDecls(TinyPtrVector<ValueDecl *> decls,
1717+
DeclName name,
1718+
bool includeAttrImplements,
1719+
bool excludeMacroExpansions) {
1720+
if (includeAttrImplements && !excludeMacroExpansions)
17201721
return decls;
17211722
TinyPtrVector<ValueDecl*> result;
17221723
for (auto V : decls) {
1724+
// If we're supposed to exclude anything that comes from a macro expansion,
1725+
// check whether the source location of the declaration is in a macro
1726+
// expansion, and skip this declaration if it does.
1727+
if (excludeMacroExpansions) {
1728+
auto sourceFile =
1729+
V->getModuleContext()->getSourceFileContainingLocation(V->getLoc());
1730+
if (sourceFile && sourceFile->Kind == SourceFileKind::MacroExpansion)
1731+
continue;
1732+
}
1733+
17231734
// Filter-out any decl that doesn't have the name we're looking for
17241735
// (asserting as a consistency-check that such entries all have
17251736
// @_implements attrs for the name!)
@@ -1755,12 +1766,16 @@ DirectLookupRequest::evaluate(Evaluator &evaluator,
17551766
decl->hasLazyMembers());
17561767
const bool includeAttrImplements =
17571768
flags.contains(NominalTypeDecl::LookupDirectFlags::IncludeAttrImplements);
1769+
const bool excludeMacroExpansions =
1770+
flags.contains(NominalTypeDecl::LookupDirectFlags::ExcludeMacroExpansions);
17581771

17591772
LLVM_DEBUG(llvm::dbgs() << decl->getNameStr() << ".lookupDirect("
17601773
<< name << ")"
17611774
<< ", hasLazyMembers()=" << decl->hasLazyMembers()
17621775
<< ", useNamedLazyMemberLoading="
17631776
<< useNamedLazyMemberLoading
1777+
<< ", excludeMacroExpansions="
1778+
<< excludeMacroExpansions
17641779
<< "\n");
17651780

17661781
decl->prepareLookupTable();
@@ -1797,8 +1812,9 @@ DirectLookupRequest::evaluate(Evaluator &evaluator,
17971812
if (!allFound.empty()) {
17981813
auto known = Table.find(name);
17991814
if (known != Table.end()) {
1800-
auto swiftLookupResult = maybeFilterOutAttrImplements(
1801-
known->second, name, includeAttrImplements);
1815+
auto swiftLookupResult = maybeFilterOutUnwantedDecls(
1816+
known->second, name, includeAttrImplements,
1817+
excludeMacroExpansions);
18021818
for (auto foundSwiftDecl : swiftLookupResult) {
18031819
allFound.push_back(foundSwiftDecl);
18041820
}
@@ -1828,7 +1844,8 @@ DirectLookupRequest::evaluate(Evaluator &evaluator,
18281844
}
18291845

18301846
DeclName macroExpansionKey = adjustLazyMacroExpansionNameKey(ctx, name);
1831-
if (!Table.isLazilyCompleteForMacroExpansion(macroExpansionKey)) {
1847+
if (!excludeMacroExpansions &&
1848+
!Table.isLazilyCompleteForMacroExpansion(macroExpansionKey)) {
18321849
populateLookupTableEntryFromMacroExpansions(
18331850
ctx, Table, macroExpansionKey, decl);
18341851
for (auto ext : decl->getExtensions()) {
@@ -1845,8 +1862,9 @@ DirectLookupRequest::evaluate(Evaluator &evaluator,
18451862
}
18461863

18471864
// We found something; return it.
1848-
return maybeFilterOutAttrImplements(known->second, name,
1849-
includeAttrImplements);
1865+
return maybeFilterOutUnwantedDecls(known->second, name,
1866+
includeAttrImplements,
1867+
excludeMacroExpansions);
18501868
}
18511869

18521870
bool NominalTypeDecl::createObjCMethodLookup() {
@@ -2201,6 +2219,8 @@ QualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC,
22012219
auto flags = OptionSet<NominalTypeDecl::LookupDirectFlags>();
22022220
if (options & NL_IncludeAttributeImplements)
22032221
flags |= NominalTypeDecl::LookupDirectFlags::IncludeAttrImplements;
2222+
if (options & NL_ExcludeMacroExpansions)
2223+
flags |= NominalTypeDecl::LookupDirectFlags::ExcludeMacroExpansions;
22042224
for (auto decl : current->lookupDirect(member.getFullName(), flags)) {
22052225
// If we're performing a type lookup, don't even attempt to validate
22062226
// the decl if its not a type.

0 commit comments

Comments
 (0)