From b440ab73315b4d4bb288078e241d974ae8a6e7d4 Mon Sep 17 00:00:00 2001 From: Brent Royal-Gordon Date: Fri, 25 Sep 2020 13:48:30 -0700 Subject: [PATCH 01/13] [NFC] Move several types/functions to Import.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To help consolidate our various types describing imports, this commit moves the following types and methods to Import.h: * ImplicitImports * ImplicitStdlibKind * ImplicitImportInfo * ModuleDecl::ImportedModule * ModuleDecl::OrderImportedModules (as ImportedModule::Order) * ModuleDecl::removeDuplicateImports() (as ImportedModule::removeDuplicates()) * SourceFile::ImportFlags * SourceFile::ImportOptions * SourceFile::ImportedModuleDesc This commit is large and intentionally kept mechanical—nothing interesting to see here. --- include/swift/AST/FileUnit.h | 4 +- include/swift/AST/Import.h | 242 +++++++++++++++++- include/swift/AST/ImportCache.h | 28 +- include/swift/AST/Module.h | 103 -------- include/swift/AST/SourceFile.h | 111 +------- include/swift/AST/TypeCheckRequests.h | 19 -- include/swift/ClangImporter/ClangModule.h | 6 +- .../Serialization/SerializedModuleLoader.h | 2 +- lib/AST/ImportCache.cpp | 42 ++- lib/AST/Module.cpp | 22 +- lib/AST/ModuleNameLookup.cpp | 5 +- lib/AST/NameLookup.cpp | 3 +- lib/AST/OperatorNameLookup.cpp | 3 +- lib/ClangImporter/ClangImporter.cpp | 6 +- lib/ClangImporter/DWARFImporter.cpp | 4 +- lib/Frontend/ModuleInterfaceSupport.cpp | 18 +- lib/FrontendTool/FrontendTool.cpp | 4 +- lib/FrontendTool/ImportedModules.cpp | 2 +- lib/IDE/CodeCompletion.cpp | 8 +- lib/IDE/REPLCodeCompletion.cpp | 2 +- lib/IRGen/IRGenDebugInfo.cpp | 8 +- lib/Index/Index.cpp | 6 +- lib/Index/IndexRecord.cpp | 6 +- lib/Sema/ImportResolution.cpp | 7 +- lib/Serialization/ModuleFile.cpp | 11 +- lib/Serialization/ModuleFile.h | 4 +- lib/Serialization/Serialization.cpp | 19 +- lib/Serialization/SerializedModuleLoader.cpp | 4 +- .../lib/SwiftLang/CodeCompletionOrganizer.cpp | 4 +- .../lib/SwiftLang/SwiftASTManager.cpp | 2 +- tools/swift-ide-test/swift-ide-test.cpp | 2 +- 31 files changed, 350 insertions(+), 357 deletions(-) diff --git a/include/swift/AST/FileUnit.h b/include/swift/AST/FileUnit.h index ec8ea98f22b88..16d6e46d749dd 100644 --- a/include/swift/AST/FileUnit.h +++ b/include/swift/AST/FileUnit.h @@ -235,12 +235,12 @@ class FileUnit : public DeclContext { /// \p filter controls whether public, private, or any imports are included /// in this list. virtual void - getImportedModules(SmallVectorImpl &imports, + getImportedModules(SmallVectorImpl &imports, ModuleDecl::ImportFilter filter) const {} /// \see ModuleDecl::getImportedModulesForLookup virtual void getImportedModulesForLookup( - SmallVectorImpl &imports) const { + SmallVectorImpl &imports) const { return getImportedModules(imports, ModuleDecl::ImportFilterKind::Exported); } diff --git a/include/swift/AST/Import.h b/include/swift/AST/Import.h index 55f5bd642f0f5..6bb179543213e 100644 --- a/include/swift/AST/Import.h +++ b/include/swift/AST/Import.h @@ -21,14 +21,19 @@ #include "swift/AST/Identifier.h" #include "swift/Basic/Located.h" +#include "swift/Basic/OptionSet.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include namespace swift { class ASTContext; +class ModuleDecl; + +// MARK: - Fundamental import enums /// Describes what kind of name is being imported. /// @@ -45,6 +50,39 @@ enum class ImportKind : uint8_t { Func }; +/// Possible attributes for imports in source files. +enum class ImportFlags { + /// The imported module is exposed to anyone who imports the parent module. + Exported = 0x1, + + /// This source file has access to testable declarations in the imported + /// module. + Testable = 0x2, + + /// This source file has access to private declarations in the imported + /// module. + PrivateImport = 0x4, + + /// The imported module is an implementation detail of this file and should + /// not be required to be present if the main module is ever imported + /// elsewhere. + /// + /// Mutually exclusive with Exported. + ImplementationOnly = 0x8, + + // The module is imported to have access to named SPIs which is an + // implementation detail of this file. + SPIAccessControl = 0x10, + + /// Used for DenseMap. + Reserved = 0x80 +}; + +/// \see ImportFlags +using ImportOptions = OptionSet; + +// MARK: - Import Paths + namespace detail { using ImportPathElement = Located; using ImportPathRaw = llvm::ArrayRef; @@ -362,6 +400,208 @@ class ImportPath : public detail::ImportPathBase { } }; +// MARK: - Abstractions of imports + +/// Convenience struct to keep track of a module along with its access path. +struct alignas(uint64_t) ImportedModule { + /// The access path from an import: `import Foo.Bar` -> `Foo.Bar`. + ImportPath::Access accessPath; + /// The actual module corresponding to the import. + /// + /// Invariant: The pointer is non-null. + ModuleDecl *importedModule; + + ImportedModule(ImportPath::Access accessPath, + ModuleDecl *importedModule) + : accessPath(accessPath), importedModule(importedModule) { + assert(this->importedModule); + } + + bool operator==(const ImportedModule &other) const { + return (this->importedModule == other.importedModule) && + (this->accessPath == other.accessPath); + } + + /// Uniques the items in \p imports, ignoring the source locations of the + /// access paths. + /// + /// The order of items in \p imports is \e not preserved. + static void removeDuplicates(SmallVectorImpl &imports); + + /// Arbitrarily orders ImportedModule records, for inclusion in sets and such. + class Order { + public: + bool operator()(const ImportedModule &lhs, + const ImportedModule &rhs) const { + if (lhs.importedModule != rhs.importedModule) + return std::less()(lhs.importedModule, + rhs.importedModule); + if (lhs.accessPath.getRaw().data() != rhs.accessPath.getRaw().data()) + return std::less()(lhs.accessPath.begin(), + rhs.accessPath.begin()); + return lhs.accessPath.size() < rhs.accessPath.size(); + } + }; +}; + +struct ImportedModuleDesc { + ImportedModule module; + ImportOptions importOptions; + + // Filename for a @_private import. + StringRef filename; + + // Names of explicitly imported SPIs. + ArrayRef spiGroups; + + ImportedModuleDesc(ImportedModule module, ImportOptions options, + StringRef filename = {}, + ArrayRef spiGroups = {}) + : module(module), importOptions(options), filename(filename), + spiGroups(spiGroups) { + assert(!(importOptions.contains(ImportFlags::Exported) && + importOptions.contains(ImportFlags::ImplementationOnly)) || + importOptions.contains(ImportFlags::Reserved)); + } +}; + +// MARK: - Implicit imports + +/// A module which has been implicitly imported. +struct ImplicitImport { + ModuleDecl *Module; + ImportOptions Options; + + ImplicitImport(ModuleDecl *module, ImportOptions opts = {}) + : Module(module), Options(opts) {} + + friend bool operator==(const ImplicitImport &lhs, + const ImplicitImport &rhs) { + return lhs.Module == rhs.Module && + lhs.Options.toRaw() == rhs.Options.toRaw(); + } +}; + +void simple_display(llvm::raw_ostream &out, const ImplicitImport &import); + +/// The kind of stdlib that should be imported. +enum class ImplicitStdlibKind { + /// No standard library should be implicitly imported. + None, + + /// The Builtin module should be implicitly imported. + Builtin, + + /// The regular Swift standard library should be implicitly imported. + Stdlib +}; + +struct ImplicitImportInfo { + /// The implicit stdlib to import. + ImplicitStdlibKind StdlibKind; + + /// Whether we should attempt to import an underlying Clang half of this + /// module. + bool ShouldImportUnderlyingModule; + + /// The bridging header path for this module, empty if there is none. + StringRef BridgingHeaderPath; + + /// The names of additional modules to be implicitly imported. + SmallVector ModuleNames; + + /// An additional list of already-loaded modules which should be implicitly + /// imported. + SmallVector, 4> + AdditionalModules; + + ImplicitImportInfo() + : StdlibKind(ImplicitStdlibKind::None), + ShouldImportUnderlyingModule(false) {} +}; + +} + +// MARK: - DenseMapInfo + +namespace llvm { + +template<> +struct DenseMapInfo { + using ImportOptions = swift::ImportOptions; + + using UnsignedDMI = DenseMapInfo; + + static inline ImportOptions getEmptyKey() { + return ImportOptions(UnsignedDMI::getEmptyKey()); + } + static inline ImportOptions getTombstoneKey() { + return ImportOptions(UnsignedDMI::getTombstoneKey()); + } + static inline unsigned getHashValue(ImportOptions options) { + return UnsignedDMI::getHashValue(options.toRaw()); + } + static bool isEqual(ImportOptions a, ImportOptions b) { + return UnsignedDMI::isEqual(a.toRaw(), b.toRaw()); + } +}; + +template <> +class DenseMapInfo { + using ImportedModule = swift::ImportedModule; + using ModuleDecl = swift::ModuleDecl; +public: + static ImportedModule getEmptyKey() { + return {{}, llvm::DenseMapInfo::getEmptyKey()}; + } + static ImportedModule getTombstoneKey() { + return {{}, llvm::DenseMapInfo::getTombstoneKey()}; + } + + static unsigned getHashValue(const ImportedModule &val) { + auto pair = std::make_pair(val.accessPath.size(), val.importedModule); + return llvm::DenseMapInfo::getHashValue(pair); + } + + static bool isEqual(const ImportedModule &lhs, + const ImportedModule &rhs) { + return lhs.importedModule == rhs.importedModule && + lhs.accessPath.isSameAs(rhs.accessPath); + } +}; + +template<> +struct DenseMapInfo { + using ImportedModuleDesc = swift::ImportedModuleDesc; + + using ImportedModuleDMI = DenseMapInfo; + using ImportOptionsDMI = DenseMapInfo; + using StringRefDMI = DenseMapInfo; + + static inline ImportedModuleDesc getEmptyKey() { + return ImportedModuleDesc(ImportedModuleDMI::getEmptyKey(), + ImportOptionsDMI::getEmptyKey(), + StringRefDMI::getEmptyKey()); + } + static inline ImportedModuleDesc getTombstoneKey() { + return ImportedModuleDesc(ImportedModuleDMI::getTombstoneKey(), + ImportOptionsDMI::getTombstoneKey(), + StringRefDMI::getTombstoneKey()); + } + static inline unsigned getHashValue(const ImportedModuleDesc &import) { + return detail::combineHashValue( + ImportedModuleDMI::getHashValue(import.module), + detail::combineHashValue( + ImportOptionsDMI::getHashValue(import.importOptions), + StringRefDMI::getHashValue(import.filename))); + } + static bool isEqual(const ImportedModuleDesc &a, + const ImportedModuleDesc &b) { + return ImportedModuleDMI::isEqual(a.module, b.module) && + ImportOptionsDMI::isEqual(a.importOptions, b.importOptions) && + StringRefDMI::isEqual(a.filename, b.filename); + } +}; } #endif diff --git a/include/swift/AST/ImportCache.h b/include/swift/AST/ImportCache.h index e52e322c604a0..5334b5ddddd36 100644 --- a/include/swift/AST/ImportCache.h +++ b/include/swift/AST/ImportCache.h @@ -49,7 +49,7 @@ namespace namelookup { /// it was explicitly imported (or re-exported). class ImportSet final : public llvm::FoldingSetNode, - private llvm::TrailingObjects { + private llvm::TrailingObjects { friend TrailingObjects; friend class ImportCache; @@ -58,8 +58,8 @@ class ImportSet final : unsigned NumTransitiveImports; ImportSet(bool hasHeaderImportModule, - ArrayRef topLevelImports, - ArrayRef transitiveImports); + ArrayRef topLevelImports, + ArrayRef transitiveImports); ImportSet(const ImportSet &) = delete; void operator=(const ImportSet &) = delete; @@ -70,9 +70,9 @@ class ImportSet final : } static void Profile( llvm::FoldingSetNodeID &ID, - ArrayRef topLevelImports); + ArrayRef topLevelImports); - size_t numTrailingObjects(OverloadToken) const { + size_t numTrailingObjects(OverloadToken) const { return NumTopLevelImports + NumTransitiveImports; } @@ -83,24 +83,24 @@ class ImportSet final : return HasHeaderImportModule; } - ArrayRef getTopLevelImports() const { - return {getTrailingObjects(), + ArrayRef getTopLevelImports() const { + return {getTrailingObjects(), NumTopLevelImports}; } - ArrayRef getTransitiveImports() const { - return {getTrailingObjects() + + ArrayRef getTransitiveImports() const { + return {getTrailingObjects() + NumTopLevelImports, NumTransitiveImports}; } - ArrayRef getAllImports() const { - return {getTrailingObjects(), + ArrayRef getAllImports() const { + return {getTrailingObjects(), NumTopLevelImports + NumTransitiveImports}; } }; -class alignas(ModuleDecl::ImportedModule) ImportCache { +class alignas(ImportedModule) ImportCache { ImportCache(const ImportCache &) = delete; void operator=(const ImportCache &) = delete; @@ -121,7 +121,7 @@ class alignas(ModuleDecl::ImportedModule) ImportCache { SmallVectorImpl &results); ImportSet &getImportSet(ASTContext &ctx, - ArrayRef topLevelImports); + ArrayRef topLevelImports); public: ImportCache() {} @@ -154,7 +154,7 @@ class alignas(ModuleDecl::ImportedModule) ImportCache { } }; -ArrayRef getAllImports(const DeclContext *dc); +ArrayRef getAllImports(const DeclContext *dc); } // namespace namelookup diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index 7717bc02cfee3..3c3dcb0485995 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -154,42 +154,6 @@ enum class ResilienceStrategy : unsigned { Resilient }; -/// The kind of stdlib that should be imported. -enum class ImplicitStdlibKind { - /// No standard library should be implicitly imported. - None, - - /// The Builtin module should be implicitly imported. - Builtin, - - /// The regular Swift standard library should be implicitly imported. - Stdlib -}; - -struct ImplicitImportInfo { - /// The implicit stdlib to import. - ImplicitStdlibKind StdlibKind; - - /// Whether we should attempt to import an underlying Clang half of this - /// module. - bool ShouldImportUnderlyingModule; - - /// The bridging header path for this module, empty if there is none. - StringRef BridgingHeaderPath; - - /// The names of additional modules to be implicitly imported. - SmallVector ModuleNames; - - /// An additional list of already-loaded modules which should be implicitly - /// imported. - SmallVector, 4> - AdditionalModules; - - ImplicitImportInfo() - : StdlibKind(ImplicitStdlibKind::None), - ShouldImportUnderlyingModule(false) {} -}; - class OverlayFile; /// The minimum unit of compilation. @@ -203,42 +167,6 @@ class ModuleDecl : public DeclContext, public TypeDecl { friend class DirectPrecedenceGroupLookupRequest; public: - /// Convenience struct to keep track of a module along with its access path. - struct alignas(uint64_t) ImportedModule { - /// The access path from an import: `import Foo.Bar` -> `Foo.Bar`. - ImportPath::Access accessPath; - /// The actual module corresponding to the import. - /// - /// Invariant: The pointer is non-null. - ModuleDecl *importedModule; - - ImportedModule(ImportPath::Access accessPath, - ModuleDecl *importedModule) - : accessPath(accessPath), importedModule(importedModule) { - assert(this->importedModule); - } - - bool operator==(const ModuleDecl::ImportedModule &other) const { - return (this->importedModule == other.importedModule) && - (this->accessPath == other.accessPath); - } - }; - - /// Arbitrarily orders ImportedModule records, for inclusion in sets and such. - class OrderImportedModules { - public: - bool operator()(const ImportedModule &lhs, - const ImportedModule &rhs) const { - if (lhs.importedModule != rhs.importedModule) - return std::less()(lhs.importedModule, - rhs.importedModule); - if (lhs.accessPath.getRaw().data() != rhs.accessPath.getRaw().data()) - return std::less()(lhs.accessPath.begin(), - rhs.accessPath.begin()); - return lhs.accessPath.size() < rhs.accessPath.size(); - } - }; - /// Produces the components of a given module's full name in reverse order. /// /// For a Swift module, this will only ever have one component, but an @@ -715,12 +643,6 @@ class ModuleDecl : public DeclContext, public TypeDecl { /// This assumes that \p module was imported. bool isImportedImplementationOnly(const ModuleDecl *module) const; - /// Uniques the items in \p imports, ignoring the source locations of the - /// access paths. - /// - /// The order of items in \p imports is \e not preserved. - static void removeDuplicateImports(SmallVectorImpl &imports); - /// Finds all top-level decls of this module. /// /// This does a simple local lookup, not recursively looking through imports. @@ -887,29 +809,4 @@ inline SourceLoc extractNearestSourceLoc(const ModuleDecl *mod) { } // end namespace swift -namespace llvm { - template <> - class DenseMapInfo { - using ModuleDecl = swift::ModuleDecl; - public: - static ModuleDecl::ImportedModule getEmptyKey() { - return {{}, llvm::DenseMapInfo::getEmptyKey()}; - } - static ModuleDecl::ImportedModule getTombstoneKey() { - return {{}, llvm::DenseMapInfo::getTombstoneKey()}; - } - - static unsigned getHashValue(const ModuleDecl::ImportedModule &val) { - auto pair = std::make_pair(val.accessPath.size(), val.importedModule); - return llvm::DenseMapInfo::getHashValue(pair); - } - - static bool isEqual(const ModuleDecl::ImportedModule &lhs, - const ModuleDecl::ImportedModule &rhs) { - return lhs.importedModule == rhs.importedModule && - lhs.accessPath.isSameAs(rhs.accessPath); - } - }; -} - #endif diff --git a/include/swift/AST/SourceFile.h b/include/swift/AST/SourceFile.h index 2939ffd079cd7..f92ebbae10a42 100644 --- a/include/swift/AST/SourceFile.h +++ b/include/swift/AST/SourceFile.h @@ -14,6 +14,7 @@ #define SWIFT_AST_SOURCEFILE_H #include "swift/AST/FileUnit.h" +#include "swift/AST/Import.h" #include "swift/AST/SynthesizedFileUnit.h" #include "swift/Basic/Debug.h" #include "llvm/ADT/SetVector.h" @@ -32,58 +33,6 @@ class SourceFile final : public FileUnit { friend class ParseSourceFileRequest; public: - /// Possible attributes for imports in source files. - enum class ImportFlags { - /// The imported module is exposed to anyone who imports the parent module. - Exported = 0x1, - - /// This source file has access to testable declarations in the imported - /// module. - Testable = 0x2, - - /// This source file has access to private declarations in the imported - /// module. - PrivateImport = 0x4, - - /// The imported module is an implementation detail of this file and should - /// not be required to be present if the main module is ever imported - /// elsewhere. - /// - /// Mutually exclusive with Exported. - ImplementationOnly = 0x8, - - // The module is imported to have access to named SPIs which is an - // implementation detail of this file. - SPIAccessControl = 0x10, - - /// Used for DenseMap. - Reserved = 0x80 - }; - - /// \see ImportFlags - using ImportOptions = OptionSet; - - struct ImportedModuleDesc { - ModuleDecl::ImportedModule module; - ImportOptions importOptions; - - // Filename for a @_private import. - StringRef filename; - - // Names of explicitly imported SPIs. - ArrayRef spiGroups; - - ImportedModuleDesc(ModuleDecl::ImportedModule module, ImportOptions options, - StringRef filename = {}, - ArrayRef spiGroups = {}) - : module(module), importOptions(options), filename(filename), - spiGroups(spiGroups) { - assert(!(importOptions.contains(ImportFlags::Exported) && - importOptions.contains(ImportFlags::ImplementationOnly)) || - importOptions.contains(ImportFlags::Reserved)); - } - }; - /// Flags that direct how the source file is parsed. enum class ParsingFlags : uint8_t { /// Whether to disable delayed parsing for nominal type, extension, and @@ -447,7 +396,7 @@ class SourceFile final : public FileUnit { getOpaqueReturnTypeDecls(SmallVectorImpl &results) const override; virtual void - getImportedModules(SmallVectorImpl &imports, + getImportedModules(SmallVectorImpl &imports, ModuleDecl::ImportFilter filter) const override; virtual void @@ -660,60 +609,4 @@ inline void simple_display(llvm::raw_ostream &out, const SourceFile *SF) { } } // end namespace swift -namespace llvm { - -template<> -struct DenseMapInfo { - using ImportOptions = swift::SourceFile::ImportOptions; - - using UnsignedDMI = DenseMapInfo; - - static inline ImportOptions getEmptyKey() { - return ImportOptions(UnsignedDMI::getEmptyKey()); - } - static inline ImportOptions getTombstoneKey() { - return ImportOptions(UnsignedDMI::getTombstoneKey()); - } - static inline unsigned getHashValue(ImportOptions options) { - return UnsignedDMI::getHashValue(options.toRaw()); - } - static bool isEqual(ImportOptions a, ImportOptions b) { - return UnsignedDMI::isEqual(a.toRaw(), b.toRaw()); - } -}; - -template<> -struct DenseMapInfo { - using ImportedModuleDesc = swift::SourceFile::ImportedModuleDesc; - - using ImportedModuleDMI = DenseMapInfo; - using ImportOptionsDMI = DenseMapInfo; - using StringRefDMI = DenseMapInfo; - - static inline ImportedModuleDesc getEmptyKey() { - return ImportedModuleDesc(ImportedModuleDMI::getEmptyKey(), - ImportOptionsDMI::getEmptyKey(), - StringRefDMI::getEmptyKey()); - } - static inline ImportedModuleDesc getTombstoneKey() { - return ImportedModuleDesc(ImportedModuleDMI::getTombstoneKey(), - ImportOptionsDMI::getTombstoneKey(), - StringRefDMI::getTombstoneKey()); - } - static inline unsigned getHashValue(const ImportedModuleDesc &import) { - return detail::combineHashValue( - ImportedModuleDMI::getHashValue(import.module), - detail::combineHashValue( - ImportOptionsDMI::getHashValue(import.importOptions), - StringRefDMI::getHashValue(import.filename))); - } - static bool isEqual(const ImportedModuleDesc &a, - const ImportedModuleDesc &b) { - return ImportedModuleDMI::isEqual(a.module, b.module) && - ImportOptionsDMI::isEqual(a.importOptions, b.importOptions) && - StringRefDMI::isEqual(a.filename, b.filename); - } -}; -} - #endif diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 9546b7dfab229..4d2b1a8acc57d 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -2494,25 +2494,6 @@ class SimpleDidSetRequest } }; -/// A module which has been implicitly imported. -struct ImplicitImport { - using ImportOptions = SourceFile::ImportOptions; - - ModuleDecl *Module; - ImportOptions Options; - - ImplicitImport(ModuleDecl *module, ImportOptions opts = {}) - : Module(module), Options(opts) {} - - friend bool operator==(const ImplicitImport &lhs, - const ImplicitImport &rhs) { - return lhs.Module == rhs.Module && - lhs.Options.toRaw() == rhs.Options.toRaw(); - } -}; - -void simple_display(llvm::raw_ostream &out, const ImplicitImport &import); - /// Computes the loaded modules that should be implicitly imported by each file /// of a given module. class ModuleImplicitImportsRequest diff --git a/include/swift/ClangImporter/ClangModule.h b/include/swift/ClangImporter/ClangModule.h index c79fb8c04ece4..6541f1fcacdce 100644 --- a/include/swift/ClangImporter/ClangModule.h +++ b/include/swift/ClangImporter/ClangModule.h @@ -36,7 +36,7 @@ class ClangModuleUnit final : public LoadedFile { ClangImporter::Implementation &owner; const clang::Module *clangModule; llvm::PointerIntPair overlayModule; - mutable Optional> importedModulesForLookup; + mutable Optional> importedModulesForLookup; /// The metadata of the underlying Clang module. clang::ASTSourceDescriptor ASTSourceDescriptor; @@ -92,11 +92,11 @@ class ClangModuleUnit final : public LoadedFile { virtual void getDisplayDecls(SmallVectorImpl &results) const override; virtual void - getImportedModules(SmallVectorImpl &imports, + getImportedModules(SmallVectorImpl &imports, ModuleDecl::ImportFilter filter) const override; virtual void getImportedModulesForLookup( - SmallVectorImpl &imports) const override; + SmallVectorImpl &imports) const override; virtual void collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const override; diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h index e0aa714fd3914..59e813857f324 100644 --- a/include/swift/Serialization/SerializedModuleLoader.h +++ b/include/swift/Serialization/SerializedModuleLoader.h @@ -414,7 +414,7 @@ class SerializedASTFile final : public LoadedFile { virtual void getDisplayDecls(SmallVectorImpl &results) const override; virtual void - getImportedModules(SmallVectorImpl &imports, + getImportedModules(SmallVectorImpl &imports, ModuleDecl::ImportFilter filter) const override; virtual void diff --git a/lib/AST/ImportCache.cpp b/lib/AST/ImportCache.cpp index a9a893934b824..af6e922ba0773 100644 --- a/lib/AST/ImportCache.cpp +++ b/lib/AST/ImportCache.cpp @@ -26,19 +26,19 @@ using namespace swift; using namespace namelookup; ImportSet::ImportSet(bool hasHeaderImportModule, - ArrayRef topLevelImports, - ArrayRef transitiveImports) + ArrayRef topLevelImports, + ArrayRef transitiveImports) : HasHeaderImportModule(hasHeaderImportModule), NumTopLevelImports(topLevelImports.size()), NumTransitiveImports(transitiveImports.size()) { - auto buffer = getTrailingObjects(); + auto buffer = getTrailingObjects(); std::uninitialized_copy(topLevelImports.begin(), topLevelImports.end(), buffer); std::uninitialized_copy(transitiveImports.begin(), transitiveImports.end(), buffer + topLevelImports.size()); #ifndef NDEBUG - llvm::SmallDenseSet unique; + llvm::SmallDenseSet unique; for (auto import : topLevelImports) { auto result = unique.insert(import).second; assert(result && "Duplicate imports in import set"); @@ -52,7 +52,7 @@ ImportSet::ImportSet(bool hasHeaderImportModule, void ImportSet::Profile( llvm::FoldingSetNodeID &ID, - ArrayRef topLevelImports) { + ArrayRef topLevelImports) { ID.AddInteger(topLevelImports.size()); for (auto import : topLevelImports) { ID.AddInteger(import.accessPath.size()); @@ -63,9 +63,9 @@ void ImportSet::Profile( } } -static void collectExports(ModuleDecl::ImportedModule next, - SmallVectorImpl &stack) { - SmallVector exports; +static void collectExports(ImportedModule next, + SmallVectorImpl &stack) { + SmallVector exports; next.importedModule->getImportedModulesForLookup(exports); for (auto exported : exports) { if (next.accessPath.empty()) @@ -81,16 +81,16 @@ static void collectExports(ModuleDecl::ImportedModule next, ImportSet & ImportCache::getImportSet(ASTContext &ctx, - ArrayRef imports) { + ArrayRef imports) { bool hasHeaderImportModule = false; ModuleDecl *headerImportModule = nullptr; if (auto *loader = ctx.getClangModuleLoader()) headerImportModule = loader->getImportedHeaderModule(); - SmallVector topLevelImports; + SmallVector topLevelImports; - SmallVector transitiveImports; - llvm::SmallDenseSet visited; + SmallVector transitiveImports; + llvm::SmallDenseSet visited; for (auto next : imports) { if (!visited.insert(next).second) @@ -115,7 +115,7 @@ ImportCache::getImportSet(ASTContext &ctx, if (ctx.Stats) ++ctx.Stats->getFrontendCounters().ImportSetFoldMiss; - SmallVector stack; + SmallVector stack; for (auto next : topLevelImports) { collectExports(next, stack); } @@ -139,7 +139,7 @@ ImportCache::getImportSet(ASTContext &ctx, if (ImportSet *result = ImportSets.FindNodeOrInsertPos(ID, InsertPos)) return *result; - size_t bytes = ImportSet::totalSizeToAlloc(topLevelImports.size() + transitiveImports.size()); + size_t bytes = ImportSet::totalSizeToAlloc(topLevelImports.size() + transitiveImports.size()); void *mem = ctx.Allocate(bytes, alignof(ImportSet), AllocationArena::Permanent); auto *result = new (mem) ImportSet(hasHeaderImportModule, @@ -169,10 +169,9 @@ ImportSet &ImportCache::getImportSet(const DeclContext *dc) { if (ctx.Stats) ++ctx.Stats->getFrontendCounters().ImportSetCacheMiss; - SmallVector imports; + SmallVector imports; - imports.emplace_back( - ModuleDecl::ImportedModule{ImportPath::Access(), mod}); + imports.emplace_back(ImportPath::Access(), mod); if (file) { // Should include both SPI & non-SPI. @@ -254,11 +253,10 @@ ImportCache::getAllAccessPathsNotShadowedBy(const ModuleDecl *mod, if (ctx.Stats) ++ctx.Stats->getFrontendCounters().ModuleShadowCacheMiss; - SmallVector stack; - llvm::SmallDenseSet visited; + SmallVector stack; + llvm::SmallDenseSet visited; - stack.emplace_back( - ModuleDecl::ImportedModule{ImportPath::Access(), currentMod}); + stack.emplace_back(ImportPath::Access(), currentMod); if (auto *file = dyn_cast(dc)) { // Should include both SPI & non-SPI @@ -297,7 +295,7 @@ ImportCache::getAllAccessPathsNotShadowedBy(const ModuleDecl *mod, return result; }; -ArrayRef +ArrayRef swift::namelookup::getAllImports(const DeclContext *dc) { return dc->getASTContext().getImportCache().getImportSet(dc) .getAllImports(); diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 135efbd415b97..ac0c4bcf9d868 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -1175,7 +1175,7 @@ void ModuleDecl::getImportedModules(SmallVectorImpl &modules, } void -SourceFile::getImportedModules(SmallVectorImpl &modules, +SourceFile::getImportedModules(SmallVectorImpl &modules, ModuleDecl::ImportFilter filter) const { // FIXME: Ideally we should assert that the file has had its imports resolved // before calling this function. However unfortunately that can cause issues @@ -1281,7 +1281,7 @@ ModuleDecl::ReverseFullNameIterator::printForward(raw_ostream &out, } void -ModuleDecl::removeDuplicateImports(SmallVectorImpl &imports) { +ImportedModule::removeDuplicates(SmallVectorImpl &imports) { std::sort(imports.begin(), imports.end(), [](const ImportedModule &lhs, const ImportedModule &rhs) -> bool { // Arbitrarily sort by name to get a deterministic order. @@ -1451,7 +1451,7 @@ void ModuleDecl::collectLinkLibraries(LinkLibraryCallback callback) const { void SourceFile::collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const { llvm::SmallDenseSet visited; - SmallVector stack; + SmallVector stack; ModuleDecl::ImportFilter filter = { ModuleDecl::ImportFilterKind::Exported, @@ -1465,9 +1465,7 @@ SourceFile::collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const topLevel->getImportedModules(stack, topLevelFilter); // Make sure the top-level module is first; we want pre-order-ish traversal. - auto topLevelModule = - ModuleDecl::ImportedModule{ImportPath::Access(), topLevel}; - stack.emplace_back(topLevelModule); + stack.emplace_back(ImportPath::Access(), topLevel); while (!stack.empty()) { auto next = stack.pop_back_val().importedModule; @@ -1685,8 +1683,8 @@ ModuleDecl::getDeclaringModuleAndBystander() { // Search the transitive set of imported @_exported modules to see if any have // this module as their overlay. SmallPtrSet seen; - SmallVector imported; - SmallVector furtherImported; + SmallVector imported; + SmallVector furtherImported; ModuleDecl *overlayModule = this; getImportedModules(imported, ModuleDecl::ImportFilterKind::Exported); @@ -1891,10 +1889,8 @@ void SourceFile::setImports(ArrayRef imports) { bool HasImplementationOnlyImportsRequest::evaluate(Evaluator &evaluator, SourceFile *SF) const { - using ModuleDesc = SourceFile::ImportedModuleDesc; - return llvm::any_of(SF->getImports(), [](ModuleDesc desc) { - return desc.importOptions.contains( - SourceFile::ImportFlags::ImplementationOnly); + return llvm::any_of(SF->getImports(), [](ImportedModuleDesc desc) { + return desc.importOptions.contains(ImportFlags::ImplementationOnly); }); } @@ -2001,7 +1997,7 @@ bool ModuleDecl::isImportedImplementationOnly(const ModuleDecl *module) const { ModuleDecl::ImportFilterKind::Default, ModuleDecl::ImportFilterKind::SPIAccessControl, ModuleDecl::ImportFilterKind::ShadowedByCrossImportOverlay}; - SmallVector results; + SmallVector results; getImportedModules(results, filter); for (auto &desc : results) { diff --git a/lib/AST/ModuleNameLookup.cpp b/lib/AST/ModuleNameLookup.cpp index af29ee62144e3..56ea9383c6d29 100644 --- a/lib/AST/ModuleNameLookup.cpp +++ b/lib/AST/ModuleNameLookup.cpp @@ -182,7 +182,7 @@ void ModuleNameLookup::lookupInModule( if (!canReturnEarly) { auto &imports = ctx.getImportCache().getImportSet(moduleOrFile); - auto visitImport = [&](ModuleDecl::ImportedModule import, + auto visitImport = [&](ImportedModule import, const DeclContext *moduleScopeContext) { if (import.accessPath.empty()) import.accessPath = accessPath; @@ -202,8 +202,7 @@ void ModuleNameLookup::lookupInModule( if (auto *loader = ctx.getClangModuleLoader()) { headerImportModule = loader->getImportedHeaderModule(); if (headerImportModule) { - ModuleDecl::ImportedModule import{ImportPath::Access(), - headerImportModule}; + ImportedModule import{ImportPath::Access(), headerImportModule}; visitImport(import, nullptr); } } diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index c448198233fec..17cf849302574 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -290,8 +290,7 @@ static void recordShadowedDeclsAfterTypeMatch( auto file = dc->getParentSourceFile(); if (!file) return false; for (const auto &import : file->getImports()) { - if (import.importOptions.contains( - SourceFile::ImportFlags::PrivateImport) + if (import.importOptions.contains(ImportFlags::PrivateImport) && import.module.importedModule == module && import.module.accessPath.matches(name)) return true; diff --git a/lib/AST/OperatorNameLookup.cpp b/lib/AST/OperatorNameLookup.cpp index b074fbf30f630..e05e3347de08b 100644 --- a/lib/AST/OperatorNameLookup.cpp +++ b/lib/AST/OperatorNameLookup.cpp @@ -83,8 +83,7 @@ static TinyPtrVector lookupOperatorImpl( if (!visitedModules.insert(mod).second) continue; - bool isExported = - import.importOptions.contains(SourceFile::ImportFlags::Exported); + bool isExported = import.importOptions.contains(ImportFlags::Exported); if (!includePrivate && !isExported) continue; diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 0720569da9558..37ad1a8ce665e 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -3434,7 +3434,7 @@ ModuleDecl *ClangModuleUnit::getOverlayModule() const { } void ClangModuleUnit::getImportedModules( - SmallVectorImpl &imports, + SmallVectorImpl &imports, ModuleDecl::ImportFilter filter) const { // Bail out if we /only/ want ImplementationOnly imports; Clang modules never // have any of these. @@ -3505,7 +3505,7 @@ void ClangModuleUnit::getImportedModules( } void ClangModuleUnit::getImportedModulesForLookup( - SmallVectorImpl &imports) const { + SmallVectorImpl &imports) const { // Reuse our cached list of imports if we have one. if (importedModulesForLookup.hasValue()) { @@ -3530,7 +3530,7 @@ void ClangModuleUnit::getImportedModulesForLookup( } if (imported.empty()) { - importedModulesForLookup = ArrayRef(); + importedModulesForLookup = ArrayRef(); return; } diff --git a/lib/ClangImporter/DWARFImporter.cpp b/lib/ClangImporter/DWARFImporter.cpp index 79bb6eeea19e4..8b635d1ce5ed6 100644 --- a/lib/ClangImporter/DWARFImporter.cpp +++ b/lib/ClangImporter/DWARFImporter.cpp @@ -67,11 +67,11 @@ class DWARFModuleUnit final : public LoadedFile { getDisplayDecls(SmallVectorImpl &results) const override {} virtual void - getImportedModules(SmallVectorImpl &imports, + getImportedModules(SmallVectorImpl &imports, ModuleDecl::ImportFilter filter) const override {} virtual void getImportedModulesForLookup( - SmallVectorImpl &imports) const override {}; + SmallVectorImpl &imports) const override {}; virtual void collectLinkLibraries( ModuleDecl::LinkLibraryCallback callback) const override {}; diff --git a/lib/Frontend/ModuleInterfaceSupport.cpp b/lib/Frontend/ModuleInterfaceSupport.cpp index 52eb640375d99..4c442fd32feec 100644 --- a/lib/Frontend/ModuleInterfaceSupport.cpp +++ b/lib/Frontend/ModuleInterfaceSupport.cpp @@ -46,8 +46,8 @@ version::Version swift::InterfaceFormatVersion({1, 0}); /// /// These come from declarations like `import class FooKit.MainFooController`. static void diagnoseScopedImports(DiagnosticEngine &diags, - ArrayRef imports){ - for (const ModuleDecl::ImportedModule &importPair : imports) { + ArrayRef imports){ + for (const ImportedModule &importPair : imports) { if (importPair.accessPath.empty()) continue; diags.diagnose(importPair.accessPath.front().Loc, @@ -109,29 +109,27 @@ static void printImports(raw_ostream &out, // When printing the private swiftinterface file, print implementation-only // imports only if they are also SPI. First, list all implementation-only // imports and filter them later. - llvm::SmallSet ioiImportSet; + llvm::SmallSet ioiImportSet; if (Opts.PrintSPIs && Opts.ExperimentalSPIImports) { allImportFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly; - SmallVector ioiImport; + SmallVector ioiImport; M->getImportedModules(ioiImport, {ModuleDecl::ImportFilterKind::ImplementationOnly, ModuleDecl::ImportFilterKind::SPIAccessControl}); ioiImportSet.insert(ioiImport.begin(), ioiImport.end()); } - SmallVector allImports; + SmallVector allImports; M->getImportedModules(allImports, allImportFilter); - ModuleDecl::removeDuplicateImports(allImports); + ImportedModule::removeDuplicates(allImports); diagnoseScopedImports(M->getASTContext().Diags, allImports); // Collect the public imports as a subset so that we can mark them with // '@_exported'. - SmallVector publicImports; + SmallVector publicImports; M->getImportedModules(publicImports, ModuleDecl::ImportFilterKind::Exported); - llvm::SmallSet publicImportSet; + llvm::SmallSet publicImportSet; publicImportSet.insert(publicImports.begin(), publicImports.end()); diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 39231330e0c30..65ed97bc973aa 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -318,10 +318,10 @@ static void getImmediateImports( ModuleDecl::ImportFilterKind::SPIAccessControl, ModuleDecl::ImportFilterKind::ShadowedByCrossImportOverlay }) { - SmallVector importList; + SmallVector importList; module->getImportedModules(importList, importFilter); - for (ModuleDecl::ImportedModule &import : importList) + for (ImportedModule &import : importList) imports.insert(import.importedModule); } diff --git a/lib/FrontendTool/ImportedModules.cpp b/lib/FrontendTool/ImportedModules.cpp index 4ced1a7c5c8aa..857efcda8f98b 100644 --- a/lib/FrontendTool/ImportedModules.cpp +++ b/lib/FrontendTool/ImportedModules.cpp @@ -78,7 +78,7 @@ bool swift::emitImportedModules(ModuleDecl *mainModule, StringRef implicitHeaderPath = opts.ImplicitObjCHeaderPath; if (!implicitHeaderPath.empty()) { if (!clangImporter->importBridgingHeader(implicitHeaderPath, mainModule)) { - SmallVector imported; + SmallVector imported; clangImporter->getImportedHeaderModule()->getImportedModules( imported, {ModuleDecl::ImportFilterKind::Exported, ModuleDecl::ImportFilterKind::Default, diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index 4fc0b5b149841..8079cd00c93d9 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -2036,8 +2036,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { } void collectImportedModules(llvm::StringSet<> &ImportedModules) { - SmallVector Imported; - SmallVector FurtherImported; + SmallVector Imported; + SmallVector FurtherImported; CurrDeclContext->getParentSourceFile()->getImportedModules( Imported, {ModuleDecl::ImportFilterKind::Exported, @@ -5923,7 +5923,7 @@ static void deliverCompletionResults(CodeCompletionContext &CompletionContext, for (auto &Request: Lookup.RequestedCachedResults) { llvm::DenseSet ImportsSeen; - auto handleImport = [&](ModuleDecl::ImportedModule Import) { + auto handleImport = [&](ImportedModule Import) { ModuleDecl *TheModule = Import.importedModule; ImportPath::Access Path = Import.accessPath; if (TheModule->getFiles().empty()) @@ -5991,7 +5991,7 @@ static void deliverCompletionResults(CodeCompletionContext &CompletionContext, Lookup.addModuleName(curModule); // Add results for all imported modules. - SmallVector Imports; + SmallVector Imports; SF.getImportedModules( Imports, {ModuleDecl::ImportFilterKind::Exported, ModuleDecl::ImportFilterKind::Default, diff --git a/lib/IDE/REPLCodeCompletion.cpp b/lib/IDE/REPLCodeCompletion.cpp index caf7aef65bf70..1c7ffa17883b6 100644 --- a/lib/IDE/REPLCodeCompletion.cpp +++ b/lib/IDE/REPLCodeCompletion.cpp @@ -225,7 +225,7 @@ doCodeCompletion(SourceFile &SF, StringRef EnteredCode, unsigned *BufferID, /*exported*/ false); // Carry over the private imports from the last module. - SmallVector imports; + SmallVector imports; lastModule->getImportedModules(imports, ModuleDecl::ImportFilterKind::Default); for (auto &import : imports) { diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 5d91564f12c26..d462676af3db3 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -661,7 +661,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { } void createImportedModule(llvm::DIScope *Context, - ModuleDecl::ImportedModule M, llvm::DIFile *File, + ImportedModule M, llvm::DIFile *File, unsigned Line) { // For overlays of Clang modules also emit an import of the underlying Clang // module. The helps the debugger resolve types that are present only in the @@ -761,7 +761,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { return None; } - llvm::DIModule *getOrCreateModule(ModuleDecl::ImportedModule IM) { + llvm::DIModule *getOrCreateModule(ImportedModule IM) { ModuleDecl *M = IM.importedModule; if (Optional ModuleDesc = getClangModule(*M)) return getOrCreateModule(*ModuleDesc, ModuleDesc->getModuleOrNull()); @@ -1882,7 +1882,7 @@ void IRGenDebugInfoImpl::finalize() { // Get the list of imported modules (which may actually be different // from all ImportDecls). - SmallVector ModuleWideImports; + SmallVector ModuleWideImports; IGM.getSwiftModule()->getImportedModules( ModuleWideImports, {ModuleDecl::ImportFilterKind::Exported, ModuleDecl::ImportFilterKind::Default, @@ -2129,7 +2129,7 @@ void IRGenDebugInfoImpl::emitImport(ImportDecl *D) { return; assert(D->getModule() && "compiler-synthesized ImportDecl is incomplete"); - ModuleDecl::ImportedModule Imported = { D->getAccessPath(), D->getModule() }; + ImportedModule Imported = { D->getAccessPath(), D->getModule() }; auto L = getDebugLoc(*this, D); auto *File = getOrCreateFile(L.Filename); createImportedModule(File, Imported, File, L.Line); diff --git a/lib/Index/Index.cpp b/lib/Index/Index.cpp index f26580b5d3324..e8e6fab61ddc9 100644 --- a/lib/Index/Index.cpp +++ b/lib/Index/Index.cpp @@ -124,7 +124,7 @@ class SourceFileOrModule { } void - getImportedModules(SmallVectorImpl &Modules) const { + getImportedModules(SmallVectorImpl &Modules) const { constexpr ModuleDecl::ImportFilter ImportFilter = { ModuleDecl::ImportFilterKind::Exported, ModuleDecl::ImportFilterKind::Default, @@ -715,7 +715,7 @@ bool IndexSwiftASTWalker::visitImports( if (!IsNew) return true; - SmallVector Imports; + SmallVector Imports; TopMod.getImportedModules(Imports); llvm::SmallPtrSet Reported; @@ -1602,7 +1602,7 @@ void IndexSwiftASTWalker::collectRecursiveModuleImports( ImportFilter |= ModuleDecl::ImportFilterKind::Exported; ImportFilter |= ModuleDecl::ImportFilterKind::Default; // FIXME: ImportFilterKind::ShadowedByCrossImportOverlay? - SmallVector Imports; + SmallVector Imports; TopMod.getImportedModules(Imports); for (auto Import : Imports) { diff --git a/lib/Index/IndexRecord.cpp b/lib/Index/IndexRecord.cpp index 9beed7ea04ca0..4d0706ff6fa6e 100644 --- a/lib/Index/IndexRecord.cpp +++ b/lib/Index/IndexRecord.cpp @@ -383,7 +383,7 @@ emitDataForSwiftSerializedModule(ModuleDecl *module, IndexUnitWriter &parentUnitWriter, SourceFile *initialFile); -static void addModuleDependencies(ArrayRef imports, +static void addModuleDependencies(ArrayRef imports, StringRef indexStorePath, bool indexSystemModules, bool skipStdlib, @@ -580,7 +580,7 @@ emitDataForSwiftSerializedModule(ModuleDecl *module, unitWriter.addRecordFile(recordFile, *FE, isSystemModule, mod); } - SmallVector imports; + SmallVector imports; module->getImportedModules(imports, {ModuleDecl::ImportFilterKind::Exported, ModuleDecl::ImportFilterKind::Default}); StringScratchSpace moduleNameScratch; @@ -619,7 +619,7 @@ recordSourceFileUnit(SourceFile *primarySourceFile, StringRef indexUnitToken, getModuleInfoFromOpaqueModule); // Module dependencies. - SmallVector imports; + SmallVector imports; primarySourceFile->getImportedModules( imports, {ModuleDecl::ImportFilterKind::Exported, ModuleDecl::ImportFilterKind::Default, diff --git a/lib/Sema/ImportResolution.cpp b/lib/Sema/ImportResolution.cpp index 9b2a4362eaa3f..8583c03d3ea25 100644 --- a/lib/Sema/ImportResolution.cpp +++ b/lib/Sema/ImportResolution.cpp @@ -43,11 +43,6 @@ using namespace swift; // MARK: ImportResolver and supporting types //===----------------------------------------------------------------------===// -using ImportedModule = ModuleDecl::ImportedModule; -using ImportedModuleDesc = SourceFile::ImportedModuleDesc; -using ImportOptions = SourceFile::ImportOptions; -using ImportFlags = SourceFile::ImportFlags; - namespace { /// Represents an import which the ImportResolver knows exists, but which has /// not yet had its options checked, module loaded, or cross-imports found. @@ -520,7 +515,7 @@ UnboundImport::UnboundImport(ImportDecl *ID) SmallVector spiGroups; for (auto attr : ID->getAttrs().getAttributes()) { - options |= SourceFile::ImportFlags::SPIAccessControl; + options |= ImportFlags::SPIAccessControl; auto attrSPIs = attr->getSPIGroups(); spiGroups.append(attrSPIs.begin(), attrSPIs.end()); } diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index 5bd056555121f..31e559be687bf 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -167,8 +167,8 @@ Status ModuleFile::associateWithFileContext(FileUnit *file, SourceLoc diagLoc) { return error(Status::FailedToLoadBridgingHeader); } ModuleDecl *importedHeaderModule = clangImporter->getImportedHeaderModule(); - dependency.Import = ModuleDecl::ImportedModule{ImportPath::Access(), - importedHeaderModule}; + dependency.Import = ImportedModule{ImportPath::Access(), + importedHeaderModule}; continue; } @@ -212,7 +212,7 @@ Status ModuleFile::associateWithFileContext(FileUnit *file, SourceLoc diagLoc) { continue; } - dependency.Import = ModuleDecl::ImportedModule{accessPath, module}; + dependency.Import = ImportedModule{accessPath, module}; // SPI StringRef spisStr = dependency.Core.RawSPIs; @@ -420,9 +420,8 @@ PrecedenceGroupDecl *ModuleFile::lookupPrecedenceGroup(Identifier name) { return cast(getDecl(data[0].second)); } -void ModuleFile::getImportedModules( - SmallVectorImpl &results, - ModuleDecl::ImportFilter filter) { +void ModuleFile::getImportedModules(SmallVectorImpl &results, + ModuleDecl::ImportFilter filter) { PrettyStackTraceModuleFile stackEntry(*this); for (auto &dep : Dependencies) { diff --git a/lib/Serialization/ModuleFile.h b/lib/Serialization/ModuleFile.h index 7749f82adee91..dfa5594eaf46f 100644 --- a/lib/Serialization/ModuleFile.h +++ b/lib/Serialization/ModuleFile.h @@ -90,7 +90,7 @@ class ModuleFile public: const ModuleFileSharedCore::Dependency &Core; - llvm::Optional Import = llvm::None; + llvm::Optional Import = llvm::None; SmallVector spiGroups; Dependency(const ModuleFileSharedCore::Dependency &coreDependency) @@ -527,7 +527,7 @@ class ModuleFile PrecedenceGroupDecl *lookupPrecedenceGroup(Identifier name); /// Adds any imported modules to the given vector. - void getImportedModules(SmallVectorImpl &results, + void getImportedModules(SmallVectorImpl &results, ModuleDecl::ImportFilter filter); void getImportDecls(SmallVectorImpl &Results); diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index ad6e002234df8..f5f2830ae446a 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -953,7 +953,7 @@ void Serializer::writeHeader(const SerializationOptions &options) { } } -static void flattenImportPath(const ModuleDecl::ImportedModule &import, +static void flattenImportPath(const ImportedModule &import, SmallVectorImpl &out) { llvm::raw_svector_ostream outStream(out); import.importedModule->getReverseFullModuleName().printForward( @@ -974,11 +974,10 @@ uint64_t getRawModTimeOrHash(const SerializationOptions::FileDependency &dep) { return dep.getModificationTime(); } -using ImportSet = llvm::SmallSet; +using ImportSet = llvm::SmallSet; static ImportSet getImportsAsSet(const ModuleDecl *M, ModuleDecl::ImportFilter filter) { - SmallVector imports; + SmallVector imports; M->getImportedModules(imports, filter); ImportSet importSet; importSet.insert(imports.begin(), imports.end()); @@ -987,7 +986,7 @@ static ImportSet getImportsAsSet(const ModuleDecl *M, void Serializer::writeInputBlock(const SerializationOptions &options) { BCBlockRAII restoreBlock(Out, INPUT_BLOCK_ID, 4); - input_block::ImportedModuleLayout ImportedModule(Out); + input_block::ImportedModuleLayout importedModule(Out); input_block::ImportedModuleLayoutSPI ImportedModuleSPI(Out); input_block::LinkLibraryLayout LinkLibrary(Out); input_block::ImportedHeaderLayout ImportedHeader(Out); @@ -1031,13 +1030,13 @@ void Serializer::writeInputBlock(const SerializationOptions &options) { if (!options.ModuleInterface.empty()) ModuleInterface.emit(ScratchRecord, options.ModuleInterface); - SmallVector allImports; + SmallVector allImports; M->getImportedModules(allImports, {ModuleDecl::ImportFilterKind::Exported, ModuleDecl::ImportFilterKind::Default, ModuleDecl::ImportFilterKind::ImplementationOnly, ModuleDecl::ImportFilterKind::SPIAccessControl}); - ModuleDecl::removeDuplicateImports(allImports); + ImportedModule::removeDuplicates(allImports); // Collect the public and private imports as a subset so that we can // distinguish them. @@ -1055,8 +1054,8 @@ void Serializer::writeInputBlock(const SerializationOptions &options) { auto clangImporter = static_cast(M->getASTContext().getClangModuleLoader()); ModuleDecl *bridgingHeaderModule = clangImporter->getImportedHeaderModule(); - ModuleDecl::ImportedModule bridgingHeaderImport{ImportPath::Access(), - bridgingHeaderModule}; + ImportedModule bridgingHeaderImport{ImportPath::Access(), + bridgingHeaderModule}; // Make sure the bridging header module is always at the top of the import // list, mimicking how it is processed before any module imports when @@ -1104,7 +1103,7 @@ void Serializer::writeInputBlock(const SerializationOptions &options) { llvm::SmallSetVector spis; M->lookupImportedSPIGroups(import.importedModule, spis); - ImportedModule.emit(ScratchRecord, + importedModule.emit(ScratchRecord, static_cast(stableImportControl), !import.accessPath.empty(), !spis.empty(), importPath); diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index c3ae09130cf70..30e5baaa778e2 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -1109,14 +1109,14 @@ void SerializedModuleLoaderBase::verifyAllModules() { //----------------------------------------------------------------------------- void SerializedASTFile::getImportedModules( - SmallVectorImpl &imports, + SmallVectorImpl &imports, ModuleDecl::ImportFilter filter) const { File.getImportedModules(imports, filter); } void SerializedASTFile::collectLinkLibrariesFromImports( ModuleDecl::LinkLibraryCallback callback) const { - llvm::SmallVector Imports; + llvm::SmallVector Imports; File.getImportedModules(Imports, {ModuleDecl::ImportFilterKind::Exported, ModuleDecl::ImportFilterKind::Default}); diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp index 13a1b571e34c3..731ba21165ffa 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp @@ -354,7 +354,7 @@ ImportDepth::ImportDepth(ASTContext &context, // Private imports from this module. // FIXME: only the private imports from the current source file. // FIXME: ImportFilterKind::ShadowedByCrossImportOverlay? - SmallVector mainImports; + SmallVector mainImports; main->getImportedModules(mainImports, {ModuleDecl::ImportFilterKind::Default, ModuleDecl::ImportFilterKind::ImplementationOnly}); @@ -384,7 +384,7 @@ ImportDepth::ImportDepth(ASTContext &context, } // Add imports to the worklist. - SmallVector imports; + SmallVector imports; module->getImportedModules(imports); for (auto &import : imports) { uint8_t next = std::max(depth, uint8_t(depth + 1)); // unsigned wrap diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp index e90b71447c525..2620dfb3be2bb 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp @@ -754,7 +754,7 @@ static void collectModuleDependencies(ModuleDecl *TopMod, ImportFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly; } // FIXME: ImportFilterKind::ShadowedByCrossImportOverlay? - SmallVector Imports; + SmallVector Imports; TopMod->getImportedModules(Imports, ImportFilter); for (auto Import : Imports) { diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index 2bc1c5206ab80..d0d874bbc2d17 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -3176,7 +3176,7 @@ static int doPrintModuleImports(const CompilerInvocation &InitInvok, continue; } - SmallVector scratch; + SmallVector scratch; for (auto next : namelookup::getAllImports(M)) { llvm::outs() << next.importedModule->getName(); if (next.importedModule->isNonSwiftModule()) From f3d99cefbb63960fdcd2b177b418d2a9a43930df Mon Sep 17 00:00:00 2001 From: Brent Royal-Gordon Date: Sat, 12 Sep 2020 17:09:30 -0700 Subject: [PATCH 02/13] [NFC] Turn ImportedModuleDesc into AttributedImport MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename ImportedModuleDesc to AttributedImport and make it a template that’s parameterized on the representation of the module. This will allow us to reduce duplicated representations of “abstract” ImportDecls. --- include/swift/AST/Import.h | 52 +++++++++++++++------------- include/swift/AST/SourceFile.h | 8 +++-- lib/AST/Module.cpp | 24 ++++++------- lib/Sema/ImportResolution.cpp | 62 ++++++++++++++++++---------------- 4 files changed, 78 insertions(+), 68 deletions(-) diff --git a/include/swift/AST/Import.h b/include/swift/AST/Import.h index 6bb179543213e..5482e714b10af 100644 --- a/include/swift/AST/Import.h +++ b/include/swift/AST/Import.h @@ -70,8 +70,8 @@ enum class ImportFlags { /// Mutually exclusive with Exported. ImplementationOnly = 0x8, - // The module is imported to have access to named SPIs which is an - // implementation detail of this file. + /// The module is imported to have access to named SPIs which is an + /// implementation detail of this file. SPIAccessControl = 0x10, /// Used for DenseMap. @@ -444,8 +444,10 @@ struct alignas(uint64_t) ImportedModule { }; }; -struct ImportedModuleDesc { - ImportedModule module; +template +struct AttributedImport { + ModuleInfo module; + ImportOptions importOptions; // Filename for a @_private import. @@ -454,9 +456,8 @@ struct ImportedModuleDesc { // Names of explicitly imported SPIs. ArrayRef spiGroups; - ImportedModuleDesc(ImportedModule module, ImportOptions options, - StringRef filename = {}, - ArrayRef spiGroups = {}) + AttributedImport(ModuleInfo module, ImportOptions options, + StringRef filename = {}, ArrayRef spiGroups = {}) : module(module), importOptions(options), filename(filename), spiGroups(spiGroups) { assert(!(importOptions.contains(ImportFlags::Exported) && @@ -465,6 +466,8 @@ struct ImportedModuleDesc { } }; +using ImportedModuleDesc = AttributedImport; + // MARK: - Implicit imports /// A module which has been implicitly imported. @@ -570,34 +573,35 @@ class DenseMapInfo { } }; -template<> -struct DenseMapInfo { - using ImportedModuleDesc = swift::ImportedModuleDesc; +template +struct DenseMapInfo> { + using AttributedImport = swift::AttributedImport; - using ImportedModuleDMI = DenseMapInfo; + using ModuleInfoDMI = DenseMapInfo; using ImportOptionsDMI = DenseMapInfo; using StringRefDMI = DenseMapInfo; + // FIXME: SPI groups not used by DenseMapInfo??? - static inline ImportedModuleDesc getEmptyKey() { - return ImportedModuleDesc(ImportedModuleDMI::getEmptyKey(), - ImportOptionsDMI::getEmptyKey(), - StringRefDMI::getEmptyKey()); + static inline AttributedImport getEmptyKey() { + return AttributedImport(ModuleInfoDMI::getEmptyKey(), + ImportOptionsDMI::getEmptyKey(), + StringRefDMI::getEmptyKey()); } - static inline ImportedModuleDesc getTombstoneKey() { - return ImportedModuleDesc(ImportedModuleDMI::getTombstoneKey(), - ImportOptionsDMI::getTombstoneKey(), - StringRefDMI::getTombstoneKey()); + static inline AttributedImport getTombstoneKey() { + return AttributedImport(ModuleInfoDMI::getTombstoneKey(), + ImportOptionsDMI::getTombstoneKey(), + StringRefDMI::getTombstoneKey()); } - static inline unsigned getHashValue(const ImportedModuleDesc &import) { + static inline unsigned getHashValue(const AttributedImport &import) { return detail::combineHashValue( - ImportedModuleDMI::getHashValue(import.module), + ModuleInfoDMI::getHashValue(import.module), detail::combineHashValue( ImportOptionsDMI::getHashValue(import.importOptions), StringRefDMI::getHashValue(import.filename))); } - static bool isEqual(const ImportedModuleDesc &a, - const ImportedModuleDesc &b) { - return ImportedModuleDMI::isEqual(a.module, b.module) && + static bool isEqual(const AttributedImport &a, + const AttributedImport &b) { + return ModuleInfoDMI::isEqual(a.module, b.module) && ImportOptionsDMI::isEqual(a.importOptions, b.importOptions) && StringRefDMI::isEqual(a.filename, b.filename); } diff --git a/include/swift/AST/SourceFile.h b/include/swift/AST/SourceFile.h index f92ebbae10a42..5679e5d5f76de 100644 --- a/include/swift/AST/SourceFile.h +++ b/include/swift/AST/SourceFile.h @@ -82,7 +82,7 @@ class SourceFile final : public FileUnit { /// This is the list of modules that are imported by this module. /// /// This is \c None until it is filled in by the import resolution phase. - Optional> Imports; + Optional>> Imports; /// A unique identifier representing this file; used to mark private decls /// within the file to keep them from conflicting with other files in the @@ -288,11 +288,13 @@ class SourceFile final : public FileUnit { ~SourceFile(); /// Retrieve an immutable view of the source file's imports. - ArrayRef getImports() const { return *Imports; } + ArrayRef> getImports() const { + return *Imports; + } /// Set the imports for this source file. This gets called by import /// resolution. - void setImports(ArrayRef imports); + void setImports(ArrayRef> imports); enum ImportQueryKind { /// Return the results for testable or private imports. diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index ac0c4bcf9d868..66fcd8bc4d466 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -1882,14 +1882,16 @@ void SourceFile::print(ASTPrinter &Printer, const PrintOptions &PO) { } } -void SourceFile::setImports(ArrayRef imports) { +void +SourceFile::setImports(ArrayRef> imports) { assert(!Imports && "Already computed imports"); Imports = getASTContext().AllocateCopy(imports); } bool HasImplementationOnlyImportsRequest::evaluate(Evaluator &evaluator, SourceFile *SF) const { - return llvm::any_of(SF->getImports(), [](ImportedModuleDesc desc) { + return llvm::any_of(SF->getImports(), + [](AttributedImport desc) { return desc.importOptions.contains(ImportFlags::ImplementationOnly); }); } @@ -1911,9 +1913,8 @@ bool SourceFile::hasTestableOrPrivateImport( // internal/public access only needs an import marked as @_private. The // filename does not need to match (and we don't serialize it for such // decls). - return std::any_of( - Imports->begin(), Imports->end(), - [module, queryKind](ImportedModuleDesc desc) -> bool { + return llvm::any_of(*Imports, + [module, queryKind](AttributedImport desc) -> bool { if (queryKind == ImportQueryKind::TestableAndPrivate) return desc.module.importedModule == module && (desc.importOptions.contains(ImportFlags::PrivateImport) || @@ -1954,13 +1955,12 @@ bool SourceFile::hasTestableOrPrivateImport( if (filename.empty()) return false; - return std::any_of(Imports->begin(), Imports->end(), - [module, filename](ImportedModuleDesc desc) -> bool { - return desc.module.importedModule == module && - desc.importOptions.contains( - ImportFlags::PrivateImport) && - desc.filename == filename; - }); + return llvm::any_of(*Imports, + [module, filename](AttributedImport desc) { + return desc.module.importedModule == module && + desc.importOptions.contains(ImportFlags::PrivateImport) && + desc.filename == filename; + }); } bool SourceFile::isImportedImplementationOnly(const ModuleDecl *module) const { diff --git a/lib/Sema/ImportResolution.cpp b/lib/Sema/ImportResolution.cpp index 8583c03d3ea25..c03b927af3953 100644 --- a/lib/Sema/ImportResolution.cpp +++ b/lib/Sema/ImportResolution.cpp @@ -102,8 +102,8 @@ struct UnboundImport { /// Create an UnboundImport for a cross-import overlay. explicit UnboundImport(ASTContext &ctx, const UnboundImport &base, Identifier overlayName, - const ImportedModuleDesc &declaringImport, - const ImportedModuleDesc &bystandingImport); + const AttributedImport &declaringImport, + const AttributedImport &bystandingImport); /// Diagnoses if the import would simply load the module \p SF already /// belongs to, with no actual effect. @@ -133,11 +133,12 @@ struct UnboundImport { /// non-implementation-only import of a fragile library from a resilient one. void validateOptions(NullablePtr topLevelModule, SourceFile &SF); - /// Create an \c ImportedModuleDesc from the information in this + /// Create an \c AttributedImport from the information in this /// UnboundImport. - ImportedModuleDesc makeDesc(ModuleDecl *module) const { - return ImportedModuleDesc({ accessPath, module }, options, - privateImportFileName, spiGroups); + AttributedImport + makeAttributedImport(ModuleDecl *module) const { + return AttributedImport({ accessPath, module }, options, + privateImportFileName, spiGroups); } private: @@ -165,7 +166,7 @@ class ImportResolver final : public DeclVisitor { SmallVector unboundImports; /// The list of fully bound imports. - SmallVector boundImports; + SmallVector, 16> boundImports; /// All imported modules which should be considered when cross-importing. /// This is basically the transitive import graph, but with only top-level @@ -174,14 +175,14 @@ class ImportResolver final : public DeclVisitor { /// We use a \c SmallSetVector here because this doubles as the worklist for /// cross-importing, so we want to keep it in order; this is feasible /// because this set is usually fairly small. - SmallSetVector crossImportableModules; + SmallSetVector, 64> crossImportableModules; /// The subset of \c crossImportableModules which may declare cross-imports. /// /// This is a performance optimization. Since most modules do not register /// any cross-imports, we can usually compare against this list, which is /// much, much smaller than \c crossImportableModules. - SmallVector crossImportDeclaringModules; + SmallVector, 16> crossImportDeclaringModules; /// The index of the next module in \c visibleModules that should be /// cross-imported. @@ -203,7 +204,7 @@ class ImportResolver final : public DeclVisitor { } /// Retrieve the finalized imports. - ArrayRef getFinishedImports() const { + ArrayRef> getFinishedImports() const { return boundImports; } @@ -228,7 +229,7 @@ class ImportResolver final : public DeclVisitor { /// Adds \p desc and everything it re-exports to \c visibleModules using /// the settings from \c desc. - void addCrossImportableModules(ImportedModuleDesc desc); + void addCrossImportableModules(AttributedImport desc); /// * If \p I is a cross-import overlay, registers \p M as overlaying /// \p I.underlyingModule in \c SF. @@ -239,18 +240,19 @@ class ImportResolver final : public DeclVisitor { /// Discovers any cross-imports between \p newImport and /// \p oldImports and adds them to \c unboundImports, using source /// locations from \p I. - void findCrossImportsInLists(UnboundImport &I, - ArrayRef declaring, - ArrayRef bystanding, - bool shouldDiagnoseRedundantCrossImports); + void findCrossImportsInLists( + UnboundImport &I, + ArrayRef> declaring, + ArrayRef> bystanding, + bool shouldDiagnoseRedundantCrossImports); /// Discovers any cross-imports between \p declaringImport and /// \p bystandingImport and adds them to \c unboundImports, using source /// locations from \p I. void findCrossImports(UnboundImport &I, - const ImportedModuleDesc &declaringImport, - const ImportedModuleDesc &bystandingImport, - bool shouldDiagnoseRedundantCrossImports); + const AttributedImport &declaringImport, + const AttributedImport &bystandingImport, + bool shouldDiagnoseRedundantCrossImports); /// Load a module referenced by an import statement. /// @@ -353,7 +355,7 @@ void ImportResolver::bindImport(UnboundImport &&I) { } void ImportResolver::addImport(const UnboundImport &I, ModuleDecl *M) { - auto importDesc = I.makeDesc(M); + auto importDesc = I.makeAttributedImport(M); addCrossImportableModules(importDesc); boundImports.push_back(importDesc); } @@ -912,7 +914,7 @@ ScopedImportLookupRequest::evaluate(Evaluator &evaluator, // MARK: Cross-import overlays //===----------------------------------------------------------------------===// -static bool canCrossImport(const ImportedModuleDesc &import) { +static bool canCrossImport(const AttributedImport &import) { if (import.importOptions.contains(ImportFlags::Testable)) return false; if (import.importOptions.contains(ImportFlags::PrivateImport)) @@ -922,10 +924,10 @@ static bool canCrossImport(const ImportedModuleDesc &import) { } /// Create an UnboundImport for a cross-import overlay. -UnboundImport::UnboundImport(ASTContext &ctx, const UnboundImport &base, - Identifier overlayName, - const ImportedModuleDesc &declaringImport, - const ImportedModuleDesc &bystandingImport) +UnboundImport::UnboundImport( + ASTContext &ctx, const UnboundImport &base, Identifier overlayName, + const AttributedImport &declaringImport, + const AttributedImport &bystandingImport) : importLoc(base.importLoc), options(), privateImportFileName(), // Cross-imports are not backed by an ImportDecl, so we need to provide // our own storage for their module paths. @@ -1032,8 +1034,8 @@ void ImportResolver::crossImport(ModuleDecl *M, UnboundImport &I) { } void ImportResolver::findCrossImportsInLists( - UnboundImport &I, ArrayRef declaring, - ArrayRef bystanding, + UnboundImport &I, ArrayRef> declaring, + ArrayRef> bystanding, bool shouldDiagnoseRedundantCrossImports) { for (auto &declaringImport : declaring) { if (!canCrossImport(declaringImport)) @@ -1050,8 +1052,9 @@ void ImportResolver::findCrossImportsInLists( } void ImportResolver::findCrossImports( - UnboundImport &I, const ImportedModuleDesc &declaringImport, - const ImportedModuleDesc &bystandingImport, + UnboundImport &I, + const AttributedImport &declaringImport, + const AttributedImport &bystandingImport, bool shouldDiagnoseRedundantCrossImports) { assert(&declaringImport != &bystandingImport); @@ -1120,7 +1123,8 @@ static bool isSubmodule(ModuleDecl* M) { return clangMod && clangMod->Parent; } -void ImportResolver::addCrossImportableModules(ImportedModuleDesc importDesc) { +void ImportResolver::addCrossImportableModules( + AttributedImport importDesc) { // FIXME: namelookup::getAllImports() doesn't quite do what we need (mainly // w.r.t. scoped imports), but it seems like we could extend it to do so, and // then eliminate most of this. From c489fffb796432c4c463b4cb11a2d88f23b8b508 Mon Sep 17 00:00:00 2001 From: Brent Royal-Gordon Date: Fri, 25 Sep 2020 15:04:53 -0700 Subject: [PATCH 03/13] [NFC] Rename and document fields of AttributedImport Also renames a member in ImportResolution.cpp to align with this naming. --- include/swift/AST/Import.h | 30 ++++++++++++++++++------------ lib/AST/Module.cpp | 24 ++++++++++++------------ lib/AST/NameLookup.cpp | 2 +- lib/AST/OperatorNameLookup.cpp | 2 +- lib/Sema/ImportResolution.cpp | 22 +++++++++++----------- 5 files changed, 43 insertions(+), 37 deletions(-) diff --git a/include/swift/AST/Import.h b/include/swift/AST/Import.h index 5482e714b10af..5ff068feb5bc5 100644 --- a/include/swift/AST/Import.h +++ b/include/swift/AST/Import.h @@ -444,25 +444,31 @@ struct alignas(uint64_t) ImportedModule { }; }; +/// Augments a type representing an import to also include information about the +/// import's attributes. This is usually used with either \c ImportedModule or +/// \c UnloadedImportedModule. template struct AttributedImport { + /// Information about the module and access path being imported. ModuleInfo module; - ImportOptions importOptions; + /// Flags indicating which attributes of this import are present. + ImportOptions options; - // Filename for a @_private import. - StringRef filename; + /// If this is a @_private import, the value of its 'sourceFile:' argument; + /// otherwise, empty string. + StringRef sourceFileArg; - // Names of explicitly imported SPIs. + /// Names of explicitly imported SPI groups. ArrayRef spiGroups; AttributedImport(ModuleInfo module, ImportOptions options, StringRef filename = {}, ArrayRef spiGroups = {}) - : module(module), importOptions(options), filename(filename), + : module(module), options(options), sourceFileArg(filename), spiGroups(spiGroups) { - assert(!(importOptions.contains(ImportFlags::Exported) && - importOptions.contains(ImportFlags::ImplementationOnly)) || - importOptions.contains(ImportFlags::Reserved)); + assert(!(options.contains(ImportFlags::Exported) && + options.contains(ImportFlags::ImplementationOnly)) || + options.contains(ImportFlags::Reserved)); } }; @@ -596,14 +602,14 @@ struct DenseMapInfo> { return detail::combineHashValue( ModuleInfoDMI::getHashValue(import.module), detail::combineHashValue( - ImportOptionsDMI::getHashValue(import.importOptions), - StringRefDMI::getHashValue(import.filename))); + ImportOptionsDMI::getHashValue(import.options), + StringRefDMI::getHashValue(import.sourceFileArg))); } static bool isEqual(const AttributedImport &a, const AttributedImport &b) { return ModuleInfoDMI::isEqual(a.module, b.module) && - ImportOptionsDMI::isEqual(a.importOptions, b.importOptions) && - StringRefDMI::isEqual(a.filename, b.filename); + ImportOptionsDMI::isEqual(a.options, b.options) && + StringRefDMI::isEqual(a.sourceFileArg, b.sourceFileArg); } }; } diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 66fcd8bc4d466..e553925cf85c7 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -1191,14 +1191,14 @@ SourceFile::getImportedModules(SmallVectorImpl &modules, for (auto desc : *Imports) { ModuleDecl::ImportFilter requiredFilter; - if (desc.importOptions.contains(ImportFlags::Exported)) + if (desc.options.contains(ImportFlags::Exported)) requiredFilter |= ModuleDecl::ImportFilterKind::Exported; - else if (desc.importOptions.contains(ImportFlags::ImplementationOnly)) + else if (desc.options.contains(ImportFlags::ImplementationOnly)) requiredFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly; else requiredFilter |= ModuleDecl::ImportFilterKind::Default; - if (desc.importOptions.contains(ImportFlags::SPIAccessControl)) + if (desc.options.contains(ImportFlags::SPIAccessControl)) requiredFilter |= ModuleDecl::ImportFilterKind::SPIAccessControl; if (!separatelyImportedOverlays.lookup(desc.module.importedModule).empty()) @@ -1892,7 +1892,7 @@ bool HasImplementationOnlyImportsRequest::evaluate(Evaluator &evaluator, SourceFile *SF) const { return llvm::any_of(SF->getImports(), [](AttributedImport desc) { - return desc.importOptions.contains(ImportFlags::ImplementationOnly); + return desc.options.contains(ImportFlags::ImplementationOnly); }); } @@ -1917,15 +1917,15 @@ bool SourceFile::hasTestableOrPrivateImport( [module, queryKind](AttributedImport desc) -> bool { if (queryKind == ImportQueryKind::TestableAndPrivate) return desc.module.importedModule == module && - (desc.importOptions.contains(ImportFlags::PrivateImport) || - desc.importOptions.contains(ImportFlags::Testable)); + (desc.options.contains(ImportFlags::PrivateImport) || + desc.options.contains(ImportFlags::Testable)); else if (queryKind == ImportQueryKind::TestableOnly) return desc.module.importedModule == module && - desc.importOptions.contains(ImportFlags::Testable); + desc.options.contains(ImportFlags::Testable); else { assert(queryKind == ImportQueryKind::PrivateOnly); return desc.module.importedModule == module && - desc.importOptions.contains(ImportFlags::PrivateImport); + desc.options.contains(ImportFlags::PrivateImport); } }); case AccessLevel::Open: @@ -1958,8 +1958,8 @@ bool SourceFile::hasTestableOrPrivateImport( return llvm::any_of(*Imports, [module, filename](AttributedImport desc) { return desc.module.importedModule == module && - desc.importOptions.contains(ImportFlags::PrivateImport) && - desc.filename == filename; + desc.options.contains(ImportFlags::PrivateImport) && + desc.sourceFileArg == filename; }); } @@ -1974,7 +1974,7 @@ bool SourceFile::isImportedImplementationOnly(const ModuleDecl *module) const { // Look at the imports of this source file. for (auto &desc : *Imports) { // Ignore implementation-only imports. - if (desc.importOptions.contains(ImportFlags::ImplementationOnly)) + if (desc.options.contains(ImportFlags::ImplementationOnly)) continue; // If the module is imported this way, it's not imported @@ -2012,7 +2012,7 @@ void SourceFile::lookupImportedSPIGroups( const ModuleDecl *importedModule, llvm::SmallSetVector &spiGroups) const { for (auto &import : *Imports) { - if (import.importOptions.contains(ImportFlags::SPIAccessControl) && + if (import.options.contains(ImportFlags::SPIAccessControl) && importedModule == import.module.importedModule) { auto importedSpis = import.spiGroups; spiGroups.insert(importedSpis.begin(), importedSpis.end()); diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index 17cf849302574..b8ee1ff3f1c8c 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -290,7 +290,7 @@ static void recordShadowedDeclsAfterTypeMatch( auto file = dc->getParentSourceFile(); if (!file) return false; for (const auto &import : file->getImports()) { - if (import.importOptions.contains(ImportFlags::PrivateImport) + if (import.options.contains(ImportFlags::PrivateImport) && import.module.importedModule == module && import.module.accessPath.matches(name)) return true; diff --git a/lib/AST/OperatorNameLookup.cpp b/lib/AST/OperatorNameLookup.cpp index e05e3347de08b..63e64547b4ef9 100644 --- a/lib/AST/OperatorNameLookup.cpp +++ b/lib/AST/OperatorNameLookup.cpp @@ -83,7 +83,7 @@ static TinyPtrVector lookupOperatorImpl( if (!visitedModules.insert(mod).second) continue; - bool isExported = import.importOptions.contains(ImportFlags::Exported); + bool isExported = import.options.contains(ImportFlags::Exported); if (!includePrivate && !isExported) continue; diff --git a/lib/Sema/ImportResolution.cpp b/lib/Sema/ImportResolution.cpp index c03b927af3953..ec0b2e76a1408 100644 --- a/lib/Sema/ImportResolution.cpp +++ b/lib/Sema/ImportResolution.cpp @@ -61,7 +61,7 @@ struct UnboundImport { /// If \c options includes \c PrivateImport, the filename we should import /// private declarations from. - StringRef privateImportFileName; + StringRef sourceFileArg; /// The module names being imported. There will usually be just one for the /// top-level module, but a submodule import will have more. @@ -137,8 +137,8 @@ struct UnboundImport { /// UnboundImport. AttributedImport makeAttributedImport(ModuleDecl *module) const { - return AttributedImport({ accessPath, module }, options, - privateImportFileName, spiGroups); + return { ImportedModule{ accessPath, module }, + options, sourceFileArg, spiGroups }; } private: @@ -496,7 +496,7 @@ ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, /// Create an UnboundImport for a user-written import declaration. UnboundImport::UnboundImport(ImportDecl *ID) - : importLoc(ID->getLoc()), options(), privateImportFileName(), + : importLoc(ID->getLoc()), options(), sourceFileArg(), modulePath(ID->getModulePath()), accessPath(ID->getAccessPath()), importOrUnderlyingModuleDecl(ID) { @@ -512,7 +512,7 @@ UnboundImport::UnboundImport(ImportDecl *ID) if (auto *privateImportAttr = ID->getAttrs().getAttribute()) { options |= ImportFlags::PrivateImport; - privateImportFileName = privateImportAttr->getSourceFile(); + sourceFileArg = privateImportAttr->getSourceFile(); } SmallVector spiGroups; @@ -607,7 +607,7 @@ void UnboundImport::validatePrivate(ModuleDecl *topLevelModule) { diagnoseInvalidAttr(DAK_PrivateImport, ctx.Diags, diag::module_not_compiled_for_private_import); - privateImportFileName = StringRef(); + sourceFileArg = StringRef(); } void UnboundImport::validateImplementationOnly(ASTContext &ctx) { @@ -915,9 +915,9 @@ ScopedImportLookupRequest::evaluate(Evaluator &evaluator, //===----------------------------------------------------------------------===// static bool canCrossImport(const AttributedImport &import) { - if (import.importOptions.contains(ImportFlags::Testable)) + if (import.options.contains(ImportFlags::Testable)) return false; - if (import.importOptions.contains(ImportFlags::PrivateImport)) + if (import.options.contains(ImportFlags::PrivateImport)) return false; return true; @@ -928,7 +928,7 @@ UnboundImport::UnboundImport( ASTContext &ctx, const UnboundImport &base, Identifier overlayName, const AttributedImport &declaringImport, const AttributedImport &bystandingImport) - : importLoc(base.importLoc), options(), privateImportFileName(), + : importLoc(base.importLoc), options(), sourceFileArg(), // Cross-imports are not backed by an ImportDecl, so we need to provide // our own storage for their module paths. modulePath( @@ -944,8 +944,8 @@ UnboundImport::UnboundImport( assert(canCrossImport(declaringImport)); assert(canCrossImport(bystandingImport)); - auto &declaringOptions = declaringImport.importOptions; - auto &bystandingOptions = bystandingImport.importOptions; + auto &declaringOptions = declaringImport.options; + auto &bystandingOptions = bystandingImport.options; // If both are exported, the cross-import is exported. if (declaringOptions.contains(ImportFlags::Exported) && From 8070e8aaedf662bceea1483840cf0f61d5a8b8a4 Mon Sep 17 00:00:00 2001 From: Brent Royal-Gordon Date: Fri, 25 Sep 2020 15:19:05 -0700 Subject: [PATCH 04/13] [NFC] Use AttributedImport in import resolution Removes what amount to redundant definitions from UnboundImport. --- include/swift/AST/Import.h | 70 ++++++++++++++++++-- lib/Sema/ImportResolution.cpp | 121 ++++++++++++++++------------------ 2 files changed, 123 insertions(+), 68 deletions(-) diff --git a/include/swift/AST/Import.h b/include/swift/AST/Import.h index 5ff068feb5bc5..1988460bc24ba 100644 --- a/include/swift/AST/Import.h +++ b/include/swift/AST/Import.h @@ -24,6 +24,7 @@ #include "swift/Basic/OptionSet.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" @@ -50,6 +51,10 @@ enum class ImportKind : uint8_t { Func }; +inline bool isScopedImportKind(ImportKind importKind) { + return importKind != ImportKind::Module; +} + /// Possible attributes for imports in source files. enum class ImportFlags { /// The imported module is exposed to anyone who imports the parent module. @@ -156,9 +161,17 @@ namespace detail { template class ImportPathBuilder { - llvm::SmallVector scratch; + using Scratch = llvm::SmallVector; + Scratch scratch; public: + using value_type = Scratch::value_type; + using reference = Scratch::reference; + using iterator = Scratch::iterator; + using const_iterator = Scratch::const_iterator; + using difference_type = Scratch::difference_type; + using size_type = Scratch::size_type; + Subclass get() const { return Subclass(scratch); } @@ -390,18 +403,67 @@ class ImportPath : public detail::ImportPathBase { /// including submodules, assuming the \c ImportDecl has the indicated /// \c importKind. Module getModulePath(ImportKind importKind) const { - return getModulePath(importKind != ImportKind::Module); + return getModulePath(isScopedImportKind(importKind)); } /// Extracts the portion of the \c ImportPath which represents a scope for the /// import, assuming the \c ImportDecl has the indicated \c importKind. Access getAccessPath(ImportKind importKind) const { - return getAccessPath(importKind != ImportKind::Module); + return getAccessPath(isScopedImportKind(importKind)); } }; // MARK: - Abstractions of imports +/// Convenience struct to keep track of an import path and whether or not it +/// is scoped. +class UnloadedImportedModule { + // This is basically an ArrayRef with a bit stolen from the pointer. + // FIXME: Extract an ArrayRefIntPair type from this. + llvm::PointerIntPair dataAndIsScoped; + ImportPath::Raw::size_type length; + + ImportPath::Raw::iterator data() const { + return dataAndIsScoped.getPointer(); + } + + bool isScoped() const { + return dataAndIsScoped.getInt(); + } + + ImportPath::Raw getRaw() const { + return ImportPath::Raw(data(), length); + } + + UnloadedImportedModule(ImportPath::Raw raw, bool isScoped) + : dataAndIsScoped(raw.data(), isScoped), length(raw.size()) { } + +public: + UnloadedImportedModule(ImportPath importPath, bool isScoped) + : UnloadedImportedModule(importPath.getRaw(), isScoped) { } + + UnloadedImportedModule(ImportPath importPath, ImportKind importKind) + : UnloadedImportedModule(importPath, isScopedImportKind(importKind)) { } + + ImportPath getImportPath() const { + return ImportPath(getRaw()); + } + + ImportPath::Module getModulePath() const { + return getImportPath().getModulePath(isScoped()); + } + + ImportPath::Access getAccessPath() const { + return getImportPath().getAccessPath(isScoped()); + } + + friend bool operator==(const UnloadedImportedModule &lhs, + const UnloadedImportedModule &rhs) { + return (lhs.getRaw() == rhs.getRaw()) && + (lhs.isScoped() == rhs.isScoped()); + } +}; + /// Convenience struct to keep track of a module along with its access path. struct alignas(uint64_t) ImportedModule { /// The access path from an import: `import Foo.Bar` -> `Foo.Bar`. @@ -472,8 +534,6 @@ struct AttributedImport { } }; -using ImportedModuleDesc = AttributedImport; - // MARK: - Implicit imports /// A module which has been implicitly imported. diff --git a/lib/Sema/ImportResolution.cpp b/lib/Sema/ImportResolution.cpp index ec0b2e76a1408..b6825c8ef9e2f 100644 --- a/lib/Sema/ImportResolution.cpp +++ b/lib/Sema/ImportResolution.cpp @@ -51,36 +51,17 @@ namespace { /// source, or it may represent a cross-import overlay that has been found and /// needs to be loaded. struct UnboundImport { + /// Information about the import. Use this field, not \c getImportDecl(), to + /// determine the behavior expected for this import. + AttributedImport import; + /// The source location to use when diagnosing errors for this import. SourceLoc importLoc; - /// The options for this import, such as "exported" or - /// "implementation-only". Use this field, not \c attrs, to determine the - /// behavior expected for this import. - ImportOptions options; - - /// If \c options includes \c PrivateImport, the filename we should import - /// private declarations from. - StringRef sourceFileArg; - - /// The module names being imported. There will usually be just one for the - /// top-level module, but a submodule import will have more. - ImportPath::Module modulePath; - - /// If this is a scoped import, the names of the declaration being imported; - /// otherwise empty. (Currently the compiler doesn't support nested scoped - /// imports, so there should always be zero or one elements, but - /// \c ImportPath::Access is the common currency type for this.) - ImportPath::Access accessPath; - - // Names of explicitly imported SPI groups via @_spi. - ArrayRef spiGroups; - /// If this UnboundImport directly represents an ImportDecl, contains the /// ImportDecl it represents. This should only be used for diagnostics and /// for updating the AST; if you want to read information about the import, - /// get it from the other fields in \c UnboundImport rather than from the - /// \c ImportDecl. + /// get it from the \c import field rather than from the \c ImportDecl. /// /// If this UnboundImport represents a cross-import, contains the declaring /// module's \c ModuleDecl. @@ -137,8 +118,8 @@ struct UnboundImport { /// UnboundImport. AttributedImport makeAttributedImport(ModuleDecl *module) const { - return { ImportedModule{ accessPath, module }, - options, sourceFileArg, spiGroups }; + return { ImportedModule{ import.module.getAccessPath(), module }, + import.options, import.sourceFileArg, import.spiGroups }; } private: @@ -326,7 +307,7 @@ void ImportResolver::bindImport(UnboundImport &&I) { return; } - ModuleDecl *M = getModule(I.modulePath); + ModuleDecl *M = getModule(I.import.module.getModulePath()); if (!I.checkModuleLoaded(M, SF)) { // Can't process further. checkModuleLoaded() will have diagnosed this. if (ID) @@ -392,11 +373,11 @@ ImportResolver::getModule(ImportPath::Module modulePath) { NullablePtr UnboundImport::getTopLevelModule(ModuleDecl *M, SourceFile &SF) { - if (modulePath.size() == 1) + if (import.module.getModulePath().size() == 1) return M; // If we imported a submodule, import the top-level module as well. - Identifier topLevelName = modulePath.front().Item; + Identifier topLevelName = import.module.getModulePath().front().Item; ModuleDecl *topLevelModule = SF.getASTContext().getLoadedModule(topLevelName); if (!topLevelModule) { @@ -496,39 +477,40 @@ ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, /// Create an UnboundImport for a user-written import declaration. UnboundImport::UnboundImport(ImportDecl *ID) - : importLoc(ID->getLoc()), options(), sourceFileArg(), - modulePath(ID->getModulePath()), accessPath(ID->getAccessPath()), - importOrUnderlyingModuleDecl(ID) + : import(UnloadedImportedModule(ID->getImportPath(), ID->getImportKind()), + {}), + importLoc(ID->getLoc()), importOrUnderlyingModuleDecl(ID) { if (ID->isExported()) - options |= ImportFlags::Exported; + import.options |= ImportFlags::Exported; if (ID->getAttrs().hasAttribute()) - options |= ImportFlags::Testable; + import.options |= ImportFlags::Testable; if (ID->getAttrs().hasAttribute()) - options |= ImportFlags::ImplementationOnly; + import.options |= ImportFlags::ImplementationOnly; if (auto *privateImportAttr = ID->getAttrs().getAttribute()) { - options |= ImportFlags::PrivateImport; - sourceFileArg = privateImportAttr->getSourceFile(); + import.options |= ImportFlags::PrivateImport; + import.sourceFileArg = privateImportAttr->getSourceFile(); } SmallVector spiGroups; for (auto attr : ID->getAttrs().getAttributes()) { - options |= ImportFlags::SPIAccessControl; + import.options |= ImportFlags::SPIAccessControl; auto attrSPIs = attr->getSPIGroups(); spiGroups.append(attrSPIs.begin(), attrSPIs.end()); } - this->spiGroups = ID->getASTContext().AllocateCopy(spiGroups); + import.spiGroups = ID->getASTContext().AllocateCopy(spiGroups); } bool UnboundImport::checkNotTautological(const SourceFile &SF) { // Exit early if this is not a self-import. + auto modulePath = import.module.getModulePath(); if (modulePath.front().Item != SF.getParentModule()->getName() || // Overlays use an @_exported self-import to load their clang module. - options.contains(ImportFlags::Exported) || + import.options.contains(ImportFlags::Exported) || // Imports of your own submodules are allowed in cross-language libraries. modulePath.size() != 1 || // SIL files self-import to get decls from the rest of the module. @@ -555,7 +537,8 @@ bool UnboundImport::checkModuleLoaded(ModuleDecl *M, SourceFile &SF) { ASTContext &ctx = SF.getASTContext(); SmallString<64> modulePathStr; - llvm::interleave(modulePath, [&](ImportPath::Element elem) { + llvm::interleave(import.module.getModulePath(), + [&](ImportPath::Element elem) { modulePathStr += elem.Item.str(); }, [&] { modulePathStr += "."; }); @@ -599,7 +582,7 @@ void UnboundImport::validatePrivate(ModuleDecl *topLevelModule) { assert(topLevelModule); ASTContext &ctx = topLevelModule->getASTContext(); - if (!options.contains(ImportFlags::PrivateImport)) + if (!import.options.contains(ImportFlags::PrivateImport)) return; if (topLevelModule->arePrivateImportsEnabled()) @@ -607,16 +590,16 @@ void UnboundImport::validatePrivate(ModuleDecl *topLevelModule) { diagnoseInvalidAttr(DAK_PrivateImport, ctx.Diags, diag::module_not_compiled_for_private_import); - sourceFileArg = StringRef(); + import.sourceFileArg = StringRef(); } void UnboundImport::validateImplementationOnly(ASTContext &ctx) { - if (!options.contains(ImportFlags::ImplementationOnly) || - !options.contains(ImportFlags::Exported)) + if (!import.options.contains(ImportFlags::ImplementationOnly) || + !import.options.contains(ImportFlags::Exported)) return; // Remove one flag to maintain the invariant. - options -= ImportFlags::ImplementationOnly; + import.options -= ImportFlags::ImplementationOnly; diagnoseInvalidAttr(DAK_ImplementationOnly, ctx.Diags, diag::import_implementation_cannot_be_exported); @@ -626,7 +609,7 @@ void UnboundImport::validateTestable(ModuleDecl *topLevelModule) { assert(topLevelModule); ASTContext &ctx = topLevelModule->getASTContext(); - if (!options.contains(ImportFlags::Testable) || + if (!import.options.contains(ImportFlags::Testable) || topLevelModule->isTestingEnabled() || topLevelModule->isNonSwiftModule() || !ctx.LangOpts.EnableTestableAttrRequiresTestableModule) @@ -637,7 +620,7 @@ void UnboundImport::validateTestable(ModuleDecl *topLevelModule) { void UnboundImport::validateResilience(NullablePtr topLevelModule, SourceFile &SF) { - if (options.contains(ImportFlags::ImplementationOnly)) + if (import.options.contains(ImportFlags::ImplementationOnly)) return; // Per getTopLevelModule(), we'll only get nullptr here for non-Swift modules, @@ -650,7 +633,7 @@ void UnboundImport::validateResilience(NullablePtr topLevelModule, return; ASTContext &ctx = SF.getASTContext(); - ctx.Diags.diagnose(modulePath.front().Loc, + ctx.Diags.diagnose(import.module.getModulePath().front().Loc, diag::module_not_compiled_with_library_evolution, topLevelModule.get()->getName(), SF.getParentModule()->getName()); @@ -661,8 +644,8 @@ void UnboundImport::validateResilience(NullablePtr topLevelModule, void UnboundImport::diagnoseInvalidAttr(DeclAttrKind attrKind, DiagnosticEngine &diags, Diag diagID) { - auto diag = diags.diagnose(modulePath.front().Loc, diagID, - modulePath.front().Item); + auto diag = diags.diagnose(import.module.getModulePath().front().Loc, diagID, + import.module.getModulePath().front().Item); auto *ID = getImportDecl().getPtrOrNull(); if (!ID) return; @@ -923,20 +906,32 @@ static bool canCrossImport(const AttributedImport &import) { return true; } +static UnloadedImportedModule makeUnimportedCrossImportOverlay( + ASTContext &ctx, + Identifier overlayName, + const UnboundImport &base, + const AttributedImport &declaringImport) { + ImportPath::Builder + builder(overlayName, base.import.module.getModulePath()[0].Loc); + + // If the declaring import was scoped, inherit that scope in the overlay's + // import. + llvm::copy(declaringImport.module.accessPath, std::back_inserter(builder)); + + // Cross-imports are not backed by an ImportDecl, so we need to provide + // our own storage for their module paths. + return UnloadedImportedModule(builder.copyTo(ctx), + /*isScoped=*/!declaringImport.module.accessPath.empty()); +} + /// Create an UnboundImport for a cross-import overlay. UnboundImport::UnboundImport( ASTContext &ctx, const UnboundImport &base, Identifier overlayName, const AttributedImport &declaringImport, const AttributedImport &bystandingImport) - : importLoc(base.importLoc), options(), sourceFileArg(), - // Cross-imports are not backed by an ImportDecl, so we need to provide - // our own storage for their module paths. - modulePath( - ImportPath::Module::Builder(overlayName, base.modulePath[0].Loc) - .copyTo(ctx)), - // If the declaring import was scoped, inherit that scope in the - // overlay's import. - accessPath(declaringImport.module.accessPath), + : import(makeUnimportedCrossImportOverlay(ctx, overlayName, base, + declaringImport), {}), + importLoc(base.importLoc), importOrUnderlyingModuleDecl(declaringImport.module.importedModule) { // A cross-import is never private or testable, and never comes from a private @@ -950,13 +945,13 @@ UnboundImport::UnboundImport( // If both are exported, the cross-import is exported. if (declaringOptions.contains(ImportFlags::Exported) && bystandingOptions.contains(ImportFlags::Exported)) - options |= ImportFlags::Exported; + import.options |= ImportFlags::Exported; // If either are implementation-only, the cross-import is // implementation-only. if (declaringOptions.contains(ImportFlags::ImplementationOnly) || bystandingOptions.contains(ImportFlags::ImplementationOnly)) - options |= ImportFlags::ImplementationOnly; + import.options |= ImportFlags::ImplementationOnly; } void ImportResolver::crossImport(ModuleDecl *M, UnboundImport &I) { @@ -1107,7 +1102,7 @@ void ImportResolver::findCrossImports( name); LLVM_DEBUG({ - auto &crossImportOptions = unboundImports.back().options; + auto &crossImportOptions = unboundImports.back().import.options; llvm::dbgs() << " "; if (crossImportOptions.contains(ImportFlags::Exported)) llvm::dbgs() << "@_exported "; From d55c5bd549fa17769c23be9708c33c8de9ed0ef1 Mon Sep 17 00:00:00 2001 From: Brent Royal-Gordon Date: Fri, 25 Sep 2020 16:26:39 -0700 Subject: [PATCH 05/13] [NFC] Add type for ModuleDecl::getImplicitImports() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This doesn’t really change the design yet. --- include/swift/AST/ASTTypeIDZone.def | 2 +- include/swift/AST/ASTTypeIDs.h | 2 +- include/swift/AST/Import.h | 15 ++++++++++++ include/swift/AST/Module.h | 3 +-- include/swift/AST/TypeCheckRequests.h | 5 ++-- include/swift/AST/TypeCheckerTypeIDZone.def | 2 +- lib/AST/Module.cpp | 3 +-- lib/AST/TypeCheckRequests.cpp | 8 +++++++ lib/Sema/ImportResolution.cpp | 26 ++++++++++++--------- 9 files changed, 45 insertions(+), 21 deletions(-) diff --git a/include/swift/AST/ASTTypeIDZone.def b/include/swift/AST/ASTTypeIDZone.def index 6bbe1a459ceb5..d4ebede4903ec 100644 --- a/include/swift/AST/ASTTypeIDZone.def +++ b/include/swift/AST/ASTTypeIDZone.def @@ -22,7 +22,7 @@ SWIFT_TYPEID(BodyInitKindAndExpr) SWIFT_TYPEID(CtorInitializerKind) SWIFT_TYPEID(FunctionBuilderBodyPreCheck) SWIFT_TYPEID(GenericSignature) -SWIFT_TYPEID(ImplicitImport) +SWIFT_TYPEID(ImplicitImportList) SWIFT_TYPEID(ImplicitMemberAction) SWIFT_TYPEID(ParamSpecifier) SWIFT_TYPEID(PropertyWrapperBackingPropertyInfo) diff --git a/include/swift/AST/ASTTypeIDs.h b/include/swift/AST/ASTTypeIDs.h index 8bbb7366f965d..94323e9353913 100644 --- a/include/swift/AST/ASTTypeIDs.h +++ b/include/swift/AST/ASTTypeIDs.h @@ -42,7 +42,7 @@ class GenericTypeParamType; class InfixOperatorDecl; class IterableDeclContext; class ModuleDecl; -struct ImplicitImport; +struct ImplicitImportList; class NamedPattern; class NominalTypeDecl; class OperatorDecl; diff --git a/include/swift/AST/Import.h b/include/swift/AST/Import.h index 1988460bc24ba..e6b28b438c22f 100644 --- a/include/swift/AST/Import.h +++ b/include/swift/AST/Import.h @@ -565,6 +565,7 @@ enum class ImplicitStdlibKind { Stdlib }; +/// Represents unprocessed options for implicit imports. struct ImplicitImportInfo { /// The implicit stdlib to import. ImplicitStdlibKind StdlibKind; @@ -589,6 +590,20 @@ struct ImplicitImportInfo { ShouldImportUnderlyingModule(false) {} }; +/// Contains names of and pointers to modules that must be implicitly imported. +struct ImplicitImportList { + ArrayRef imports; + + friend bool operator==(const ImplicitImportList &lhs, + const ImplicitImportList &rhs) { + return lhs.imports == rhs.imports; + } +}; + +/// A list of modules to implicitly import. +void simple_display(llvm::raw_ostream &out, + const ImplicitImportList &importList); + } // MARK: - DenseMapInfo diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index 3c3dcb0485995..d9c6dc675b40d 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -56,7 +56,6 @@ namespace swift { class FuncDecl; class InfixOperatorDecl; class LinkLibrary; - struct ImplicitImport; class ModuleLoader; class NominalTypeDecl; class EnumElementDecl; @@ -278,7 +277,7 @@ class ModuleDecl : public DeclContext, public TypeDecl { /// Retrieve a list of modules that each file of this module implicitly /// imports. - ArrayRef getImplicitImports() const; + ImplicitImportList getImplicitImports() const; ArrayRef getFiles() { assert(!Files.empty() || failedToLoad()); diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 4d2b1a8acc57d..4926c75477fac 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -2498,7 +2498,7 @@ class SimpleDidSetRequest /// of a given module. class ModuleImplicitImportsRequest : public SimpleRequest(ModuleDecl *), + ImplicitImportList(ModuleDecl *), RequestFlags::Cached> { public: using SimpleRequest::SimpleRequest; @@ -2506,8 +2506,7 @@ class ModuleImplicitImportsRequest private: friend SimpleRequest; - ArrayRef - evaluate(Evaluator &evaluator, ModuleDecl *module) const; + ImplicitImportList evaluate(Evaluator &evaluator, ModuleDecl *module) const; public: // Cached. diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 7b3f269555979..446b8c1e1a39f 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -148,7 +148,7 @@ SWIFT_REQUEST(TypeChecker, ValidatePrecedenceGroupRequest, SWIFT_REQUEST(TypeChecker, MangleLocalTypeDeclRequest, std::string(const TypeDecl *), Cached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, ModuleImplicitImportsRequest, - ArrayRef(ModuleDecl *), Cached, NoLocationInfo) + ImplicitImportList(ModuleDecl *), Cached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, NamingPatternRequest, NamedPattern *(VarDecl *), SeparatelyCached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, OpaqueReadOwnershipRequest, diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index e553925cf85c7..6095d2d8c0008 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -487,14 +487,13 @@ ModuleDecl::ModuleDecl(Identifier name, ASTContext &ctx, Bits.ModuleDecl.HasIncrementalInfo = 0; } -ArrayRef ModuleDecl::getImplicitImports() const { +ImplicitImportList ModuleDecl::getImplicitImports() const { auto &evaluator = getASTContext().evaluator; auto *mutableThis = const_cast(this); return evaluateOrDefault(evaluator, ModuleImplicitImportsRequest{mutableThis}, {}); } - void ModuleDecl::addFile(FileUnit &newFile) { // If this is a LoadedFile, make sure it loaded without error. assert(!(isa(newFile) && diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index da08ab9057d25..501499a62b8a9 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -1397,6 +1397,14 @@ void swift::simple_display(llvm::raw_ostream &out, simple_display(out, import.Module); } +void swift::simple_display(llvm::raw_ostream &out, + const ImplicitImportList &importList) { + llvm::interleaveComma(importList.imports, out, + [&](const auto &import) { + simple_display(out, import); + }); +} + //----------------------------------------------------------------------------// // ResolveTypeRequest computation. //----------------------------------------------------------------------------// diff --git a/lib/Sema/ImportResolution.cpp b/lib/Sema/ImportResolution.cpp index b6825c8ef9e2f..68ad80ec9b3e0 100644 --- a/lib/Sema/ImportResolution.cpp +++ b/lib/Sema/ImportResolution.cpp @@ -174,15 +174,7 @@ class ImportResolver final : public DeclVisitor { addImplicitImports(); } - void addImplicitImports() { - // TODO: Support cross-module imports. - for (auto &import : SF.getParentModule()->getImplicitImports()) { - assert(!(SF.Kind == SourceFileKind::SIL && - import.Module->isStdlibModule())); - ImportedModule importedMod{ImportPath::Access(), import.Module}; - boundImports.emplace_back(importedMod, import.Options); - } - } + void addImplicitImports(); /// Retrieve the finalized imports. ArrayRef> getFinishedImports() const { @@ -400,7 +392,7 @@ UnboundImport::getTopLevelModule(ModuleDecl *M, SourceFile &SF) { // MARK: Implicit imports //===----------------------------------------------------------------------===// -ArrayRef +ImplicitImportList ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, ModuleDecl *module) const { SmallVector imports; @@ -468,7 +460,19 @@ ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, } } - return ctx.AllocateCopy(imports); + return { ctx.AllocateCopy(imports) }; +} + +void ImportResolver::addImplicitImports() { + auto implicitImports = SF.getParentModule()->getImplicitImports(); + + // TODO: Support cross-module imports. + for (auto &import : implicitImports.imports) { + assert(!(SF.Kind == SourceFileKind::SIL && + import.Module->isStdlibModule())); + ImportedModule importedMod{ImportPath::Access(), import.Module}; + boundImports.emplace_back(importedMod, import.Options); + } } //===----------------------------------------------------------------------===// From 563386b06d8c1cf863be71c38345fcaefa00e423 Mon Sep 17 00:00:00 2001 From: Brent Royal-Gordon Date: Fri, 25 Sep 2020 16:34:33 -0700 Subject: [PATCH 06/13] [NFC] Eliminate ImplicitImport MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead, we will use AttributedImport, a common currency type which supports a superset of ImplicitImport’s current behavior. --- include/swift/AST/Import.h | 29 ++++++++++++----------------- lib/AST/TypeCheckRequests.cpp | 34 +++++++++++++++++++++++++++++++--- lib/Sema/ImportResolution.cpp | 33 +++++++++++++++++++++------------ 3 files changed, 64 insertions(+), 32 deletions(-) diff --git a/include/swift/AST/Import.h b/include/swift/AST/Import.h index e6b28b438c22f..e94fd37189324 100644 --- a/include/swift/AST/Import.h +++ b/include/swift/AST/Import.h @@ -532,26 +532,21 @@ struct AttributedImport { options.contains(ImportFlags::ImplementationOnly)) || options.contains(ImportFlags::Reserved)); } -}; - -// MARK: - Implicit imports - -/// A module which has been implicitly imported. -struct ImplicitImport { - ModuleDecl *Module; - ImportOptions Options; - ImplicitImport(ModuleDecl *module, ImportOptions opts = {}) - : Module(module), Options(opts) {} - - friend bool operator==(const ImplicitImport &lhs, - const ImplicitImport &rhs) { - return lhs.Module == rhs.Module && - lhs.Options.toRaw() == rhs.Options.toRaw(); + friend bool operator==(const AttributedImport &lhs, + const AttributedImport &rhs) { + return lhs.module == rhs.module && + lhs.options.toRaw() == rhs.options.toRaw() && + lhs.sourceFileArg == rhs.sourceFileArg && + lhs.spiGroups == rhs.spiGroups; } }; -void simple_display(llvm::raw_ostream &out, const ImplicitImport &import); +/// A module which has been implicitly imported. +void simple_display(llvm::raw_ostream &out, + const AttributedImport &import); + +// MARK: - Implicit imports /// The kind of stdlib that should be imported. enum class ImplicitStdlibKind { @@ -592,7 +587,7 @@ struct ImplicitImportInfo { /// Contains names of and pointers to modules that must be implicitly imported. struct ImplicitImportList { - ArrayRef imports; + ArrayRef> imports; friend bool operator==(const ImplicitImportList &lhs, const ImplicitImportList &rhs) { diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index 501499a62b8a9..feb1f4087388f 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -1392,9 +1392,37 @@ TypeCheckFunctionBodyRequest::readDependencySource( //----------------------------------------------------------------------------// void swift::simple_display(llvm::raw_ostream &out, - const ImplicitImport &import) { - out << "implicit import of "; - simple_display(out, import.Module); + const AttributedImport &import) { + out << "import of "; + + if (!import.module.accessPath.empty()) { + simple_display(out, import.module.accessPath.front().Item); + out << " in "; + } + + simple_display(out, import.module.importedModule); + + out << " ["; + if (import.options.contains(ImportFlags::Exported)) + out << " exported"; + if (import.options.contains(ImportFlags::Testable)) + out << " testable"; + if (import.options.contains(ImportFlags::ImplementationOnly)) + out << " implementation-only"; + if (import.options.contains(ImportFlags::PrivateImport)) + out << " private(" << import.sourceFileArg << ")"; + + if (import.options.contains(ImportFlags::SPIAccessControl)) { + out << " spi("; + llvm::interleave(import.spiGroups, + [&out](Identifier name) { + simple_display(out, name); + }, + [&out]() { out << " "; }); + out << ")"; + } + + out << " ]"; } void swift::simple_display(llvm::raw_ostream &out, diff --git a/lib/Sema/ImportResolution.cpp b/lib/Sema/ImportResolution.cpp index 68ad80ec9b3e0..0c6b618fdcac7 100644 --- a/lib/Sema/ImportResolution.cpp +++ b/lib/Sema/ImportResolution.cpp @@ -395,26 +395,32 @@ UnboundImport::getTopLevelModule(ModuleDecl *M, SourceFile &SF) { ImplicitImportList ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, ModuleDecl *module) const { - SmallVector imports; + SmallVector, 4> imports; auto &ctx = module->getASTContext(); auto &importInfo = module->getImplicitImportInfo(); // Add an implicit stdlib if needed. + ModuleDecl *stdlib; switch (importInfo.StdlibKind) { case ImplicitStdlibKind::None: + stdlib = nullptr; break; case ImplicitStdlibKind::Builtin: - imports.emplace_back(ctx.TheBuiltinModule); + stdlib = ctx.TheBuiltinModule; break; case ImplicitStdlibKind::Stdlib: { - auto *stdlib = ctx.getStdlibModule(/*loadIfAbsent*/ true); + stdlib = ctx.getStdlibModule(/*loadIfAbsent*/ true); assert(stdlib && "Missing stdlib?"); - imports.emplace_back(stdlib); break; } } + if (stdlib) { + ImportedModule import(ImportPath::Access(), stdlib); + imports.emplace_back(import, ImportOptions()); + } + // Add any modules we were asked to implicitly import. for (auto moduleName : importInfo.ModuleNames) { auto *importModule = ctx.getModuleByIdentifier(moduleName); @@ -427,13 +433,15 @@ ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, } continue; } - imports.emplace_back(importModule); + ImportedModule import(ImportPath::Access(), importModule); + imports.emplace_back(import, ImportOptions()); } // Add any pre-loaded modules. for (auto &module : importInfo.AdditionalModules) { - imports.emplace_back(module.first, module.second ? ImportFlags::Exported - : ImportOptions()); + ImportedModule import(ImportPath::Access(), module.first); + imports.emplace_back(import, module.second ? ImportFlags::Exported + : ImportOptions()); } auto *clangImporter = @@ -445,7 +453,8 @@ ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, !clangImporter->importBridgingHeader(bridgingHeaderPath, module)) { auto *headerModule = clangImporter->getImportedHeaderModule(); assert(headerModule && "Didn't load bridging header?"); - imports.emplace_back(headerModule, ImportFlags::Exported); + ImportedModule import(ImportPath::Access(), headerModule); + imports.emplace_back(import, ImportFlags::Exported); } // Implicitly import the underlying Clang half of this module if needed. @@ -453,7 +462,8 @@ ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, auto *underlyingMod = clangImporter->loadModule( SourceLoc(), ImportPath::Module::Builder(module->getName()).get()); if (underlyingMod) { - imports.emplace_back(underlyingMod, ImportFlags::Exported); + ImportedModule import(ImportPath::Access(), underlyingMod); + imports.emplace_back(import, ImportFlags::Exported); } else { ctx.Diags.diagnose(SourceLoc(), diag::error_underlying_module_not_found, module->getName()); @@ -469,9 +479,8 @@ void ImportResolver::addImplicitImports() { // TODO: Support cross-module imports. for (auto &import : implicitImports.imports) { assert(!(SF.Kind == SourceFileKind::SIL && - import.Module->isStdlibModule())); - ImportedModule importedMod{ImportPath::Access(), import.Module}; - boundImports.emplace_back(importedMod, import.Options); + import.module.importedModule->isStdlibModule())); + boundImports.push_back(import); } } From c13067a0e0e9a1ea474a307c10d177c27e57fd58 Mon Sep 17 00:00:00 2001 From: Brent Royal-Gordon Date: Fri, 25 Sep 2020 15:28:29 -0700 Subject: [PATCH 07/13] [NFC] Rework ImplicitImportInfo::ModuleNames Replace with an array of AttributedImport to add flexibility. --- include/swift/AST/Import.h | 9 +-- lib/Frontend/Frontend.cpp | 17 +++-- lib/FrontendTool/ScanDependencies.cpp | 8 +-- lib/IDE/REPLCodeCompletion.cpp | 9 +-- lib/Sema/ImportResolution.cpp | 67 +++++++++---------- lib/Serialization/ModuleDependencyScanner.cpp | 4 +- 6 files changed, 62 insertions(+), 52 deletions(-) diff --git a/include/swift/AST/Import.h b/include/swift/AST/Import.h index e94fd37189324..5f1b582157f20 100644 --- a/include/swift/AST/Import.h +++ b/include/swift/AST/Import.h @@ -572,13 +572,14 @@ struct ImplicitImportInfo { /// The bridging header path for this module, empty if there is none. StringRef BridgingHeaderPath; - /// The names of additional modules to be implicitly imported. - SmallVector ModuleNames; + /// The names of additional modules to be loaded and implicitly imported. + SmallVector, 4> + AdditionalUnloadedImports; /// An additional list of already-loaded modules which should be implicitly /// imported. - SmallVector, 4> - AdditionalModules; + SmallVector, 4> + AdditionalImports; ImplicitImportInfo() : StdlibKind(ImplicitStdlibKind::None), diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 8ca60ba422374..4d661e604c62c 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -740,11 +740,20 @@ ImplicitImportInfo CompilerInstance::getImplicitImportInfo() const { ImplicitImportInfo imports; imports.StdlibKind = Invocation.getImplicitStdlibKind(); - for (auto &moduleStr : frontendOpts.getImplicitImportModuleNames()) - imports.ModuleNames.push_back(Context->getIdentifier(moduleStr)); + auto pushImport = [&](StringRef moduleStr) { + ImportPath::Builder importPath(Context->getIdentifier(moduleStr)); + UnloadedImportedModule import(importPath.copyTo(*Context), + /*isScoped=*/false); + imports.AdditionalUnloadedImports.emplace_back(import, ImportOptions()); + }; + + for (auto &moduleStr : frontendOpts.getImplicitImportModuleNames()) { + pushImport(moduleStr); + } - if (Invocation.shouldImportSwiftONoneSupport()) - imports.ModuleNames.push_back(Context->getIdentifier(SWIFT_ONONE_SUPPORT)); + if (Invocation.shouldImportSwiftONoneSupport()) { + pushImport(SWIFT_ONONE_SUPPORT); + } imports.ShouldImportUnderlyingModule = frontendOpts.ImportUnderlyingModule; imports.BridgingHeaderPath = frontendOpts.ImplicitObjCHeaderPath; diff --git a/lib/FrontendTool/ScanDependencies.cpp b/lib/FrontendTool/ScanDependencies.cpp index a39468e13fb21..ede07f9064085 100644 --- a/lib/FrontendTool/ScanDependencies.cpp +++ b/lib/FrontendTool/ScanDependencies.cpp @@ -817,13 +817,13 @@ bool swift::scanDependencies(CompilerInstance &instance) { } // Add any implicit module names. - for (const auto &moduleName : importInfo.ModuleNames) { - mainDependencies.addModuleDependency(moduleName.str(), &alreadyAddedModules); + for (const auto &import : importInfo.AdditionalUnloadedImports) { + mainDependencies.addModuleDependency(import.module.getModulePath().front().Item.str(), &alreadyAddedModules); } // Already-loaded, implicitly imported module names. - for (const auto &module : importInfo.AdditionalModules) { - mainDependencies.addModuleDependency(module.first->getNameStr(), &alreadyAddedModules); + for (const auto &import : importInfo.AdditionalImports) { + mainDependencies.addModuleDependency(import.module.importedModule->getNameStr(), &alreadyAddedModules); } // Add the bridging header. diff --git a/lib/IDE/REPLCodeCompletion.cpp b/lib/IDE/REPLCodeCompletion.cpp index 1c7ffa17883b6..52566e24297a9 100644 --- a/lib/IDE/REPLCodeCompletion.cpp +++ b/lib/IDE/REPLCodeCompletion.cpp @@ -221,16 +221,17 @@ doCodeCompletion(SourceFile &SF, StringRef EnteredCode, unsigned *BufferID, auto *lastModule = SF.getParentModule(); ImplicitImportInfo implicitImports; - implicitImports.AdditionalModules.emplace_back(lastModule, - /*exported*/ false); + { + ImportedModule import(ImportPath::Access(), lastModule); + implicitImports.AdditionalImports.emplace_back(import, ImportOptions()); + } // Carry over the private imports from the last module. SmallVector imports; lastModule->getImportedModules(imports, ModuleDecl::ImportFilterKind::Default); for (auto &import : imports) { - implicitImports.AdditionalModules.emplace_back(import.importedModule, - /*exported*/ false); + implicitImports.AdditionalImports.emplace_back(import, ImportOptions()); } // Create a new module and file for the code completion buffer, similar to how diff --git a/lib/Sema/ImportResolution.cpp b/lib/Sema/ImportResolution.cpp index 0c6b618fdcac7..87aff0cb51056 100644 --- a/lib/Sema/ImportResolution.cpp +++ b/lib/Sema/ImportResolution.cpp @@ -392,6 +392,27 @@ UnboundImport::getTopLevelModule(ModuleDecl *M, SourceFile &SF) { // MARK: Implicit imports //===----------------------------------------------------------------------===// +static void diagnoseNoSuchModule(ASTContext &ctx, SourceLoc importLoc, + ImportPath::Module modulePath, + bool nonfatalInREPL) { + SmallString<64> modulePathStr; + llvm::interleave(modulePath, [&](ImportPath::Element elem) { + modulePathStr += elem.Item.str(); + }, + [&] { modulePathStr += "."; }); + + auto diagKind = diag::sema_no_import; + if (nonfatalInREPL && ctx.LangOpts.DebuggerSupport) + diagKind = diag::sema_no_import_repl; + ctx.Diags.diagnose(importLoc, diagKind, modulePathStr); + + if (ctx.SearchPathOpts.SDKPath.empty() && + llvm::Triple(llvm::sys::getProcessTriple()).isMacOSX()) { + ctx.Diags.diagnose(SourceLoc(), diag::sema_no_import_no_sdk); + ctx.Diags.diagnose(SourceLoc(), diag::sema_no_import_no_sdk_xcrun); + } +} + ImplicitImportList ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, ModuleDecl *module) const { @@ -422,27 +443,22 @@ ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, } // Add any modules we were asked to implicitly import. - for (auto moduleName : importInfo.ModuleNames) { - auto *importModule = ctx.getModuleByIdentifier(moduleName); + for (auto unloadedImport : importInfo.AdditionalUnloadedImports) { + auto *importModule = ctx.getModule(unloadedImport.module.getModulePath()); if (!importModule) { - ctx.Diags.diagnose(SourceLoc(), diag::sema_no_import, moduleName.str()); - if (ctx.SearchPathOpts.SDKPath.empty() && - llvm::Triple(llvm::sys::getProcessTriple()).isMacOSX()) { - ctx.Diags.diagnose(SourceLoc(), diag::sema_no_import_no_sdk); - ctx.Diags.diagnose(SourceLoc(), diag::sema_no_import_no_sdk_xcrun); - } + diagnoseNoSuchModule(ctx, SourceLoc(), + unloadedImport.module.getModulePath(), + /*nonfatalInREPL=*/false); continue; } - ImportedModule import(ImportPath::Access(), importModule); - imports.emplace_back(import, ImportOptions()); + ImportedModule import(unloadedImport.module.getAccessPath(), importModule); + imports.emplace_back(import, unloadedImport.options, + unloadedImport.sourceFileArg, + unloadedImport.spiGroups); } // Add any pre-loaded modules. - for (auto &module : importInfo.AdditionalModules) { - ImportedModule import(ImportPath::Access(), module.first); - imports.emplace_back(import, module.second ? ImportFlags::Exported - : ImportOptions()); - } + llvm::copy(importInfo.AdditionalImports, std::back_inserter(imports)); auto *clangImporter = static_cast(ctx.getClangModuleLoader()); @@ -547,25 +563,8 @@ bool UnboundImport::checkModuleLoaded(ModuleDecl *M, SourceFile &SF) { if (M) return true; - ASTContext &ctx = SF.getASTContext(); - - SmallString<64> modulePathStr; - llvm::interleave(import.module.getModulePath(), - [&](ImportPath::Element elem) { - modulePathStr += elem.Item.str(); - }, - [&] { modulePathStr += "."; }); - - auto diagKind = diag::sema_no_import; - if (ctx.LangOpts.DebuggerSupport) - diagKind = diag::sema_no_import_repl; - ctx.Diags.diagnose(importLoc, diagKind, modulePathStr); - - if (ctx.SearchPathOpts.SDKPath.empty() && - llvm::Triple(llvm::sys::getProcessTriple()).isMacOSX()) { - ctx.Diags.diagnose(SourceLoc(), diag::sema_no_import_no_sdk); - ctx.Diags.diagnose(SourceLoc(), diag::sema_no_import_no_sdk_xcrun); - } + diagnoseNoSuchModule(SF.getASTContext(), importLoc, + import.module.getModulePath(), /*nonfatalInREPL=*/true); return false; } diff --git a/lib/Serialization/ModuleDependencyScanner.cpp b/lib/Serialization/ModuleDependencyScanner.cpp index 600744840648e..f4041c1f0e85e 100644 --- a/lib/Serialization/ModuleDependencyScanner.cpp +++ b/lib/Serialization/ModuleDependencyScanner.cpp @@ -149,8 +149,8 @@ ErrorOr ModuleDependencyScanner::scanInterfaceFile( // Collect implicitly imported modules in case they are not explicitly // printed in the interface file, e.g. SwiftOnoneSupport. auto &imInfo = mainMod->getImplicitImportInfo(); - for (auto name: imInfo.ModuleNames) { - Result->addModuleDependency(name.str(), &alreadyAddedModules); + for (auto import: imInfo.AdditionalUnloadedImports) { + Result->addModuleDependency(import.module.getModulePath().front().Item.str(), &alreadyAddedModules); } return std::error_code(); }); From d02b34cccc3edf3fece4c112bc8637ed94b1d407 Mon Sep 17 00:00:00 2001 From: Brent Royal-Gordon Date: Sat, 12 Sep 2020 23:26:21 -0700 Subject: [PATCH 08/13] [NFC] Add conveniences to clean up import code --- include/swift/AST/Import.h | 30 ++++++++++++++++++- include/swift/AST/ModuleDependencies.h | 7 +++++ lib/AST/ASTDumper.cpp | 6 +--- lib/AST/ModuleDependencies.cpp | 3 +- lib/AST/ModuleNameLookup.cpp | 3 +- lib/AST/TypeCheckRequests.cpp | 18 +++++------ lib/FrontendTool/ScanDependencies.cpp | 2 +- lib/IDE/REPLCodeCompletion.cpp | 7 ++--- lib/Sema/ImportResolution.cpp | 29 ++++++------------ lib/Serialization/ModuleDependencyScanner.cpp | 2 +- 10 files changed, 60 insertions(+), 47 deletions(-) diff --git a/include/swift/AST/Import.h b/include/swift/AST/Import.h index 5f1b582157f20..af88ac2760dbd 100644 --- a/include/swift/AST/Import.h +++ b/include/swift/AST/Import.h @@ -28,6 +28,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" #include namespace swift { @@ -151,6 +152,17 @@ namespace detail { if (empty()) return SourceRange(); return SourceRange(raw.front().Loc, raw.back().Loc); } + + void print(llvm::raw_ostream &os) const { + llvm::interleave(*this, + [&](Element elem) { os << elem.Item.str(); }, + [&]() { os << "."; }); + } + + void getString(SmallVectorImpl &modulePathStr) const { + llvm::raw_svector_ostream os(modulePathStr); + print(os); + } }; // These shims avoid circularity between ASTContext.h and Import.h. @@ -479,6 +491,9 @@ struct alignas(uint64_t) ImportedModule { assert(this->importedModule); } + explicit ImportedModule(ModuleDecl *importedModule) + : ImportedModule(ImportPath::Access(), importedModule) { } + bool operator==(const ImportedModule &other) const { return (this->importedModule == other.importedModule) && (this->accessPath == other.accessPath); @@ -490,6 +505,10 @@ struct alignas(uint64_t) ImportedModule { /// The order of items in \p imports is \e not preserved. static void removeDuplicates(SmallVectorImpl &imports); + // Purely here to allow ImportedModule and UnloadedImportedModule to + // substitute into the same templates. + ImportPath::Access getAccessPath() const { return accessPath; } + /// Arbitrarily orders ImportedModule records, for inclusion in sets and such. class Order { public: @@ -524,7 +543,7 @@ struct AttributedImport { /// Names of explicitly imported SPI groups. ArrayRef spiGroups; - AttributedImport(ModuleInfo module, ImportOptions options, + AttributedImport(ModuleInfo module, ImportOptions options = ImportOptions(), StringRef filename = {}, ArrayRef spiGroups = {}) : module(module), options(options), sourceFileArg(filename), spiGroups(spiGroups) { @@ -533,6 +552,11 @@ struct AttributedImport { options.contains(ImportFlags::Reserved)); } + template + AttributedImport(ModuleInfo module, AttributedImport other) + : AttributedImport(module, other.options, other.sourceFileArg, + other.spiGroups) { } + friend bool operator==(const AttributedImport &lhs, const AttributedImport &rhs) { return lhs.module == rhs.module && @@ -540,6 +564,10 @@ struct AttributedImport { lhs.sourceFileArg == rhs.sourceFileArg && lhs.spiGroups == rhs.spiGroups; } + + AttributedImport getLoaded(ModuleDecl *loadedModule) const { + return { ImportedModule(module.getAccessPath(), loadedModule), *this }; + } }; /// A module which has been implicitly imported. diff --git a/include/swift/AST/ModuleDependencies.h b/include/swift/AST/ModuleDependencies.h index 5eab3844b32d8..8d4af0907bf96 100644 --- a/include/swift/AST/ModuleDependencies.h +++ b/include/swift/AST/ModuleDependencies.h @@ -19,6 +19,7 @@ #define SWIFT_AST_MODULE_DEPENDENCIES_H #include "swift/Basic/LLVM.h" +#include "swift/AST/Import.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringSet.h" @@ -330,6 +331,12 @@ class ModuleDependencies { void addModuleDependency(StringRef module, llvm::StringSet<> *alreadyAddedModules = nullptr); + /// Add a dependency on the given module, if it was not already in the set. + void addModuleDependency(ImportPath::Module module, + llvm::StringSet<> *alreadyAddedModules = nullptr) { + addModuleDependency(module.front().Item.str(), alreadyAddedModules); + } + /// Add all of the module dependencies for the imports in the given source /// file to the set of module dependencies. void addModuleDependencies(const SourceFile &sf, diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index aff01f211fce0..b466124e24034 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -620,11 +620,7 @@ namespace { OS << " kind=" << getImportKindString(ID->getImportKind()); OS << " '"; - llvm::interleave(ID->getImportPath(), - [&](const ImportPath::Element &Elem) { - OS << Elem.Item; - }, - [&] { OS << '.'; }); + ID->getImportPath().print(OS); OS << "')"; } diff --git a/lib/AST/ModuleDependencies.cpp b/lib/AST/ModuleDependencies.cpp index 45821a23424a8..c6b2bfaac066a 100644 --- a/lib/AST/ModuleDependencies.cpp +++ b/lib/AST/ModuleDependencies.cpp @@ -62,8 +62,7 @@ void ModuleDependencies::addModuleDependencies( if (!importDecl) continue; - addModuleDependency(importDecl->getModulePath().front().Item.str(), - &alreadyAddedModules); + addModuleDependency(importDecl->getModulePath(), &alreadyAddedModules); } auto fileName = sf.getFilename(); diff --git a/lib/AST/ModuleNameLookup.cpp b/lib/AST/ModuleNameLookup.cpp index 56ea9383c6d29..16c9d96a87c8e 100644 --- a/lib/AST/ModuleNameLookup.cpp +++ b/lib/AST/ModuleNameLookup.cpp @@ -202,8 +202,7 @@ void ModuleNameLookup::lookupInModule( if (auto *loader = ctx.getClangModuleLoader()) { headerImportModule = loader->getImportedHeaderModule(); if (headerImportModule) { - ImportedModule import{ImportPath::Access(), headerImportModule}; - visitImport(import, nullptr); + visitImport(ImportedModule(headerImportModule), nullptr); } } } diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index feb1f4087388f..2bbdbe27dca3c 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -1395,14 +1395,14 @@ void swift::simple_display(llvm::raw_ostream &out, const AttributedImport &import) { out << "import of "; - if (!import.module.accessPath.empty()) { - simple_display(out, import.module.accessPath.front().Item); - out << " in "; - } - simple_display(out, import.module.importedModule); out << " ["; + if (!import.module.accessPath.empty()) { + out << " scoped("; + import.module.accessPath.print(out); + out << ")"; + } if (import.options.contains(ImportFlags::Exported)) out << " exported"; if (import.options.contains(ImportFlags::Testable)) @@ -1414,11 +1414,9 @@ void swift::simple_display(llvm::raw_ostream &out, if (import.options.contains(ImportFlags::SPIAccessControl)) { out << " spi("; - llvm::interleave(import.spiGroups, - [&out](Identifier name) { - simple_display(out, name); - }, - [&out]() { out << " "; }); + llvm::interleaveComma(import.spiGroups, out, [&out](Identifier name) { + simple_display(out, name); + }); out << ")"; } diff --git a/lib/FrontendTool/ScanDependencies.cpp b/lib/FrontendTool/ScanDependencies.cpp index ede07f9064085..8ab5f040d1a4e 100644 --- a/lib/FrontendTool/ScanDependencies.cpp +++ b/lib/FrontendTool/ScanDependencies.cpp @@ -818,7 +818,7 @@ bool swift::scanDependencies(CompilerInstance &instance) { // Add any implicit module names. for (const auto &import : importInfo.AdditionalUnloadedImports) { - mainDependencies.addModuleDependency(import.module.getModulePath().front().Item.str(), &alreadyAddedModules); + mainDependencies.addModuleDependency(import.module.getModulePath(), &alreadyAddedModules); } // Already-loaded, implicitly imported module names. diff --git a/lib/IDE/REPLCodeCompletion.cpp b/lib/IDE/REPLCodeCompletion.cpp index 52566e24297a9..02cdd4d82078b 100644 --- a/lib/IDE/REPLCodeCompletion.cpp +++ b/lib/IDE/REPLCodeCompletion.cpp @@ -221,17 +221,14 @@ doCodeCompletion(SourceFile &SF, StringRef EnteredCode, unsigned *BufferID, auto *lastModule = SF.getParentModule(); ImplicitImportInfo implicitImports; - { - ImportedModule import(ImportPath::Access(), lastModule); - implicitImports.AdditionalImports.emplace_back(import, ImportOptions()); - } + implicitImports.AdditionalImports.emplace_back(ImportedModule(lastModule)); // Carry over the private imports from the last module. SmallVector imports; lastModule->getImportedModules(imports, ModuleDecl::ImportFilterKind::Default); for (auto &import : imports) { - implicitImports.AdditionalImports.emplace_back(import, ImportOptions()); + implicitImports.AdditionalImports.emplace_back(import); } // Create a new module and file for the code completion buffer, similar to how diff --git a/lib/Sema/ImportResolution.cpp b/lib/Sema/ImportResolution.cpp index 87aff0cb51056..a406472748240 100644 --- a/lib/Sema/ImportResolution.cpp +++ b/lib/Sema/ImportResolution.cpp @@ -118,8 +118,7 @@ struct UnboundImport { /// UnboundImport. AttributedImport makeAttributedImport(ModuleDecl *module) const { - return { ImportedModule{ import.module.getAccessPath(), module }, - import.options, import.sourceFileArg, import.spiGroups }; + return import.getLoaded(module); } private: @@ -396,10 +395,7 @@ static void diagnoseNoSuchModule(ASTContext &ctx, SourceLoc importLoc, ImportPath::Module modulePath, bool nonfatalInREPL) { SmallString<64> modulePathStr; - llvm::interleave(modulePath, [&](ImportPath::Element elem) { - modulePathStr += elem.Item.str(); - }, - [&] { modulePathStr += "."; }); + modulePath.getString(modulePathStr); auto diagKind = diag::sema_no_import; if (nonfatalInREPL && ctx.LangOpts.DebuggerSupport) @@ -430,17 +426,14 @@ ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, case ImplicitStdlibKind::Builtin: stdlib = ctx.TheBuiltinModule; break; - case ImplicitStdlibKind::Stdlib: { + case ImplicitStdlibKind::Stdlib: stdlib = ctx.getStdlibModule(/*loadIfAbsent*/ true); assert(stdlib && "Missing stdlib?"); break; } - } - if (stdlib) { - ImportedModule import(ImportPath::Access(), stdlib); - imports.emplace_back(import, ImportOptions()); - } + if (stdlib) + imports.emplace_back(ImportedModule(stdlib)); // Add any modules we were asked to implicitly import. for (auto unloadedImport : importInfo.AdditionalUnloadedImports) { @@ -451,10 +444,7 @@ ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, /*nonfatalInREPL=*/false); continue; } - ImportedModule import(unloadedImport.module.getAccessPath(), importModule); - imports.emplace_back(import, unloadedImport.options, - unloadedImport.sourceFileArg, - unloadedImport.spiGroups); + imports.push_back(unloadedImport.getLoaded(importModule)); } // Add any pre-loaded modules. @@ -469,8 +459,7 @@ ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, !clangImporter->importBridgingHeader(bridgingHeaderPath, module)) { auto *headerModule = clangImporter->getImportedHeaderModule(); assert(headerModule && "Didn't load bridging header?"); - ImportedModule import(ImportPath::Access(), headerModule); - imports.emplace_back(import, ImportFlags::Exported); + imports.emplace_back(ImportedModule(headerModule), ImportFlags::Exported); } // Implicitly import the underlying Clang half of this module if needed. @@ -478,8 +467,8 @@ ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, auto *underlyingMod = clangImporter->loadModule( SourceLoc(), ImportPath::Module::Builder(module->getName()).get()); if (underlyingMod) { - ImportedModule import(ImportPath::Access(), underlyingMod); - imports.emplace_back(import, ImportFlags::Exported); + imports.emplace_back(ImportedModule(underlyingMod), + ImportFlags::Exported); } else { ctx.Diags.diagnose(SourceLoc(), diag::error_underlying_module_not_found, module->getName()); diff --git a/lib/Serialization/ModuleDependencyScanner.cpp b/lib/Serialization/ModuleDependencyScanner.cpp index f4041c1f0e85e..4e211d525dbe1 100644 --- a/lib/Serialization/ModuleDependencyScanner.cpp +++ b/lib/Serialization/ModuleDependencyScanner.cpp @@ -150,7 +150,7 @@ ErrorOr ModuleDependencyScanner::scanInterfaceFile( // printed in the interface file, e.g. SwiftOnoneSupport. auto &imInfo = mainMod->getImplicitImportInfo(); for (auto import: imInfo.AdditionalUnloadedImports) { - Result->addModuleDependency(import.module.getModulePath().front().Item.str(), &alreadyAddedModules); + Result->addModuleDependency(import.module.getModulePath(), &alreadyAddedModules); } return std::error_code(); }); From 7f14affda09fb57414fa7d0203a886845dbd47fc Mon Sep 17 00:00:00 2001 From: Brent Royal-Gordon Date: Fri, 25 Sep 2020 11:02:28 -0700 Subject: [PATCH 09/13] [NFC] Give NullablePtr some PointerLikeTypeTraits Allows it to be used in PointerIntPair and PointerUnion. --- include/swift/Basic/NullablePtr.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/swift/Basic/NullablePtr.h b/include/swift/Basic/NullablePtr.h index 316cfbb46251f..75a81eb9a1924 100644 --- a/include/swift/Basic/NullablePtr.h +++ b/include/swift/Basic/NullablePtr.h @@ -20,6 +20,7 @@ #include #include #include +#include "llvm/Support/PointerLikeTypeTraits.h" namespace swift { /// NullablePtr pointer wrapper - NullablePtr is used for APIs where a @@ -81,4 +82,19 @@ class NullablePtr { } // end namespace swift +namespace llvm { +template struct PointerLikeTypeTraits; +template struct PointerLikeTypeTraits> { +public: + static inline void *getAsVoidPointer(swift::NullablePtr ptr) { + return static_cast(ptr.getPtrOrNull()); + } + static inline swift::NullablePtr getFromVoidPointer(void *ptr) { + return swift::NullablePtr(static_cast(ptr)); + } + enum { NumLowBitsAvailable = PointerLikeTypeTraits::NumLowBitsAvailable }; +}; + +} + #endif // SWIFT_BASIC_NULLABLEPTR_H From bf074b093ea9b8ef4dcb90a5494343edbef39939 Mon Sep 17 00:00:00 2001 From: Brent Royal-Gordon Date: Fri, 25 Sep 2020 17:32:16 -0700 Subject: [PATCH 10/13] Run some implicit imports through import resolution Unloaded implicit imports (e.g. the `-import-module` flag) will now be processed by import resolution, and will be fully validated and cross-imported. Preloaded imports, like the standard library import, are still not run through full import resolution, but this is a definite improvement over the status quo. This also folds `-import-underlying-module` and `@_exported import ` into a single code path, slightly changing the diagnostic for a failed overlay-style underlying module import. --- include/swift/AST/Import.h | 8 +- lib/AST/TypeCheckRequests.cpp | 38 +++++++ lib/Sema/ImportResolution.cpp | 102 +++++++++++------- .../mixed-target-using-module.swift | 8 ++ test/CrossImport/common-case.swift | 5 +- 5 files changed, 121 insertions(+), 40 deletions(-) diff --git a/include/swift/AST/Import.h b/include/swift/AST/Import.h index af88ac2760dbd..ebcfc38369e19 100644 --- a/include/swift/AST/Import.h +++ b/include/swift/AST/Import.h @@ -574,6 +574,10 @@ struct AttributedImport { void simple_display(llvm::raw_ostream &out, const AttributedImport &import); +/// A module which will be implicitly imported. +void simple_display(llvm::raw_ostream &out, + const AttributedImport &import); + // MARK: - Implicit imports /// The kind of stdlib that should be imported. @@ -617,10 +621,12 @@ struct ImplicitImportInfo { /// Contains names of and pointers to modules that must be implicitly imported. struct ImplicitImportList { ArrayRef> imports; + ArrayRef> unloadedImports; friend bool operator==(const ImplicitImportList &lhs, const ImplicitImportList &rhs) { - return lhs.imports == rhs.imports; + return lhs.imports == rhs.imports + && lhs.unloadedImports == rhs.unloadedImports; } }; diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index 2bbdbe27dca3c..5087a6d5a4501 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -1423,12 +1423,50 @@ void swift::simple_display(llvm::raw_ostream &out, out << " ]"; } +void swift::simple_display(llvm::raw_ostream &out, + const AttributedImport &import) { + out << "import of unloaded "; + + import.module.getModulePath().print(out); + + out << " ["; + if (!import.module.getAccessPath().empty()) { + out << " scoped("; + import.module.getAccessPath().print(out); + out << ")"; + } + if (import.options.contains(ImportFlags::Exported)) + out << " exported"; + if (import.options.contains(ImportFlags::Testable)) + out << " testable"; + if (import.options.contains(ImportFlags::ImplementationOnly)) + out << " implementation-only"; + if (import.options.contains(ImportFlags::PrivateImport)) + out << " private(" << import.sourceFileArg << ")"; + + if (import.options.contains(ImportFlags::SPIAccessControl)) { + out << " spi("; + llvm::interleaveComma(import.spiGroups, out, [&out](Identifier name) { + simple_display(out, name); + }); + out << ")"; + } + + out << " ]"; +} + void swift::simple_display(llvm::raw_ostream &out, const ImplicitImportList &importList) { llvm::interleaveComma(importList.imports, out, [&](const auto &import) { simple_display(out, import); }); + if (!importList.imports.empty() && !importList.unloadedImports.empty()) + out << ", "; + llvm::interleaveComma(importList.unloadedImports, out, + [&](const auto &import) { + simple_display(out, import); + }); } //----------------------------------------------------------------------------// diff --git a/lib/Sema/ImportResolution.cpp b/lib/Sema/ImportResolution.cpp index a406472748240..017fe84c4e5f6 100644 --- a/lib/Sema/ImportResolution.cpp +++ b/lib/Sema/ImportResolution.cpp @@ -65,11 +65,12 @@ struct UnboundImport { /// /// If this UnboundImport represents a cross-import, contains the declaring /// module's \c ModuleDecl. - PointerUnion importOrUnderlyingModuleDecl; + PointerUnion, ModuleDecl *> + importOrUnderlyingModuleDecl; NullablePtr getImportDecl() const { - return importOrUnderlyingModuleDecl.is() ? - importOrUnderlyingModuleDecl.get() : nullptr; + return importOrUnderlyingModuleDecl.is>() ? + importOrUnderlyingModuleDecl.get>() : nullptr; } NullablePtr getUnderlyingModule() const { @@ -80,6 +81,9 @@ struct UnboundImport { /// Create an UnboundImport for a user-written import declaration. explicit UnboundImport(ImportDecl *ID); + /// Create an UnboundImport for an unloaded implicit import. + explicit UnboundImport(AttributedImport implicit); + /// Create an UnboundImport for a cross-import overlay. explicit UnboundImport(ASTContext &ctx, const UnboundImport &base, Identifier overlayName, @@ -192,6 +196,9 @@ class ImportResolver final : public DeclVisitor { return ctx.Diags.diagnose(std::forward(Args)...); } + /// Calls \c bindImport() on unbound imports until \c boundImports is drained. + void bindPendingImports(); + /// Check a single unbound import, bind it, add it to \c boundImports, /// and add its cross-import overlays to \c unboundImports. void bindImport(UnboundImport &&I); @@ -284,6 +291,10 @@ void ImportResolver::visitImportDecl(ImportDecl *ID) { assert(unboundImports.empty()); unboundImports.emplace_back(ID); + bindPendingImports(); +} + +void ImportResolver::bindPendingImports() { while(!unboundImports.empty()) bindImport(unboundImports.pop_back_val()); } @@ -336,14 +347,16 @@ void ImportResolver::addImport(const UnboundImport &I, ModuleDecl *M) { // MARK: Import module loading //===----------------------------------------------------------------------===// -ModuleDecl * -ImportResolver::getModule(ImportPath::Module modulePath) { +static ModuleDecl * +getModuleImpl(ImportPath::Module modulePath, ModuleDecl *loadingModule, + bool canImportBuiltin) { + ASTContext &ctx = loadingModule->getASTContext(); + assert(!modulePath.empty()); auto moduleID = modulePath[0]; // The Builtin module cannot be explicitly imported unless we're a .sil file. - if (SF.Kind == SourceFileKind::SIL && - moduleID.Item == ctx.TheBuiltinModule->getName()) + if (canImportBuiltin && moduleID.Item == ctx.TheBuiltinModule->getName()) return ctx.TheBuiltinModule; // If the imported module name is the same as the current module, @@ -352,8 +365,7 @@ ImportResolver::getModule(ImportPath::Module modulePath) { // // FIXME: We'd like to only use this in SIL mode, but unfortunately we use it // for clang overlays as well. - if (moduleID.Item == SF.getParentModule()->getName() && - modulePath.size() == 1) { + if (moduleID.Item == loadingModule->getName() && modulePath.size() == 1) { if (auto importer = ctx.getClangModuleLoader()) return importer->loadModule(moduleID.Loc, modulePath); return nullptr; @@ -362,6 +374,12 @@ ImportResolver::getModule(ImportPath::Module modulePath) { return ctx.getModule(modulePath); } +ModuleDecl * +ImportResolver::getModule(ImportPath::Module modulePath) { + return getModuleImpl(modulePath, SF.getParentModule(), + /*canImportBuiltin=*/SF.Kind == SourceFileKind::SIL); +} + NullablePtr UnboundImport::getTopLevelModule(ModuleDecl *M, SourceFile &SF) { if (import.module.getModulePath().size() == 1) @@ -391,16 +409,25 @@ UnboundImport::getTopLevelModule(ModuleDecl *M, SourceFile &SF) { // MARK: Implicit imports //===----------------------------------------------------------------------===// -static void diagnoseNoSuchModule(ASTContext &ctx, SourceLoc importLoc, +static void diagnoseNoSuchModule(ModuleDecl *importingModule, + SourceLoc importLoc, ImportPath::Module modulePath, bool nonfatalInREPL) { - SmallString<64> modulePathStr; - modulePath.getString(modulePathStr); - - auto diagKind = diag::sema_no_import; - if (nonfatalInREPL && ctx.LangOpts.DebuggerSupport) - diagKind = diag::sema_no_import_repl; - ctx.Diags.diagnose(importLoc, diagKind, modulePathStr); + ASTContext &ctx = importingModule->getASTContext(); + + if (modulePath.size() == 1 && + importingModule->getName() == modulePath.front().Item) { + ctx.Diags.diagnose(importLoc, diag::error_underlying_module_not_found, + importingModule->getName()); + } else { + SmallString<64> modulePathStr; + modulePath.getString(modulePathStr); + + auto diagKind = diag::sema_no_import; + if (nonfatalInREPL && ctx.LangOpts.DebuggerSupport) + diagKind = diag::sema_no_import_repl; + ctx.Diags.diagnose(importLoc, diagKind, modulePathStr); + } if (ctx.SearchPathOpts.SDKPath.empty() && llvm::Triple(llvm::sys::getProcessTriple()).isMacOSX()) { @@ -413,6 +440,7 @@ ImplicitImportList ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, ModuleDecl *module) const { SmallVector, 4> imports; + SmallVector, 4> unloadedImports; auto &ctx = module->getASTContext(); auto &importInfo = module->getImplicitImportInfo(); @@ -436,16 +464,8 @@ ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, imports.emplace_back(ImportedModule(stdlib)); // Add any modules we were asked to implicitly import. - for (auto unloadedImport : importInfo.AdditionalUnloadedImports) { - auto *importModule = ctx.getModule(unloadedImport.module.getModulePath()); - if (!importModule) { - diagnoseNoSuchModule(ctx, SourceLoc(), - unloadedImport.module.getModulePath(), - /*nonfatalInREPL=*/false); - continue; - } - imports.push_back(unloadedImport.getLoaded(importModule)); - } + llvm::copy(importInfo.AdditionalUnloadedImports, + std::back_inserter(unloadedImports)); // Add any pre-loaded modules. llvm::copy(importInfo.AdditionalImports, std::back_inserter(imports)); @@ -464,18 +484,15 @@ ModuleImplicitImportsRequest::evaluate(Evaluator &evaluator, // Implicitly import the underlying Clang half of this module if needed. if (importInfo.ShouldImportUnderlyingModule) { - auto *underlyingMod = clangImporter->loadModule( - SourceLoc(), ImportPath::Module::Builder(module->getName()).get()); - if (underlyingMod) { - imports.emplace_back(ImportedModule(underlyingMod), - ImportFlags::Exported); - } else { - ctx.Diags.diagnose(SourceLoc(), diag::error_underlying_module_not_found, - module->getName()); - } + // An @_exported self-import is loaded from ClangImporter instead of being + // rejected; see the special case in getModuleImpl() for details. + ImportPath::Builder importPath(module->getName()); + unloadedImports.emplace_back(UnloadedImportedModule(importPath.copyTo(ctx), + /*isScoped=*/false), + ImportFlags::Exported); } - return { ctx.AllocateCopy(imports) }; + return { ctx.AllocateCopy(imports), ctx.AllocateCopy(unloadedImports) }; } void ImportResolver::addImplicitImports() { @@ -487,8 +504,17 @@ void ImportResolver::addImplicitImports() { import.module.importedModule->isStdlibModule())); boundImports.push_back(import); } + + for (auto &unloadedImport : implicitImports.unloadedImports) + unboundImports.emplace_back(unloadedImport); + + bindPendingImports(); } +UnboundImport::UnboundImport(AttributedImport implicit) + : import(implicit), importLoc(), + importOrUnderlyingModuleDecl(static_cast(nullptr)) {} + //===----------------------------------------------------------------------===// // MARK: Import validation (except for scoped imports) //===----------------------------------------------------------------------===// @@ -552,7 +578,7 @@ bool UnboundImport::checkModuleLoaded(ModuleDecl *M, SourceFile &SF) { if (M) return true; - diagnoseNoSuchModule(SF.getASTContext(), importLoc, + diagnoseNoSuchModule(SF.getParentModule(), importLoc, import.module.getModulePath(), /*nonfatalInREPL=*/true); return false; } diff --git a/test/ClangImporter/MixedSource/mixed-target-using-module.swift b/test/ClangImporter/MixedSource/mixed-target-using-module.swift index 0c007f6dd7895..7cacecc69c4fd 100644 --- a/test/ClangImporter/MixedSource/mixed-target-using-module.swift +++ b/test/ClangImporter/MixedSource/mixed-target-using-module.swift @@ -1,6 +1,14 @@ // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -F %S/Inputs/mixed-target/ -module-name Mixed -import-underlying-module -typecheck %s -verify -enable-objc-interop -disable-objc-attr-requires-foundation-module // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -F %S/Inputs/mixed-target/ -module-name Mixed -import-underlying-module -enable-objc-interop -emit-ir %S/../../Inputs/empty.swift | %FileCheck -check-prefix=CHECK-AUTOLINK %s +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -F %S/Inputs/mixed-target/ -module-name Mixed -DOVERLAY_STYLE_RIGHT -enable-objc-interop -emit-ir %S/../../Inputs/empty.swift | %FileCheck -check-prefix=CHECK-AUTOLINK %s // RUN: not %target-swift-frontend(mock-sdk: %clang-importer-sdk) -F %S/Inputs/mixed-target/ -module-name WrongName -import-underlying-module -typecheck %s -enable-objc-interop -disable-objc-attr-requires-foundation-module 2>&1 | %FileCheck -check-prefix=CHECK-WRONG-NAME %s +// RUN: not %target-swift-frontend(mock-sdk: %clang-importer-sdk) -F %S/Inputs/mixed-target/ -module-name WrongName -DOVERLAY_STYLE_WRONG -typecheck %s -enable-objc-interop -disable-objc-attr-requires-foundation-module 2>&1 | %FileCheck -check-prefix=CHECK-WRONG-NAME %s + +#if OVERLAY_STYLE_RIGHT +@_exported import Mixed +#elseif OVERLAY_STYLE_WRONG +@_exported import WrongName +#endif // CHECK-AUTOLINK: !llvm.linker.options = !{ // CHECK-AUTOLINK-NOT: !"-framework" diff --git a/test/CrossImport/common-case.swift b/test/CrossImport/common-case.swift index f29a547e6004e..7ac70d60823cf 100644 --- a/test/CrossImport/common-case.swift +++ b/test/CrossImport/common-case.swift @@ -5,10 +5,13 @@ // RUN: cp -r %S/Inputs/lib-templates/* %t/ // RUN: %{python} %S/Inputs/rewrite-module-triples.py %t %module-target-triple -// RUN: %target-typecheck-verify-swift -enable-cross-import-overlays -I %t/include -I %t/lib/swift -F %t/Frameworks +// RUN: %target-typecheck-verify-swift -enable-cross-import-overlays -DIMPORT_BYSTANDING_LIBRARY -I %t/include -I %t/lib/swift -F %t/Frameworks +// RUN: %target-typecheck-verify-swift -enable-cross-import-overlays -import-module BystandingLibrary -I %t/include -I %t/lib/swift -F %t/Frameworks // Each framework has a cross-import overlay with this library: +#if IMPORT_BYSTANDING_LIBRARY import BystandingLibrary +#endif // 1. A Swift framework From f71923778b6ddbb50500744e1460bca96ea35ff5 Mon Sep 17 00:00:00 2001 From: Brent Royal-Gordon Date: Sun, 13 Sep 2020 17:05:44 -0700 Subject: [PATCH 11/13] Add -testable-import-module frontend flag This is just like -import-module, but it does an @testable import. Simple, right? Fixes rdar://66544654. --- include/swift/Frontend/FrontendOptions.h | 6 ++++-- include/swift/Option/FrontendOptions.td | 3 +++ lib/Frontend/ArgsToFrontendOptionsConverter.cpp | 10 ++++++---- lib/Frontend/ArgsToFrontendOptionsConverter.h | 3 ++- lib/Frontend/Frontend.cpp | 11 +++++++---- test/ImportResolution/import-command-line.swift | 3 +++ .../lib/SwiftLang/CodeCompletionOrganizer.cpp | 4 ++-- 7 files changed, 27 insertions(+), 13 deletions(-) diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index dc0dff3c449f2..66fdcc94afefd 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -34,7 +34,8 @@ class FrontendOptions { friend class ArgsToFrontendOptionsConverter; /// A list of arbitrary modules to import and make implicitly visible. - std::vector ImplicitImportModuleNames; + std::vector> + ImplicitImportModuleNames; public: FrontendInputsAndOutputs InputsAndOutputs; @@ -351,7 +352,8 @@ class FrontendOptions { /// Retrieves the list of arbitrary modules to import and make implicitly /// visible. - ArrayRef getImplicitImportModuleNames() const { + ArrayRef> + getImplicitImportModuleNames() const { return ImplicitImportModuleNames; } diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index fe6e53afe9c98..8c2a727c4947b 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -512,6 +512,9 @@ def enable_throw_without_try : Flag<["-"], "enable-throw-without-try">, def import_module : Separate<["-"], "import-module">, HelpText<"Implicitly import the specified module">; +def testable_import_module : Separate<["-"], "testable-import-module">, + HelpText<"Implicitly import the specified module with @testable">; + def print_stats : Flag<["-"], "print-stats">, HelpText<"Print various statistics">; diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index 8634d26296f1c..43c131981211a 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -215,7 +215,8 @@ bool ArgsToFrontendOptionsConverter::convert( Opts.DisableBuildingInterface = Args.hasArg(OPT_disable_building_interface); computeImportObjCHeaderOptions(); - computeImplicitImportModuleNames(); + computeImplicitImportModuleNames(OPT_import_module, /*isTestable=*/false); + computeImplicitImportModuleNames(OPT_testable_import_module, /*isTestable=*/true); computeLLVMArgs(); return false; @@ -586,16 +587,17 @@ void ArgsToFrontendOptionsConverter::computeImportObjCHeaderOptions() { Opts.SerializeBridgingHeader |= !Opts.InputsAndOutputs.hasPrimaryInputs(); } } -void ArgsToFrontendOptionsConverter::computeImplicitImportModuleNames() { +void ArgsToFrontendOptionsConverter:: +computeImplicitImportModuleNames(OptSpecifier id, bool isTestable) { using namespace options; - for (const Arg *A : Args.filtered(OPT_import_module)) { + for (const Arg *A : Args.filtered(id)) { auto *moduleStr = A->getValue(); if (!Lexer::isIdentifier(moduleStr)) { Diags.diagnose(SourceLoc(), diag::error_bad_module_name, moduleStr, /*suggestModuleNameFlag*/ false); continue; } - Opts.ImplicitImportModuleNames.push_back(moduleStr); + Opts.ImplicitImportModuleNames.emplace_back(moduleStr, isTestable); } } void ArgsToFrontendOptionsConverter::computeLLVMArgs() { diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.h b/lib/Frontend/ArgsToFrontendOptionsConverter.h index 6e20e3688a8fa..66d85512ff068 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.h +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.h @@ -40,7 +40,8 @@ class ArgsToFrontendOptionsConverter { bool computeMainAndSupplementaryOutputFilenames(); void computeDumpScopeMapLocations(); void computeHelpOptions(); - void computeImplicitImportModuleNames(); + void computeImplicitImportModuleNames(llvm::opt::OptSpecifier id, + bool isTestable); void computeImportObjCHeaderOptions(); void computeLLVMArgs(); void computePlaygroundOptions(); diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 4d661e604c62c..9601547de0193 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -740,15 +740,18 @@ ImplicitImportInfo CompilerInstance::getImplicitImportInfo() const { ImplicitImportInfo imports; imports.StdlibKind = Invocation.getImplicitStdlibKind(); - auto pushImport = [&](StringRef moduleStr) { + auto pushImport = [&](StringRef moduleStr, + ImportOptions options = ImportOptions()) { ImportPath::Builder importPath(Context->getIdentifier(moduleStr)); UnloadedImportedModule import(importPath.copyTo(*Context), /*isScoped=*/false); - imports.AdditionalUnloadedImports.emplace_back(import, ImportOptions()); + imports.AdditionalUnloadedImports.emplace_back(import, options); }; - for (auto &moduleStr : frontendOpts.getImplicitImportModuleNames()) { - pushImport(moduleStr); + for (auto &moduleStrAndTestable : frontendOpts.getImplicitImportModuleNames()) { + pushImport(moduleStrAndTestable.first, + moduleStrAndTestable.second ? ImportFlags::Testable + : ImportOptions()); } if (Invocation.shouldImportSwiftONoneSupport()) { diff --git a/test/ImportResolution/import-command-line.swift b/test/ImportResolution/import-command-line.swift index 8a305450578b5..1f0012bdefd4e 100644 --- a/test/ImportResolution/import-command-line.swift +++ b/test/ImportResolution/import-command-line.swift @@ -7,5 +7,8 @@ // RUN: not %target-swift-frontend -typecheck %s -enable-source-import -I %S/Inputs -sdk "" -import-module NON_EXISTENT 2>&1 | %FileCheck -check-prefix=NON-EXISTENT %s // NON-EXISTENT: error: no such module 'NON_EXISTENT' +// RUN: not %target-swift-frontend -typecheck %s -enable-source-import -I %S/Inputs -sdk "" -testable-import-module abcde 2>&1 | %FileCheck -check-prefix=NON-TESTABLE %s +// NON-TESTABLE: error: module 'abcde' was not compiled for testing + var a: A? // expected-error {{cannot find type 'A' in scope}} var qA: abcde.A? // expected-error {{cannot find type 'abcde' in scope}} diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp index 731ba21165ffa..0268272f6e1d5 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp @@ -347,9 +347,9 @@ ImportDepth::ImportDepth(ASTContext &context, // Imports from -import-name such as Playground auxiliary sources are treated // specially by applying import depth 0. llvm::StringSet<> auxImports; - for (StringRef moduleName : + for (const auto &pair : invocation.getFrontendOptions().getImplicitImportModuleNames()) - auxImports.insert(moduleName); + auxImports.insert(pair.first); // Private imports from this module. // FIXME: only the private imports from the current source file. From 48b866b8fe179faa49f2c407a9920f28539c496c Mon Sep 17 00:00:00 2001 From: Brent Royal-Gordon Date: Fri, 9 Oct 2020 17:47:40 -0700 Subject: [PATCH 12/13] [NFC] Compare spiGroups in DenseMapInfo This ought to result in more consistent behavior. --- include/swift/AST/Import.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/include/swift/AST/Import.h b/include/swift/AST/Import.h index ebcfc38369e19..1ee68596eb7f4 100644 --- a/include/swift/AST/Import.h +++ b/include/swift/AST/Import.h @@ -691,17 +691,20 @@ struct DenseMapInfo> { using ModuleInfoDMI = DenseMapInfo; using ImportOptionsDMI = DenseMapInfo; using StringRefDMI = DenseMapInfo; - // FIXME: SPI groups not used by DenseMapInfo??? + // We can't include spiGroups in the hash because ArrayRef is not + // DenseMapInfo-able, but we do check that the spiGroups match in isEqual(). static inline AttributedImport getEmptyKey() { return AttributedImport(ModuleInfoDMI::getEmptyKey(), ImportOptionsDMI::getEmptyKey(), - StringRefDMI::getEmptyKey()); + StringRefDMI::getEmptyKey(), + {}); } static inline AttributedImport getTombstoneKey() { return AttributedImport(ModuleInfoDMI::getTombstoneKey(), ImportOptionsDMI::getTombstoneKey(), - StringRefDMI::getTombstoneKey()); + StringRefDMI::getTombstoneKey(), + {}); } static inline unsigned getHashValue(const AttributedImport &import) { return detail::combineHashValue( @@ -714,7 +717,8 @@ struct DenseMapInfo> { const AttributedImport &b) { return ModuleInfoDMI::isEqual(a.module, b.module) && ImportOptionsDMI::isEqual(a.options, b.options) && - StringRefDMI::isEqual(a.sourceFileArg, b.sourceFileArg); + StringRefDMI::isEqual(a.sourceFileArg, b.sourceFileArg) && + a.spiGroups == b.spiGroups; } }; } From 944ad8845582e9de58745a99cf98dd9ced60864c Mon Sep 17 00:00:00 2001 From: Brent Royal-Gordon Date: Fri, 9 Oct 2020 18:10:40 -0700 Subject: [PATCH 13/13] [NFC] Improve simple_display for AttributedImport --- include/swift/AST/Import.h | 22 ++++++++++++--- lib/AST/TypeCheckRequests.cpp | 51 +++++++++++------------------------ 2 files changed, 34 insertions(+), 39 deletions(-) diff --git a/include/swift/AST/Import.h b/include/swift/AST/Import.h index 1ee68596eb7f4..b6a1f7a2d352a 100644 --- a/include/swift/AST/Import.h +++ b/include/swift/AST/Import.h @@ -570,13 +570,27 @@ struct AttributedImport { } }; -/// A module which has been implicitly imported. void simple_display(llvm::raw_ostream &out, - const AttributedImport &import); + const ImportedModule &import); -/// A module which will be implicitly imported. void simple_display(llvm::raw_ostream &out, - const AttributedImport &import); + const UnloadedImportedModule &import); + +// This is a quasi-implementation detail of the template version below. +void simple_display(llvm::raw_ostream &out, + const AttributedImport> &import); + +template +void simple_display(llvm::raw_ostream &out, + const AttributedImport &import) { + // Print the module. + simple_display(out, import.module); + + // Print the other details of the import, using the std::tuple<> + // specialization. + AttributedImport> importWithoutModule({}, import); + simple_display(out, importWithoutModule); +} // MARK: - Implicit imports diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index 5087a6d5a4501..fee1a29ea9d51 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -1392,49 +1392,30 @@ TypeCheckFunctionBodyRequest::readDependencySource( //----------------------------------------------------------------------------// void swift::simple_display(llvm::raw_ostream &out, - const AttributedImport &import) { + const ImportedModule &module) { out << "import of "; - - simple_display(out, import.module.importedModule); - - out << " ["; - if (!import.module.accessPath.empty()) { - out << " scoped("; - import.module.accessPath.print(out); - out << ")"; + if (!module.accessPath.empty()) { + module.accessPath.print(out); + out << " in "; } - if (import.options.contains(ImportFlags::Exported)) - out << " exported"; - if (import.options.contains(ImportFlags::Testable)) - out << " testable"; - if (import.options.contains(ImportFlags::ImplementationOnly)) - out << " implementation-only"; - if (import.options.contains(ImportFlags::PrivateImport)) - out << " private(" << import.sourceFileArg << ")"; + simple_display(out, module.importedModule); +} - if (import.options.contains(ImportFlags::SPIAccessControl)) { - out << " spi("; - llvm::interleaveComma(import.spiGroups, out, [&out](Identifier name) { - simple_display(out, name); - }); - out << ")"; +void swift::simple_display(llvm::raw_ostream &out, + const UnloadedImportedModule &module) { + out << "import of "; + if (!module.getAccessPath().empty()) { + module.getAccessPath().print(out); + out << " in "; } - - out << " ]"; + out << "unloaded "; + module.getModulePath().print(out); } void swift::simple_display(llvm::raw_ostream &out, - const AttributedImport &import) { - out << "import of unloaded "; - - import.module.getModulePath().print(out); - + const AttributedImport> &import) { out << " ["; - if (!import.module.getAccessPath().empty()) { - out << " scoped("; - import.module.getAccessPath().print(out); - out << ")"; - } + if (import.options.contains(ImportFlags::Exported)) out << " exported"; if (import.options.contains(ImportFlags::Testable))