Skip to content

Commit 747c507

Browse files
committed
Add a warning about redundant cross-import declarations
These are mostly harmless, except that they make the two module names synonymous in qualified lookup. A hard error seems too aggressive for something that could easily be caused by uncoordinated changes to two modules, so warn instead.
1 parent 17087cb commit 747c507

File tree

6 files changed

+40
-5
lines changed

6 files changed

+40
-5
lines changed

include/swift/AST/DiagnosticsCommon.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,11 @@ ERROR(cannot_load_swiftoverlay_file, none,
174174
ERROR(cannot_list_swiftcrossimport_dir, none,
175175
"cannot list cross-import overlays for %0: %1 (declared in '%2')",
176176
(Identifier, StringRef, StringRef))
177+
WARNING(cross_imported_by_both_modules, none,
178+
"modules %0 and %1 both declare module %2 as a cross-import overlay, "
179+
"which may cause paradoxical behavior when looking up names in them; "
180+
"please report this bug to the maintainers of these modules",
181+
(Identifier, Identifier, Identifier))
177182

178183
#ifndef DIAG_NO_UNDEF
179184
# if defined(DIAG)

lib/Sema/NameBinding.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,8 @@ namespace {
201201
/// locations from \p I.
202202
void findCrossImports(UnboundImport &I,
203203
const ImportedModuleDesc &declaringImport,
204-
const ImportedModuleDesc &bystandingImport);
204+
const ImportedModuleDesc &bystandingImport,
205+
SmallVectorImpl<Identifier> &overlayNames);
205206

206207
/// Load a module referenced by an import statement.
207208
///
@@ -815,8 +816,21 @@ void NameBinder::crossImport(ModuleDecl *M, UnboundImport &I) {
815816
if (!canCrossImport(oldImport))
816817
continue;
817818

818-
findCrossImports(I, newImport, oldImport);
819-
findCrossImports(I, oldImport, newImport);
819+
SmallVector<Identifier, 2> newImportOverlays;
820+
findCrossImports(I, newImport, oldImport, newImportOverlays);
821+
822+
SmallVector<Identifier, 2> oldImportOverlays;
823+
findCrossImports(I, oldImport, newImport, oldImportOverlays);
824+
825+
// If both sides of the cross-import declare some of the same overlays,
826+
// this will cause some strange name lookup behavior; let's warn about it.
827+
for (auto name : newImportOverlays) {
828+
if (llvm::is_contained(oldImportOverlays, name)) {
829+
ctx.Diags.diagnose(I.importLoc, diag::cross_imported_by_both_modules,
830+
newImport.module.second->getName(),
831+
oldImport.module.second->getName(), name);
832+
}
833+
}
820834

821835
// If findCrossImports() ever changed the visibleModules list, we'd see
822836
// memory smashers here.
@@ -830,7 +844,8 @@ void NameBinder::crossImport(ModuleDecl *M, UnboundImport &I) {
830844

831845
void NameBinder::findCrossImports(UnboundImport &I,
832846
const ImportedModuleDesc &declaringImport,
833-
const ImportedModuleDesc &bystandingImport) {
847+
const ImportedModuleDesc &bystandingImport,
848+
SmallVectorImpl<Identifier> &names) {
834849
assert(&declaringImport != &bystandingImport);
835850

836851
LLVM_DEBUG(
@@ -839,7 +854,6 @@ void NameBinder::findCrossImports(UnboundImport &I,
839854
<< bystandingImport.module.second->getName() << "'\n");
840855

841856
// Find modules we need to import.
842-
SmallVector<Identifier, 2> names;
843857
declaringImport.module.second->findDeclaredCrossImportOverlays(
844858
bystandingImport.module.second->getName(), names, I.importLoc);
845859

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
version: 1
3+
modules:
4+
- name: _OverlayLibrary
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
version: 1
3+
modules:
4+
- name: _OverlayLibrary
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// swift-interface-format-version: 1.0
2+
// swift-module-flags: -swift-version 5 -enable-library-evolution -module-name RedundantGoose
3+
4+
import Swift
5+

test/CrossImport/horrible.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ import ListlessGoose
3636
import AnonymousGoose
3737
// expected-error@-1 {{cannot load cross-import overlay for 'HorribleGoose' and 'AnonymousGoose': missing required key 'name'}}
3838

39+
import RedundantGoose
40+
// expected-warning@-1 {{modules 'RedundantGoose' and 'HorribleGoose' both declare module '_OverlayLibrary' as a cross-import overlay, which may cause paradoxical behavior when looking up names in them; please report this bug to the maintainers of these modules}}
41+
3942
// CircularGoose overlays itself with EndlessGoose, which overlays itself with
4043
// CircularGoose, which should then break the cycle because we don't load the
4144
// same overlay on an underlying module twice. If the test hangs, we've broken

0 commit comments

Comments
 (0)