Merge pull request #84311 from tshortli/preconcurrency-import-in-swiftinterface

ModuleInterface: Print imports with @preconcurrency in swiftinterface files
This commit is contained in:
Allan Shortlidge
2025-09-16 13:09:48 -07:00
committed by GitHub
8 changed files with 98 additions and 0 deletions

View File

@@ -126,6 +126,13 @@ public:
const ModuleDecl *importedModule,
llvm::SmallSetVector<Identifier, 4> &spiGroups) const {};
/// Returns true if any import of \p importedModule has the `@preconcurrency`
/// attribute.
virtual bool
isModuleImportedPreconcurrency(const ModuleDecl *importedModule) const {
return false;
};
/// Find all availability domains defined in this module with the given
/// identifier.
///

View File

@@ -965,6 +965,10 @@ public:
const ModuleDecl *importedModule,
llvm::SmallSetVector<Identifier, 4> &spiGroups) const;
/// Returns true if any import of \p importedModule has the `@preconcurrency`
/// attribute.
bool isModuleImportedPreconcurrency(const ModuleDecl *importedModule) const;
/// Finds the custom availability domain defined by this module with the
/// given identifier and if one exists adds it to results.
void

View File

@@ -471,6 +471,11 @@ public:
const ModuleDecl *importedModule,
llvm::SmallSetVector<Identifier, 4> &spiGroups) const override;
/// Returns true if any import of \p importedModule has the `@preconcurrency`
/// attribute.
virtual bool isModuleImportedPreconcurrency(
const ModuleDecl *importedModule) const override;
// Is \p targetDecl accessible as an explicitly imported SPI from this file?
bool isImportedAsSPI(const ValueDecl *targetDecl) const;

View File

@@ -466,6 +466,9 @@ public:
const ModuleDecl *importedModule,
llvm::SmallSetVector<Identifier, 4> &spiGroups) const override;
virtual bool isModuleImportedPreconcurrency(
const ModuleDecl *importedModule) const override;
std::optional<CommentInfo> getCommentForDecl(const Decl *D) const override;
bool hasLoadedSwiftDoc() const override;

View File

@@ -1044,6 +1044,20 @@ void ModuleDecl::lookupImportedSPIGroups(
FORWARD(lookupImportedSPIGroups, (importedModule, spiGroups));
}
bool ModuleDecl::isModuleImportedPreconcurrency(
const ModuleDecl *importedModule) const {
for (const FileUnit *file : getFiles()) {
if (file->isModuleImportedPreconcurrency(importedModule))
return true;
if (auto *synth = file->getSynthesizedFile()) {
if (synth->isModuleImportedPreconcurrency(importedModule))
return true;
}
}
return false;
}
void ModuleDecl::lookupAvailabilityDomains(
Identifier identifier,
llvm::SmallVectorImpl<AvailabilityDomain> &results) const {
@@ -3050,6 +3064,20 @@ void SourceFile::lookupImportedSPIGroups(
}
}
bool SourceFile::isModuleImportedPreconcurrency(
const ModuleDecl *importedModule) const {
auto &imports = getASTContext().getImportCache();
for (auto &import : *Imports) {
if (import.options.contains(ImportFlags::Preconcurrency) &&
(importedModule == import.module.importedModule ||
imports.isImportedByViaSwiftOnly(importedModule,
import.module.importedModule))) {
return true;
}
}
return false;
}
bool shouldImplicitImportAsSPI(ArrayRef<Identifier> spiGroups) {
for (auto group : spiGroups) {
if (group.empty())

View File

@@ -271,6 +271,9 @@ static void printImports(raw_ostream &out,
ModuleDecl::ImportFilterKind::Default,
ModuleDecl::ImportFilterKind::ShadowedByCrossImportOverlay};
// FIXME: Scan over all imports in the module once to build up the attribute
// set for printed imports, instead of repeatedly doing linear scans for each
// kind of attribute.
using ImportSet = llvm::SmallSet<ImportedModule, 8, ImportedModule::Order>;
auto getImports = [M](ModuleDecl::ImportFilter filter) -> ImportSet {
SmallVector<ImportedModule, 8> matchingImports;
@@ -355,6 +358,9 @@ static void printImports(raw_ostream &out,
out << "@_spi(" << spiName << ") ";
}
if (M->isModuleImportedPreconcurrency(importedModule))
out << "@preconcurrency ";
if (Opts.printPackageInterface() &&
!publicImportSet.count(import) &&
packageOnlyImportSet.count(import))

View File

@@ -1915,6 +1915,14 @@ void SerializedASTFile::lookupImportedSPIGroups(
}
}
bool SerializedASTFile::isModuleImportedPreconcurrency(
const ModuleDecl *importedModule) const {
// This method should only be queried during `-merge-modules` jobs, which are
// deprecated, and thus no effort has been made to answer this query correctly
// (@preconcurrency is not encoded on imports in serialized modules).
return false;
}
std::optional<CommentInfo>
SerializedASTFile::getCommentForDecl(const Decl *D) const {
return File.getCommentForDecl(D);

View File

@@ -0,0 +1,37 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t
// RUN: %target-swift-frontend -emit-module %t/PreconcurrencyLib.swift -module-name PreconcurrencyLib -swift-version 5 -enable-library-evolution -emit-module-path %t/PreconcurrencyLib.swiftmodule -emit-module-interface-path %t/PreconcurrencyLib.swiftinterface
// RUN: %target-swift-frontend -emit-module %t/OtherLib.swift -module-name OtherLib -swift-version 5 -enable-library-evolution -emit-module-path %t/OtherLib.swiftmodule -emit-module-interface-path %t/OtherLib.swiftinterface
// RUN: %target-swift-emit-module-interface(%t/ClientLib.swiftinterface) -swift-version 6 %t/ClientLib_file1.swift %t/ClientLib_file2.swift -module-name ClientLib -I %t
// RUN: %target-swift-typecheck-module-from-interface(%t/ClientLib.swiftinterface) -module-name ClientLib -I %t
// RUN: %FileCheck %s < %t/ClientLib.swiftinterface
// CHECK: {{^}}@preconcurrency import OtherLib
// CHECK: {{^}}@preconcurrency import PreconcurrencyLib
// CHECK: public struct Struct1 : Swift.Sendable
// CHECK: public struct Struct2
//--- PreconcurrencyLib.swift
public class C {}
//--- OtherLib.swift
// Intentionally empty
//--- ClientLib_file1.swift
@preconcurrency public import PreconcurrencyLib
public import OtherLib
public struct Struct1: Sendable {
public var c: C
}
//--- ClientLib_file2.swift
internal import PreconcurrencyLib
@preconcurrency internal import OtherLib
public struct Struct2 {}