Skip to content

Commit dd51251

Browse files
committed
Move semantic member synthesis into the type checker's lookup utilities
Pull these calls out of lookup itself to prevent re-entrancy. Synthesizing these members can force a conformance check that can ultimately wind up back in lookup. Pull the forcing out of every single qualified lookup and just install these members in the TypeChecker's entrypoints to lookup. The upside is we can localize this gross hack, the downside is, of course, that we have to smear it across all of the lookup entrypoints.
1 parent 5599df0 commit dd51251

File tree

2 files changed

+49
-35
lines changed

2 files changed

+49
-35
lines changed

lib/AST/NameLookup.cpp

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,34 +1579,6 @@ bool DeclContext::lookupQualified(Type type,
15791579
return lookupQualified(nominalTypesToLookInto, member, options, decls);
15801580
}
15811581

1582-
static void installPropertyWrapperMembersIfNeeded(NominalTypeDecl *target,
1583-
DeclName member) {
1584-
auto &Context = target->getASTContext();
1585-
auto baseName = member.getBaseName();
1586-
if (!member.isSimpleName() || baseName.isSpecial())
1587-
return;
1588-
1589-
if ((!baseName.getIdentifier().str().startswith("$") &&
1590-
!baseName.getIdentifier().str().startswith("_")) ||
1591-
baseName.getIdentifier().str().size() <= 1) {
1592-
return;
1593-
}
1594-
1595-
// $- and _-prefixed variables can be generated by properties that have
1596-
// attached property wrappers.
1597-
auto originalPropertyName =
1598-
Context.getIdentifier(baseName.getIdentifier().str().substr(1));
1599-
for (auto member : target->lookupDirect(originalPropertyName)) {
1600-
if (auto var = dyn_cast<VarDecl>(member)) {
1601-
if (var->hasAttachedPropertyWrapper()) {
1602-
auto sourceFile = var->getDeclContext()->getParentSourceFile();
1603-
if (sourceFile && sourceFile->Kind != SourceFileKind::Interface)
1604-
(void)var->getPropertyWrapperBackingProperty();
1605-
}
1606-
}
1607-
}
1608-
}
1609-
16101582
bool DeclContext::lookupQualified(ArrayRef<NominalTypeDecl *> typeDecls,
16111583
DeclName member,
16121584
NLOptions options,
@@ -1650,7 +1622,6 @@ bool DeclContext::lookupQualified(ArrayRef<NominalTypeDecl *> typeDecls,
16501622

16511623
// Visit all of the nominal types we know about, discovering any others
16521624
// we need along the way.
1653-
auto &ctx = getASTContext();
16541625
bool wantProtocolMembers = (options & NL_ProtocolMembers);
16551626
while (!stack.empty()) {
16561627
auto current = stack.back();
@@ -1659,12 +1630,6 @@ bool DeclContext::lookupQualified(ArrayRef<NominalTypeDecl *> typeDecls,
16591630
if (tracker)
16601631
tracker->addUsedMember({current, member.getBaseName()},isLookupCascading);
16611632

1662-
// Make sure we've resolved implicit members, if we need them.
1663-
if (ctx.areSemanticQueriesEnabled()) {
1664-
current->synthesizeSemanticMembersIfNeeded(member);
1665-
installPropertyWrapperMembersIfNeeded(current, member);
1666-
}
1667-
16681633
// Look for results within the current nominal type and its extensions.
16691634
bool currentIsProtocol = isa<ProtocolDecl>(current);
16701635
auto flags = OptionSet<NominalTypeDecl::LookupDirectFlags>();

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/AST/NameLookup.h"
2323
#include "swift/AST/NameLookupRequests.h"
2424
#include "swift/AST/ProtocolConformance.h"
25+
#include "swift/AST/SourceFile.h"
2526
#include "swift/Basic/TopCollection.h"
2627
#include <algorithm>
2728

@@ -223,11 +224,47 @@ convertToUnqualifiedLookupOptions(NameLookupOptions options) {
223224
return newOptions;
224225
}
225226

227+
static void installPropertyWrapperMembersIfNeeded(NominalTypeDecl *target,
228+
DeclName member) {
229+
if (!target) return;
230+
231+
auto &Context = target->getASTContext();
232+
auto baseName = member.getBaseName();
233+
if (!member.isSimpleName() || baseName.isSpecial())
234+
return;
235+
236+
if ((!baseName.getIdentifier().str().startswith("$") &&
237+
!baseName.getIdentifier().str().startswith("_")) ||
238+
baseName.getIdentifier().str().size() <= 1) {
239+
return;
240+
}
241+
242+
// $- and _-prefixed variables can be generated by properties that have
243+
// attached property wrappers.
244+
auto originalPropertyName =
245+
Context.getIdentifier(baseName.getIdentifier().str().substr(1));
246+
for (auto member : target->lookupDirect(originalPropertyName)) {
247+
if (auto var = dyn_cast<VarDecl>(member)) {
248+
if (var->hasAttachedPropertyWrapper()) {
249+
auto sourceFile = var->getDeclContext()->getParentSourceFile();
250+
if (sourceFile && sourceFile->Kind != SourceFileKind::Interface)
251+
(void)var->getPropertyWrapperBackingProperty();
252+
}
253+
}
254+
}
255+
}
256+
226257
LookupResult TypeChecker::lookupUnqualified(DeclContext *dc, DeclName name,
227258
SourceLoc loc,
228259
NameLookupOptions options) {
229260
auto ulOptions = convertToUnqualifiedLookupOptions(options);
230261

262+
// Make sure we've resolved implicit members, if we need them.
263+
if (auto *current = dc->getInnermostTypeContext()) {
264+
installPropertyWrapperMembersIfNeeded(current->getSelfNominalTypeDecl(),
265+
name);
266+
}
267+
231268
auto &ctx = dc->getASTContext();
232269
auto descriptor = UnqualifiedLookupDescriptor(name, dc, loc, ulOptions);
233270
auto lookup = evaluateOrDefault(ctx.evaluator,
@@ -311,6 +348,12 @@ LookupResult TypeChecker::lookupMember(DeclContext *dc,
311348
subOptions &= ~NL_RemoveOverridden;
312349
subOptions &= ~NL_RemoveNonVisible;
313350

351+
// Make sure we've resolved implicit members, if we need them.
352+
if (auto *current = type->getAnyNominal()) {
353+
current->synthesizeSemanticMembersIfNeeded(name);
354+
installPropertyWrapperMembersIfNeeded(current, name);
355+
}
356+
314357
LookupResultBuilder builder(result, dc, options);
315358
SmallVector<ValueDecl *, 4> lookupResults;
316359
dc->lookupQualified(type, name, subOptions, lookupResults);
@@ -385,6 +428,12 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc,
385428
if (options.contains(NameLookupFlags::IgnoreAccessControl))
386429
subOptions |= NL_IgnoreAccessControl;
387430

431+
// Make sure we've resolved implicit members, if we need them.
432+
if (auto *current = type->getAnyNominal()) {
433+
current->synthesizeSemanticMembersIfNeeded(name);
434+
installPropertyWrapperMembersIfNeeded(current, name);
435+
}
436+
388437
if (!dc->lookupQualified(type, name, subOptions, decls))
389438
return result;
390439

0 commit comments

Comments
 (0)