Skip to content

Commit c83f638

Browse files
Merge pull request #20428 from aschwaighofer/private_imports
Add @_private(from: "SourceFile.swift") imports
2 parents 6aab1c8 + fbb4236 commit c83f638

36 files changed

+614
-79
lines changed

include/swift/AST/Attr.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,10 @@ DECL_ATTR(_dynamicReplacement, DynamicReplacement,
384384
SIMPLE_DECL_ATTR(_borrowed, Borrowed,
385385
OnVar | OnSubscript | UserInaccessible |
386386
NotSerialized, 81)
387+
DECL_ATTR(_private, PrivateImport,
388+
OnImport |
389+
UserInaccessible |
390+
NotSerialized, 82)
387391

388392
#undef TYPE_ATTR
389393
#undef DECL_ATTR_ALIAS

include/swift/AST/Attr.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,26 @@ class ObjCAttr final : public DeclAttribute,
901901
}
902902
};
903903

904+
class PrivateImportAttr final
905+
: public DeclAttribute {
906+
StringRef SourceFile;
907+
908+
PrivateImportAttr(SourceLoc atLoc, SourceRange baseRange,
909+
StringRef sourceFile, SourceRange parentRange);
910+
911+
public:
912+
static PrivateImportAttr *create(ASTContext &Ctxt, SourceLoc AtLoc,
913+
SourceLoc PrivateLoc, SourceLoc LParenLoc,
914+
StringRef sourceFile, SourceLoc RParenLoc);
915+
916+
StringRef getSourceFile() const {
917+
return SourceFile;
918+
}
919+
static bool classof(const DeclAttribute *DA) {
920+
return DA->getKind() == DAK_PrivateImport;
921+
}
922+
};
923+
904924
/// The @_dynamicReplacement(for:) attribute.
905925
class DynamicReplacementAttr final
906926
: public DeclAttribute,

include/swift/AST/Decl.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ class alignas(1 << DeclAlignInBits) Decl {
573573
HasAnyUnavailableValues : 1
574574
);
575575

576-
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1,
576+
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1,
577577
/// If the module was or is being compiled with `-enable-testing`.
578578
TestingEnabled : 1,
579579

@@ -586,7 +586,10 @@ class alignas(1 << DeclAlignInBits) Decl {
586586
RawResilienceStrategy : 1,
587587

588588
/// Whether all imports have been resolved. Used to detect circular imports.
589-
HasResolvedImports : 1
589+
HasResolvedImports : 1,
590+
591+
// If the module was or is being compiled with `-enable-private-imports`.
592+
PrivateImportsEnabled : 1
590593
);
591594

592595
SWIFT_INLINE_BITFIELD(PrecedenceGroupDecl, Decl, 1+2,

include/swift/AST/DiagnosticsParse.def

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,6 +1428,15 @@ ERROR(attr_dynamic_replacement_expected_for,none,
14281428
ERROR(attr_dynamic_replacement_expected_colon,none,
14291429
"expected ':' after @_dynamicReplacement(for", ())
14301430

1431+
ERROR(attr_private_import_expected_rparen,none,
1432+
"expected ')' after function name for @_private", ())
1433+
ERROR(attr_private_import_expected_sourcefile, none,
1434+
"expected 'sourceFile' in '_private' attribute", ())
1435+
ERROR(attr_private_import_expected_sourcefile_name,none,
1436+
"expected a source file name in @_private(sourceFile:)", ())
1437+
ERROR(attr_private_import_expected_colon,none,
1438+
"expected ':' after @_private(sourceFile", ())
1439+
14311440
// opened
14321441
ERROR(opened_attribute_expected_lparen,none,
14331442
"expected '(' after 'opened' attribute", ())

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,10 @@ ERROR(ambiguous_decl_in_module,none,
759759
ERROR(module_not_testable,none,
760760
"module %0 was not compiled for testing", (Identifier))
761761

762+
ERROR(module_not_compiled_for_private_import,none,
763+
"module %0 was not compiled for private import", (Identifier))
764+
765+
762766
// Operator decls
763767
ERROR(ambiguous_operator_decls,none,
764768
"ambiguous operator declarations found for operator", ())

include/swift/AST/Module.h

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,15 @@ class ModuleDecl : public DeclContext, public TypeDecl {
283283
Bits.ModuleDecl.TestingEnabled = enabled;
284284
}
285285

286+
/// Returns true if this module was or is begin compile with
287+
/// `-enable-private-imports`.
288+
bool arePrivateImportsEnabled() const {
289+
return Bits.ModuleDecl.PrivateImportsEnabled;
290+
}
291+
void setPrivateImportsEnabled(bool enabled = true) {
292+
Bits.ModuleDecl.PrivateImportsEnabled = true;
293+
}
294+
286295
/// Returns true if there was an error trying to load this module.
287296
bool failedToLoad() const {
288297
return Bits.ModuleDecl.FailedToLoad;
@@ -844,20 +853,38 @@ class SourceFile final : public FileUnit {
844853

845854
/// This source file has access to testable declarations in the imported
846855
/// module.
847-
Testable = 0x2
856+
Testable = 0x2,
857+
858+
/// This source file has access to private declarations in the imported
859+
/// module.
860+
PrivateImport = 0x4,
848861
};
849862

850863
/// \see ImportFlags
851864
using ImportOptions = OptionSet<ImportFlags>;
852865

866+
typedef std::pair<ImportOptions, StringRef> ImportOptionsAndFilename;
867+
868+
struct ImportedModuleDesc {
869+
ModuleDecl::ImportedModule module;
870+
ImportOptions importOptions;
871+
StringRef filename;
872+
873+
ImportedModuleDesc(ModuleDecl::ImportedModule module, ImportOptions options)
874+
: module(module), importOptions(options) {}
875+
ImportedModuleDesc(ModuleDecl::ImportedModule module, ImportOptions options,
876+
StringRef filename)
877+
: module(module), importOptions(options), filename(filename) {}
878+
};
879+
853880
private:
854881
std::unique_ptr<LookupCache> Cache;
855882
LookupCache &getCache() const;
856883

857884
/// This is the list of modules that are imported by this module.
858885
///
859886
/// This is filled in by the Name Binding phase.
860-
ArrayRef<std::pair<ModuleDecl::ImportedModule, ImportOptions>> Imports;
887+
ArrayRef<ImportedModuleDesc> Imports;
861888

862889
/// A unique identifier representing this file; used to mark private decls
863890
/// within the file to keep them from conflicting with other files in the
@@ -961,10 +988,9 @@ class SourceFile final : public FileUnit {
961988
ImplicitModuleImportKind ModImpKind, bool KeepParsedTokens = false,
962989
bool KeepSyntaxTree = false);
963990

964-
void
965-
addImports(ArrayRef<std::pair<ModuleDecl::ImportedModule, ImportOptions>> IM);
991+
void addImports(ArrayRef<ImportedModuleDesc> IM);
966992

967-
bool hasTestableImport(const ModuleDecl *module) const;
993+
bool hasTestableOrPrivateImport(AccessLevel accessLevel, const ValueDecl *ofDecl) const;
968994

969995
void clearLookupCache();
970996

@@ -1224,12 +1250,29 @@ class LoadedFile : public FileUnit {
12241250
assert(classof(this) && "invalid kind");
12251251
}
12261252

1253+
/// A map from private/fileprivate decls to the file they were defined in.
1254+
llvm::DenseMap<const ValueDecl *, Identifier> FilenameForPrivateDecls;
1255+
12271256
public:
1257+
12281258
/// Returns an arbitrary string representing the storage backing this file.
12291259
///
12301260
/// This is usually a filesystem path.
12311261
virtual StringRef getFilename() const;
12321262

1263+
void addFilenameForPrivateDecl(const ValueDecl *decl, Identifier id) {
1264+
assert(!FilenameForPrivateDecls.count(decl) ||
1265+
FilenameForPrivateDecls[decl] == id);
1266+
FilenameForPrivateDecls[decl] = id;
1267+
}
1268+
1269+
StringRef getFilenameForPrivateDecl(const ValueDecl *decl) {
1270+
auto it = FilenameForPrivateDecls.find(decl);
1271+
if (it == FilenameForPrivateDecls.end())
1272+
return StringRef();
1273+
return it->second.str();
1274+
}
1275+
12331276
/// Look up an operator declaration.
12341277
///
12351278
/// \param name The operator name ("+", ">>", etc.)

include/swift/Frontend/FrontendOptions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ class FrontendOptions {
192192
/// \see ModuleDecl::isTestingEnabled
193193
bool EnableTesting = false;
194194

195+
/// Indicates whether we are compiling for private imports.
196+
///
197+
/// \see ModuleDecl::arePrivateImportsEnabled
198+
bool EnablePrivateImports = false;
199+
195200
/// Enables the "fully resilient" resilience strategy.
196201
///
197202
/// \see ResilienceStrategy::Resilient

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,10 @@ def enable_testing : Flag<["-"], "enable-testing">,
791791
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,
792792
HelpText<"Allows this module's internal API to be accessed for testing">;
793793

794+
def enable_private_imports : Flag<["-"], "enable-private-imports">,
795+
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,
796+
HelpText<"Allows this module's internal and private API to be accessed">;
797+
794798
def sanitize_EQ : CommaJoined<["-"], "sanitize=">,
795799
Flags<[FrontendOption, NoInteractiveOption]>, MetaVarName<"<check>">,
796800
HelpText<"Turn on runtime checks for erroneous behavior.">;

include/swift/Serialization/DeclTypeRecordNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ OTHER(SUBSTITUTION_MAP, 236)
168168

169169
OTHER(LOCAL_DISCRIMINATOR, 237)
170170
OTHER(PRIVATE_DISCRIMINATOR, 238)
171+
OTHER(FILENAME_FOR_PRIVATE, 239)
171172

172173
OTHER(ABSTRACT_PROTOCOL_CONFORMANCE, 240)
173174
OTHER(NORMAL_PROTOCOL_CONFORMANCE, 241)

include/swift/Serialization/ModuleFormat.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5252
/// describe what change you made. The content of this comment isn't important;
5353
/// it just ensures a conflict if two people change the module format.
5454
/// Don't worry about adhering to the 80-column limit for this line.
55-
const uint16_t SWIFTMODULE_VERSION_MINOR = 462; // Last change: Add dynamicReplacement(for:)
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 463; // Last change: enable-private-imports
5656

5757
using DeclIDField = BCFixed<31>;
5858

@@ -592,7 +592,8 @@ namespace options_block {
592592
XCC,
593593
IS_SIB,
594594
IS_TESTABLE,
595-
RESILIENCE_STRATEGY
595+
RESILIENCE_STRATEGY,
596+
ARE_PRIVATE_IMPORTS_ENABLED
596597
};
597598

598599
using SDKPathLayout = BCRecordLayout<
@@ -614,6 +615,10 @@ namespace options_block {
614615
IS_TESTABLE
615616
>;
616617

618+
using ArePrivateImportsEnabledLayout = BCRecordLayout<
619+
ARE_PRIVATE_IMPORTS_ENABLED
620+
>;
621+
617622
using ResilienceStrategyLayout = BCRecordLayout<
618623
RESILIENCE_STRATEGY,
619624
BCFixed<2>
@@ -1309,6 +1314,11 @@ namespace decls_block {
13091314
BCVBR<2> // context-scoped discriminator counter
13101315
>;
13111316

1317+
using FilenameForPrivateLayout = BCRecordLayout<
1318+
FILENAME_FOR_PRIVATE,
1319+
IdentifierIDField // the file name, as an identifier
1320+
>;
1321+
13121322
/// A placeholder for lack of concrete conformance information.
13131323
using AbstractProtocolConformanceLayout = BCRecordLayout<
13141324
ABSTRACT_PROTOCOL_CONFORMANCE,
@@ -1513,6 +1523,7 @@ namespace decls_block {
15131523
= BCRecordLayout<RestatedObjCConformance_DECL_ATTR>;
15141524
using ClangImporterSynthesizedTypeDeclAttrLayout
15151525
= BCRecordLayout<ClangImporterSynthesizedType_DECL_ATTR>;
1526+
using PrivateImportDeclAttrLayout = BCRecordLayout<PrivateImport_DECL_ATTR>;
15161527

15171528
using InlineDeclAttrLayout = BCRecordLayout<
15181529
Inline_DECL_ATTR,

include/swift/Serialization/Validation.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class ExtendedValidationInfo {
9393
SmallVector<StringRef, 4> ExtraClangImporterOpts;
9494
StringRef SDKPath;
9595
struct {
96+
unsigned ArePrivateImportsEnabled : 1;
9697
unsigned IsSIB : 1;
9798
unsigned IsTestable : 1;
9899
unsigned ResilienceStrategy : 2;
@@ -117,6 +118,10 @@ class ExtendedValidationInfo {
117118
void setIsSIB(bool val) {
118119
Bits.IsSIB = val;
119120
}
121+
bool arePrivateImportsEnabled() { return Bits.ArePrivateImportsEnabled; }
122+
void setPrivateImportsEnabled(bool enabled) {
123+
Bits.ArePrivateImportsEnabled = enabled;
124+
}
120125
bool isTestable() const { return Bits.IsTestable; }
121126
void setIsTestable(bool val) {
122127
Bits.IsTestable = val;

lib/AST/Attr.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,12 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
468468
}
469469
break;
470470
}
471+
472+
case DAK_PrivateImport: {
473+
Printer.printAttrName("@_private(sourceFile: \"");
474+
Printer << cast<PrivateImportAttr>(this)->getSourceFile() << "\")";
475+
break;
476+
}
471477

472478
case DAK_SwiftNativeObjCRuntimeBase: {
473479
auto *attr = cast<SwiftNativeObjCRuntimeBaseAttr>(this);
@@ -547,7 +553,8 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
547553
}
548554

549555
case DAK_DynamicReplacement: {
550-
Printer.printAttrName("@_dynamicReplacement(for: \"");
556+
Printer.printAttrName("@_dynamicReplacement");
557+
Printer << "(for: \"";
551558
auto *attr = cast<DynamicReplacementAttr>(this);
552559
Printer << attr->getReplacedFunctionName() << "\")";
553560
break;
@@ -621,6 +628,8 @@ StringRef DeclAttribute::getAttrName() const {
621628
return "objc";
622629
case DAK_DynamicReplacement:
623630
return "_dynamicReplacement";
631+
case DAK_PrivateImport:
632+
return "_private";
624633
case DAK_RestatedObjCConformance:
625634
return "_restatedObjCConformance";
626635
case DAK_Inline: {
@@ -785,6 +794,22 @@ ObjCAttr *ObjCAttr::clone(ASTContext &context) const {
785794
return attr;
786795
}
787796

797+
PrivateImportAttr::PrivateImportAttr(SourceLoc atLoc, SourceRange baseRange,
798+
StringRef sourceFile,
799+
SourceRange parenRange)
800+
: DeclAttribute(DAK_PrivateImport, atLoc, baseRange, /*Implicit=*/false),
801+
SourceFile(sourceFile) {}
802+
803+
PrivateImportAttr *PrivateImportAttr::create(ASTContext &Ctxt, SourceLoc AtLoc,
804+
SourceLoc PrivateLoc,
805+
SourceLoc LParenLoc,
806+
StringRef sourceFile,
807+
SourceLoc RParenLoc) {
808+
return new (Ctxt)
809+
PrivateImportAttr(AtLoc, SourceRange(PrivateLoc, RParenLoc), sourceFile,
810+
SourceRange(LParenLoc, RParenLoc));
811+
}
812+
788813
DynamicReplacementAttr::DynamicReplacementAttr(SourceLoc atLoc,
789814
SourceRange baseRange,
790815
DeclName name,

0 commit comments

Comments
 (0)