From a68d8176a891a98e69162daedafd4ec61e279283 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Wed, 28 Jan 2026 14:26:10 -0800 Subject: [PATCH 1/2] [NFC] Tweak export_as test Duplicated set of commands, FileCheck use pattern that produces suboptimal diagnostics. --- .../export-as-in-swiftinterfaces.swift | 28 ++++++------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/test/ModuleInterface/export-as-in-swiftinterfaces.swift b/test/ModuleInterface/export-as-in-swiftinterfaces.swift index 58a816301f8..44d3087ca33 100644 --- a/test/ModuleInterface/export-as-in-swiftinterfaces.swift +++ b/test/ModuleInterface/export-as-in-swiftinterfaces.swift @@ -12,8 +12,8 @@ // RUN: -emit-module-interface-path %t/Exported.swiftinterface \ // RUN: -emit-private-module-interface-path %t/Exported.private.swiftinterface // RUN: %target-swift-typecheck-module-from-interface(%t/Exported.private.swiftinterface) -module-name Exported -I %t -// RUN: cat %t/Exported.swiftinterface | %FileCheck -check-prefix=CHECK-USE-EXPORTER %s -// RUN: cat %t/Exported.private.swiftinterface | %FileCheck -check-prefix=CHECK-USE-EXPORTED %s +// RUN: %FileCheck -input-file=%t/Exported.swiftinterface -check-prefix=CHECK-USE-EXPORTER %s +// RUN: %FileCheck -input-file=%t/Exported.private.swiftinterface -check-prefix=CHECK-USE-EXPORTED %s /// The public swiftinterface only builds under the name of Exporter. // RUN: sed -e "s/module-name Exported/module-name Exporter/" -ibk %t/Exported.swiftinterface @@ -28,20 +28,8 @@ // RUN: -emit-private-module-interface-path %t/Exporter.private.swiftinterface // RUN: %target-swift-typecheck-module-from-interface(%t/Exporter.swiftinterface) -I %t // RUN: %target-swift-typecheck-module-from-interface(%t/Exporter.private.swiftinterface) -module-name Exporter -I %t -// RUN: cat %t/Exporter.swiftinterface | %FileCheck -check-prefix=CHECK-USE-EXPORTER %s -// RUN: cat %t/Exporter.private.swiftinterface | %FileCheck -check-prefix=CHECK-USE-EXPORTED %s - -/// Build lib with an @exported import of the exported one. -// RUN: %target-swift-frontend -emit-module %t/Exporter.swift \ -// RUN: -module-name Exporter -swift-version 5 -I %t \ -// RUN: -enable-library-evolution \ -// RUN: -emit-module-path %t/Exporter.swiftmodule \ -// RUN: -emit-module-interface-path %t/Exporter.swiftinterface \ -// RUN: -emit-private-module-interface-path %t/Exporter.private.swiftinterface -// RUN: %target-swift-typecheck-module-from-interface(%t/Exporter.swiftinterface) -I %t -// RUN: %target-swift-typecheck-module-from-interface(%t/Exporter.private.swiftinterface) -module-name Exporter -I %t -// RUN: cat %t/Exporter.swiftinterface | %FileCheck -check-prefix=CHECK-USE-EXPORTER %s -// RUN: cat %t/Exporter.private.swiftinterface | %FileCheck -check-prefix=CHECK-USE-EXPORTED %s +// RUN: %FileCheck -input-file=%t/Exporter.swiftinterface -check-prefix=CHECK-USE-EXPORTER %s +// RUN: %FileCheck -input-file=%t/Exporter.private.swiftinterface -check-prefix=CHECK-USE-EXPORTED %s /// Build a client of the exporter lib. // RUN: %target-swift-frontend -emit-module %t/Client.swift \ @@ -52,8 +40,8 @@ // RUN: -emit-private-module-interface-path %t/Client.private.swiftinterface // RUN: %target-swift-typecheck-module-from-interface(%t/Client.swiftinterface) -I %t // RUN: %target-swift-typecheck-module-from-interface(%t/Client.private.swiftinterface) -module-name Client -I %t -// RUN: cat %t/Client.swiftinterface | %FileCheck -check-prefix=CHECK-USE-EXPORTER %s -// RUN: cat %t/Client.private.swiftinterface | %FileCheck -check-prefix=CHECK-USE-EXPORTED %s +// RUN: %FileCheck -input-file=%t/Client.swiftinterface -check-prefix=CHECK-USE-EXPORTER %s +// RUN: %FileCheck -input-file=%t/Client.private.swiftinterface -check-prefix=CHECK-USE-EXPORTED %s /// Build a client of the exporter lib against the public swiftinterface. // RUN: rm %t/Exporter.private.swiftinterface %t/Exporter.swiftmodule @@ -65,8 +53,8 @@ // RUN: -emit-private-module-interface-path %t/Client.private.swiftinterface // RUN: %target-swift-typecheck-module-from-interface(%t/Client.swiftinterface) -I %t // RUN: %target-swift-typecheck-module-from-interface(%t/Client.private.swiftinterface) -module-name Client -I %t -// RUN: cat %t/Client.swiftinterface | %FileCheck -check-prefix=CHECK-USE-EXPORTER %s -// RUN: cat %t/Client.private.swiftinterface | %FileCheck -check-prefix=CHECK-USE-EXPORTED %s +// RUN: %FileCheck -input-file=%t/Client.swiftinterface -check-prefix=CHECK-USE-EXPORTER %s +// RUN: %FileCheck -input-file=%t/Client.private.swiftinterface -check-prefix=CHECK-USE-EXPORTED %s //--- module.modulemap module Exported { From f02b2f153294f682217c6639739fb60575821565 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Wed, 28 Jan 2026 14:28:14 -0800 Subject: [PATCH 2/2] Use export_as name in some private swiftinterfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, if a declaration belonged to a module with an `export_as` attribute, Swift always used the exported module name in the public module interface and the real module name in the private module interface. However, this is only a rough approximation of the behavior we really want, which is to use the real name in module interfaces that might be imported by dependencies of the exported name. Change this logic so that public interfaces always use the exported name, and private interfaces use the exported name *only* if a module with that name has been loaded. This should make it so that if you’re building the `export_as` module or anything that imports it, you use the exported name; otherwise you use the real name. Fixes rdar://167874630. --- include/swift/AST/PrintOptions.h | 24 +++++++++++++++---- lib/AST/ASTPrinter.cpp | 22 +++++++++++++++-- lib/Frontend/ModuleInterfaceSupport.cpp | 4 +++- .../export-as-in-swiftinterfaces.swift | 6 ++--- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/include/swift/AST/PrintOptions.h b/include/swift/AST/PrintOptions.h index 1eda0fb4b8d..7bca650afa8 100644 --- a/include/swift/AST/PrintOptions.h +++ b/include/swift/AST/PrintOptions.h @@ -279,11 +279,26 @@ public: /// Whether to protocol-qualify DependentMemberTypes. bool ProtocolQualifiedDependentMemberTypes = false; - /// If true, printed module names will use the "exported" name, which may be - /// different from the regular name. + enum class ExportedModuleNameUsage : uint8_t { + /// If there is an exported module name, always use it instead of the + /// regular name. + Always, + + /// If there is an exported module name and the named module is the main + /// module or has been loaded by the main module, use it instead of the + /// regular name. + IfLoaded, + + /// Always use the regular name. + Never, + }; + + /// Conditions under which printed module names will use the "exported" name, + /// which may be different from the regular name. /// /// \see FileUnit::getExportedModuleName - bool UseExportedModuleNames = false; + ExportedModuleNameUsage UseExportedModuleNames = + ExportedModuleNameUsage::Never; /// If true, printed module names will use the "public" (for documentation) /// name, which may be different from the regular name. @@ -781,7 +796,8 @@ public: bool preferTypeRepr, bool printFullConvention, InterfaceMode interfaceMode, - bool useExportedModuleNames, + ExportedModuleNameUsage + useExportedModuleNames, bool aliasModuleNames, llvm::SmallSet *aliasModuleNamesTargets diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index be0ae5895dc..1037c4673e0 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -273,7 +273,8 @@ PrintOptions PrintOptions::printSwiftInterfaceFile(ModuleDecl *ModuleToPrint, bool preferTypeRepr, bool printFullConvention, InterfaceMode interfaceMode, - bool useExportedModuleNames, + ExportedModuleNameUsage + useExportedModuleNames, bool aliasModuleNames, llvm::SmallSet *aliasModuleNamesTargets @@ -6079,6 +6080,23 @@ class TypePrinter : public TypeVisitorgetVisibleClangModules(Options.InterfaceContentKind); } + bool shouldUseExportedModuleName(ASTContext &ctx, + StringRef exportedModuleName) { + if (exportedModuleName.empty()) + return false; + + switch (Options.UseExportedModuleNames) { + case PrintOptions::ExportedModuleNameUsage::Always: + return true; + case PrintOptions::ExportedModuleNameUsage::Never: + return false; + case PrintOptions::ExportedModuleNameUsage::IfLoaded: + return ctx.getLoadedModule(ctx.getIdentifier(exportedModuleName)); + } + + llvm_unreachable("Unrecognized ExportedModuleNameUsage"); + } + void printModuleContext(GenericTypeDecl *TyDecl) { FileUnit *File = cast(TyDecl->getModuleScopeContext()); ModuleDecl *Mod = File->getParentModule(); @@ -6116,7 +6134,7 @@ class TypePrinter : public TypeVisitorgetRealName(); - if (Options.UseExportedModuleNames && !ExportedModuleName.empty()) { + if (shouldUseExportedModuleName(Mod->getASTContext(), ExportedModuleName)) { Name = Mod->getASTContext().getIdentifier(ExportedModuleName); } diff --git a/lib/Frontend/ModuleInterfaceSupport.cpp b/lib/Frontend/ModuleInterfaceSupport.cpp index 72b8d489738..f3f99d01ad0 100644 --- a/lib/Frontend/ModuleInterfaceSupport.cpp +++ b/lib/Frontend/ModuleInterfaceSupport.cpp @@ -892,7 +892,9 @@ bool swift::emitSwiftInterface(raw_ostream &out, DisableModuleSelectorsInModuleInterface)) useModuleSelectors = false; - bool useExportedModuleNames = Opts.printPublicInterface(); + auto useExportedModuleNames = Opts.printPublicInterface() + ? PrintOptions::ExportedModuleNameUsage::Always + : PrintOptions::ExportedModuleNameUsage::IfLoaded; const PrintOptions printOptions = PrintOptions::printSwiftInterfaceFile( M, useModuleSelectors, Opts.PreserveTypesAsWritten, Opts.PrintFullConvention, diff --git a/test/ModuleInterface/export-as-in-swiftinterfaces.swift b/test/ModuleInterface/export-as-in-swiftinterfaces.swift index 44d3087ca33..f616da1bf68 100644 --- a/test/ModuleInterface/export-as-in-swiftinterfaces.swift +++ b/test/ModuleInterface/export-as-in-swiftinterfaces.swift @@ -29,7 +29,7 @@ // RUN: %target-swift-typecheck-module-from-interface(%t/Exporter.swiftinterface) -I %t // RUN: %target-swift-typecheck-module-from-interface(%t/Exporter.private.swiftinterface) -module-name Exporter -I %t // RUN: %FileCheck -input-file=%t/Exporter.swiftinterface -check-prefix=CHECK-USE-EXPORTER %s -// RUN: %FileCheck -input-file=%t/Exporter.private.swiftinterface -check-prefix=CHECK-USE-EXPORTED %s +// RUN: %FileCheck -input-file=%t/Exporter.private.swiftinterface -check-prefix=CHECK-USE-EXPORTER %s /// Build a client of the exporter lib. // RUN: %target-swift-frontend -emit-module %t/Client.swift \ @@ -41,7 +41,7 @@ // RUN: %target-swift-typecheck-module-from-interface(%t/Client.swiftinterface) -I %t // RUN: %target-swift-typecheck-module-from-interface(%t/Client.private.swiftinterface) -module-name Client -I %t // RUN: %FileCheck -input-file=%t/Client.swiftinterface -check-prefix=CHECK-USE-EXPORTER %s -// RUN: %FileCheck -input-file=%t/Client.private.swiftinterface -check-prefix=CHECK-USE-EXPORTED %s +// RUN: %FileCheck -input-file=%t/Client.private.swiftinterface -check-prefix=CHECK-USE-EXPORTER %s /// Build a client of the exporter lib against the public swiftinterface. // RUN: rm %t/Exporter.private.swiftinterface %t/Exporter.swiftmodule @@ -54,7 +54,7 @@ // RUN: %target-swift-typecheck-module-from-interface(%t/Client.swiftinterface) -I %t // RUN: %target-swift-typecheck-module-from-interface(%t/Client.private.swiftinterface) -module-name Client -I %t // RUN: %FileCheck -input-file=%t/Client.swiftinterface -check-prefix=CHECK-USE-EXPORTER %s -// RUN: %FileCheck -input-file=%t/Client.private.swiftinterface -check-prefix=CHECK-USE-EXPORTED %s +// RUN: %FileCheck -input-file=%t/Client.private.swiftinterface -check-prefix=CHECK-USE-EXPORTER %s //--- module.modulemap module Exported {