When sorting imports for uniquing purposes, use full module names

Fixes a longstanding issue where submodules with the same name in
different top-level modules weren't being sorted deterministically.
This doesn't come up very much in practice, and it would have been
hard to notice anything wrong, but it's good to be right.
This commit is contained in:
Jordan Rose
2018-09-06 19:53:41 -07:00
parent 37ec248823
commit 3c5fba3797
3 changed files with 34 additions and 3 deletions

View File

@@ -1059,9 +1059,11 @@ ModuleDecl::removeDuplicateImports(SmallVectorImpl<ImportedModule> &imports) {
std::sort(imports.begin(), imports.end(),
[](const ImportedModule &lhs, const ImportedModule &rhs) -> bool {
// Arbitrarily sort by name to get a deterministic order.
// FIXME: Submodules don't get sorted properly here.
if (lhs.second != rhs.second)
return lhs.second->getName().str() < rhs.second->getName().str();
if (lhs.second != rhs.second) {
return std::lexicographical_compare(
lhs.second->getReverseFullModuleName(), {},
rhs.second->getReverseFullModuleName(), {});
}
using AccessPathElem = std::pair<Identifier, SourceLoc>;
return std::lexicographical_compare(lhs.first.begin(), lhs.first.end(),
rhs.first.begin(), rhs.first.end(),

View File

@@ -0,0 +1,7 @@
module X {
explicit module Submodule {}
}
module Y {
explicit module Submodule {}
}

View File

@@ -0,0 +1,22 @@
// RUN: %target-swift-frontend -emit-interface-path - -emit-module -o /dev/null %s -I %S/Inputs/imports-submodule-order/ | %FileCheck %s
// RUN: %target-swift-frontend -emit-interface-path - -emit-module -o /dev/null %s -I %S/Inputs/imports-submodule-order/ -D XY | %FileCheck %s
#if XY
@_exported import X.Submodule
@_exported import Y.Submodule
#else
@_exported import Y.Submodule
@_exported import X.Submodule
#endif
// The order below is not alphabetical, just deterministic given a set of
// imports across any number of files and in any order.
// CHECK-NOT: import
// CHECK: import X.Submodule{{$}}
// CHECK-NEXT: import Y.Submodule{{$}}
// CHECK-NEXT: import X{{$}}
// CHECK-NEXT: import Y{{$}}
// CHECK-NOT: import