Skip to content

Commit 016acf3

Browse files
authored
Merge pull request #26864 from slavapestov/new-shadowing-rule-part-2
New shadowing rule, part 2
2 parents 771a390 + 37f308b commit 016acf3

File tree

7 files changed

+75
-62
lines changed

7 files changed

+75
-62
lines changed

include/swift/AST/ModuleNameLookup.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,24 +42,25 @@ enum class ResolutionKind {
4242
TypesOnly
4343
};
4444

45-
/// Performs a lookup into the given module and, if necessary, its
46-
/// reexports, observing proper shadowing rules.
45+
/// Performs a lookup into the given module and it's imports.
46+
///
47+
/// If 'moduleOrFile' is a ModuleDecl, we search the module and it's
48+
/// public imports. If 'moduleOrFile' is a SourceFile, we search the
49+
/// file's parent module, the module's public imports, and the source
50+
/// file's private imports.
4751
///
48-
/// \param module The module that will contain the name.
49-
/// \param accessPath The import scope on \p module.
52+
/// \param moduleOrFile The module or file unit whose imports to search.
5053
/// \param name The name to look up.
5154
/// \param[out] decls Any found decls will be added to this vector.
5255
/// \param lookupKind Whether this lookup is qualified or unqualified.
5356
/// \param resolutionKind What sort of decl is expected.
5457
/// \param moduleScopeContext The top-level context from which the lookup is
5558
/// being performed, for checking access. This must be either a
5659
/// FileUnit or a Module.
57-
/// \param extraImports Private imports to include in this search.
58-
void lookupInModule(ModuleDecl *module, ModuleDecl::AccessPathTy accessPath,
60+
void lookupInModule(const DeclContext *moduleOrFile,
5961
DeclName name, SmallVectorImpl<ValueDecl *> &decls,
6062
NLKind lookupKind, ResolutionKind resolutionKind,
61-
const DeclContext *moduleScopeContext,
62-
ArrayRef<ModuleDecl::ImportedModule> extraImports = {});
63+
const DeclContext *moduleScopeContext);
6364

6465
template <typename Fn>
6566
void forAllVisibleModules(const DeclContext *DC, const Fn &fn) {
@@ -74,12 +75,12 @@ void forAllVisibleModules(const DeclContext *DC, const Fn &fn) {
7475
/// Performs a qualified lookup into the given module and, if necessary, its
7576
/// reexports, observing proper shadowing rules.
7677
void
77-
lookupVisibleDeclsInModule(ModuleDecl *M, ModuleDecl::AccessPathTy accessPath,
78+
lookupVisibleDeclsInModule(const DeclContext *moduleOrFile,
79+
ModuleDecl::AccessPathTy accessPath,
7880
SmallVectorImpl<ValueDecl *> &decls,
7981
NLKind lookupKind,
8082
ResolutionKind resolutionKind,
81-
const DeclContext *moduleScopeContext,
82-
ArrayRef<ModuleDecl::ImportedModule> extraImports = {});
83+
const DeclContext *moduleScopeContext);
8384

8485
} // end namespace namelookup
8586

lib/AST/ModuleNameLookup.cpp

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -444,38 +444,59 @@ void ModuleNameLookup<LookupStrategy>::lookupInModule(
444444
cache.try_emplace(cacheKey, lookupResults);
445445
}
446446

447-
void namelookup::lookupInModule(ModuleDecl *startModule,
448-
ModuleDecl::AccessPathTy topAccessPath,
447+
void namelookup::lookupInModule(const DeclContext *moduleOrFile,
449448
DeclName name,
450449
SmallVectorImpl<ValueDecl *> &decls,
451450
NLKind lookupKind,
452451
ResolutionKind resolutionKind,
453-
const DeclContext *moduleScopeContext,
454-
ArrayRef<ModuleDecl::ImportedModule> extraImports) {
452+
const DeclContext *moduleScopeContext) {
453+
assert(moduleScopeContext->isModuleScopeContext());
454+
455+
auto *startModule = moduleOrFile->getParentModule();
455456
auto &ctx = startModule->getASTContext();
456457
auto *stats = ctx.Stats;
457458
if (stats)
458459
stats->getFrontendCounters().NumLookupInModule++;
459460

460461
FrontendStatsTracer tracer(stats, "lookup-in-module");
461462

462-
assert(moduleScopeContext && moduleScopeContext->isModuleScopeContext());
463+
// Add private imports to the extra search list.
464+
SmallVector<ModuleDecl::ImportedModule, 8> extraImports;
465+
if (auto *file = dyn_cast<FileUnit>(moduleOrFile)) {
466+
ModuleDecl::ImportFilter importFilter;
467+
importFilter |= ModuleDecl::ImportFilterKind::Private;
468+
importFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly;
469+
file->getImportedModules(extraImports, importFilter);
470+
}
471+
463472
LookupByName lookup(ctx, resolutionKind, name, lookupKind);
464-
lookup.lookupInModule(decls, startModule, topAccessPath, moduleScopeContext,
473+
lookup.lookupInModule(decls, startModule, {}, moduleScopeContext,
465474
extraImports);
466475
}
467476

468477
void namelookup::lookupVisibleDeclsInModule(
469-
ModuleDecl *M,
478+
const DeclContext *moduleOrFile,
470479
ModuleDecl::AccessPathTy accessPath,
471480
SmallVectorImpl<ValueDecl *> &decls,
472481
NLKind lookupKind,
473482
ResolutionKind resolutionKind,
474-
const DeclContext *moduleScopeContext,
475-
ArrayRef<ModuleDecl::ImportedModule> extraImports) {
476-
auto &ctx = M->getASTContext();
477-
assert(moduleScopeContext && moduleScopeContext->isModuleScopeContext());
483+
const DeclContext *moduleScopeContext) {
484+
assert(moduleScopeContext->isModuleScopeContext());
485+
486+
auto *startModule = moduleOrFile->getParentModule();
487+
auto &ctx = startModule->getASTContext();
488+
489+
// Add private imports to the extra search list.
490+
SmallVector<ModuleDecl::ImportedModule, 8> extraImports;
491+
if (auto *file = dyn_cast<FileUnit>(moduleOrFile)) {
492+
ModuleDecl::ImportFilter importFilter;
493+
importFilter |= ModuleDecl::ImportFilterKind::Private;
494+
importFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly;
495+
file->getImportedModules(extraImports, importFilter);
496+
}
497+
478498
LookupVisibleDecls lookup(ctx, resolutionKind, lookupKind);
479-
lookup.lookupInModule(decls, M, accessPath, moduleScopeContext, extraImports);
499+
lookup.lookupInModule(decls, startModule, accessPath, moduleScopeContext,
500+
extraImports);
480501
}
481502

lib/AST/NameLookup.cpp

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,17 @@ static void recordShadowedDeclsAfterSignatureMatch(
206206
if (firstModule != secondModule &&
207207
firstDecl->getDeclContext()->isModuleScopeContext() &&
208208
secondDecl->getDeclContext()->isModuleScopeContext()) {
209+
// First, scoped imports shadow unscoped imports.
210+
bool firstScoped = imports.isScopedImport(firstModule, name, dc);
211+
bool secondScoped = imports.isScopedImport(secondModule, name, dc);
212+
if (!firstScoped && secondScoped) {
213+
shadowed.insert(firstDecl);
214+
break;
215+
} else if (firstScoped && !secondScoped) {
216+
shadowed.insert(secondDecl);
217+
continue;
218+
}
219+
209220
// Now check if one module shadows the other.
210221
if (imports.isShadowedBy(firstModule, secondModule, name, dc)) {
211222
shadowed.insert(firstDecl);
@@ -261,22 +272,19 @@ static void recordShadowedDeclsAfterSignatureMatch(
261272
isa<ProtocolDecl>(secondDecl->getDeclContext()))
262273
continue;
263274

264-
// Prefer declarations in the current module over those in another
265-
// module.
266-
// FIXME: This is a hack. We should query a (lazily-built, cached)
267-
// module graph to determine shadowing.
268-
if ((firstModule == curModule) != (secondModule == curModule)) {
269-
// If the first module is the current module, the second declaration
270-
// is shadowed by the first.
271-
if (firstModule == curModule) {
275+
// [Backward compatibility] For members of types, the general module
276+
// shadowing check is performed after unavailable candidates have
277+
// already been dropped.
278+
if (firstModule != secondModule &&
279+
!firstDecl->getDeclContext()->isModuleScopeContext() &&
280+
!secondDecl->getDeclContext()->isModuleScopeContext()) {
281+
if (imports.isShadowedBy(firstModule, secondModule, dc)) {
282+
shadowed.insert(firstDecl);
283+
break;
284+
} else if (imports.isShadowedBy(secondModule, firstModule, dc)) {
272285
shadowed.insert(secondDecl);
273286
continue;
274287
}
275-
276-
// Otherwise, the first declaration is shadowed by the second. There is
277-
// no point in continuing to compare the first declaration to others.
278-
shadowed.insert(firstDecl);
279-
break;
280288
}
281289

282290
// Prefer declarations in the any module over those in the standard
@@ -1645,7 +1653,7 @@ bool DeclContext::lookupQualified(ModuleDecl *module, DeclName member,
16451653
if (tracker) {
16461654
recordLookupOfTopLevelName(topLevelScope, member, isLookupCascading);
16471655
}
1648-
lookupInModule(module, /*accessPath=*/{}, member, decls,
1656+
lookupInModule(module, member, decls,
16491657
NLKind::QualifiedLookup, kind, topLevelScope);
16501658
} else {
16511659
// Note: This is a lookup into another module. Unless we're compiling
@@ -1660,7 +1668,7 @@ bool DeclContext::lookupQualified(ModuleDecl *module, DeclName member,
16601668
[&](ModuleDecl::AccessPathTy accessPath) {
16611669
return ModuleDecl::matchesAccessPath(accessPath, member);
16621670
})) {
1663-
lookupInModule(module, {}, member, decls,
1671+
lookupInModule(module, member, decls,
16641672
NLKind::QualifiedLookup, kind, topLevelScope);
16651673
}
16661674
}

lib/AST/UnqualifiedLookup.cpp

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -963,21 +963,12 @@ void UnqualifiedLookupFactory::recordDependencyOnTopLevelName(
963963
}
964964

965965
void UnqualifiedLookupFactory::addImportedResults(DeclContext *const dc) {
966-
// Add private imports to the extra search list.
967-
SmallVector<ModuleDecl::ImportedModule, 8> extraImports;
968-
if (auto FU = dyn_cast<FileUnit>(dc)) {
969-
ModuleDecl::ImportFilter importFilter;
970-
importFilter |= ModuleDecl::ImportFilterKind::Private;
971-
importFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly;
972-
FU->getImportedModules(extraImports, importFilter);
973-
}
974-
975966
using namespace namelookup;
976967
SmallVector<ValueDecl *, 8> CurModuleResults;
977968
auto resolutionKind = isOriginallyTypeLookup ? ResolutionKind::TypesOnly
978969
: ResolutionKind::Overloadable;
979-
lookupInModule(&M, {}, Name, CurModuleResults, NLKind::UnqualifiedLookup,
980-
resolutionKind, dc, extraImports);
970+
lookupInModule(dc, Name, CurModuleResults, NLKind::UnqualifiedLookup,
971+
resolutionKind, dc);
981972

982973
// Always perform name shadowing for type lookup.
983974
if (options.contains(Flags::TypeLookup)) {

lib/Sema/LookupVisibleDecls.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,6 @@ static void lookupVisibleMemberDecls(
10181018
static void lookupVisibleDeclsImpl(VisibleDeclConsumer &Consumer,
10191019
const DeclContext *DC,
10201020
bool IncludeTopLevel, SourceLoc Loc) {
1021-
const ModuleDecl &M = *DC->getParentModule();
10221021
const SourceManager &SM = DC->getASTContext().SourceMgr;
10231022
auto Reason = DeclVisibilityKind::MemberOfCurrentNominal;
10241023

@@ -1121,7 +1120,6 @@ static void lookupVisibleDeclsImpl(VisibleDeclConsumer &Consumer,
11211120
Reason = DeclVisibilityKind::MemberOfOutsideNominal;
11221121
}
11231122

1124-
SmallVector<ModuleDecl::ImportedModule, 8> extraImports;
11251123
if (auto SF = dyn_cast<SourceFile>(DC)) {
11261124
if (Loc.isValid()) {
11271125
// Look for local variables in top-level code; normally, the parser
@@ -1137,22 +1135,16 @@ static void lookupVisibleDeclsImpl(VisibleDeclConsumer &Consumer,
11371135
Consumer.foundDecl(result, DeclVisibilityKind::VisibleAtTopLevel);
11381136
return;
11391137
}
1140-
1141-
ModuleDecl::ImportFilter importFilter;
1142-
importFilter |= ModuleDecl::ImportFilterKind::Private;
1143-
importFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly;
1144-
SF->getImportedModules(extraImports, importFilter);
11451138
}
11461139
}
11471140

11481141
if (IncludeTopLevel) {
11491142
using namespace namelookup;
11501143
SmallVector<ValueDecl *, 0> moduleResults;
1151-
auto &mutableM = const_cast<ModuleDecl&>(M);
1152-
lookupVisibleDeclsInModule(&mutableM, {}, moduleResults,
1144+
lookupVisibleDeclsInModule(DC, {}, moduleResults,
11531145
NLKind::UnqualifiedLookup,
11541146
ResolutionKind::Overloadable,
1155-
DC, extraImports);
1147+
DC);
11561148
for (auto result : moduleResults)
11571149
Consumer.foundDecl(result, DeclVisibilityKind::VisibleAtTopLevel);
11581150

lib/Sema/NameBinding.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ void NameBinder::addImport(
295295
// FIXME: Doesn't handle scoped testable imports correctly.
296296
assert(declPath.size() == 1 && "can't handle sub-decl imports");
297297
SmallVector<ValueDecl *, 8> decls;
298-
lookupInModule(topLevelModule, declPath, declPath.front().first, decls,
298+
lookupInModule(topLevelModule, declPath.front().first, decls,
299299
NLKind::QualifiedLookup, ResolutionKind::Overloadable,
300300
&SF);
301301

test/NameBinding/import-resolution.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ letters.asdf.A // expected-error{{module 'letters' has no member named 'asdf'}}
3232
var uA : A // expected-error {{'A' is ambiguous for type lookup in this context}}
3333
var uB : B = abcde.B()
3434
var uC : C // expected-error {{'C' is ambiguous for type lookup in this context}}
35-
var uD : D // expected-error {{'D' is ambiguous for type lookup in this context}}
36-
var uE : E // expected-error {{'E' is ambiguous for type lookup in this context}}
35+
var uD : D = asdf.D()
36+
var uE : E = aeiou.E()
3737
var uF : F = letters.F()
3838

3939
var qA1 : abcde.A // okay

0 commit comments

Comments
 (0)