Skip to content

Commit 37979c8

Browse files
committed
[5.1] Serialization: Also serialize the filename for storage decls with private accessors
If a value decl is internal hasTestableOrPrivateImport will succeed (or fail) without looking at the filename. However this breaks when we query an internal storage decl with private formal access for a private setter: the query would fail because no filename was serialized for the decl (we only serialize filenames for private decls). So in the special case of storage with private accessor also serialize the filename. rdar://48516545
1 parent 6e6b7e4 commit 37979c8

File tree

5 files changed

+57
-13
lines changed

5 files changed

+57
-13
lines changed

include/swift/AST/Decl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4621,6 +4621,9 @@ class AbstractStorageDecl : public ValueDecl {
46214621
/// other modules.
46224622
bool exportsPropertyDescriptor() const;
46234623

4624+
/// True if any of the accessors to the storage is private or fileprivate.
4625+
bool hasPrivateAccessor() const;
4626+
46244627
// Implement isa/cast/dyncast/etc.
46254628
static bool classof(const Decl *D) {
46264629
return D->getKind() >= DeclKind::First_AbstractStorageDecl &&

lib/AST/Decl.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4435,6 +4435,14 @@ void AbstractStorageDecl::overwriteImplInfo(StorageImplInfo implInfo) {
44354435
Accessors.getPointer()->overwriteImplInfo(implInfo);
44364436
}
44374437

4438+
bool AbstractStorageDecl::hasPrivateAccessor() const {
4439+
for (auto accessor : getAllAccessors()) {
4440+
if (hasPrivateOrFilePrivateFormalAccess(accessor))
4441+
return true;
4442+
}
4443+
return false;
4444+
}
4445+
44384446
void AbstractStorageDecl::setAccessors(StorageImplInfo implInfo,
44394447
SourceLoc lbraceLoc,
44404448
ArrayRef<AccessorDecl *> accessors,

lib/Serialization/Serialization.cpp

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2696,19 +2696,37 @@ void Serializer::writeDecl(const Decl *D) {
26962696
}
26972697

26982698
if (auto *value = dyn_cast<ValueDecl>(D)) {
2699-
if (value->getFormalAccess() <= swift::AccessLevel::FilePrivate &&
2700-
!value->getDeclContext()->isLocalContext()) {
2699+
auto *storage = dyn_cast<AbstractStorageDecl>(value);
2700+
auto access = value->getFormalAccess();
2701+
// Emit the private descriminator for private decls.
2702+
// FIXME: We shouldn't need to encode this for /all/ private decls.
2703+
// In theory we can follow the same rules as mangling and only include
2704+
// the outermost private context.
2705+
bool shouldEmitPrivateDescriminator =
2706+
access <= swift::AccessLevel::FilePrivate &&
2707+
!value->getDeclContext()->isLocalContext();
2708+
2709+
// Emit the the filename for private mapping for private decls and
2710+
// decls with private accessors if compiled with -enable-private-imports.
2711+
bool shouldEmitFilenameForPrivate =
2712+
M->arePrivateImportsEnabled() &&
2713+
!value->getDeclContext()->isLocalContext() &&
2714+
(access <= swift::AccessLevel::FilePrivate ||
2715+
(storage &&
2716+
storage->getFormalAccess() >= swift::AccessLevel::Internal &&
2717+
storage->hasPrivateAccessor()));
2718+
2719+
if (shouldEmitFilenameForPrivate || shouldEmitPrivateDescriminator) {
27012720
auto topLevelContext = value->getDeclContext()->getModuleScopeContext();
27022721
if (auto *enclosingFile = dyn_cast<FileUnit>(topLevelContext)) {
2703-
// FIXME: We shouldn't need to encode this for /all/ private decls.
2704-
// In theory we can follow the same rules as mangling and only include
2705-
// the outermost private context.
2706-
Identifier discriminator =
2707-
enclosingFile->getDiscriminatorForPrivateValue(value);
2708-
unsigned abbrCode =
2709-
DeclTypeAbbrCodes[PrivateDiscriminatorLayout::Code];
2710-
PrivateDiscriminatorLayout::emitRecord(Out, ScratchRecord, abbrCode,
2711-
addDeclBaseNameRef(discriminator));
2722+
if (shouldEmitPrivateDescriminator) {
2723+
Identifier discriminator =
2724+
enclosingFile->getDiscriminatorForPrivateValue(value);
2725+
unsigned abbrCode =
2726+
DeclTypeAbbrCodes[PrivateDiscriminatorLayout::Code];
2727+
PrivateDiscriminatorLayout::emitRecord(
2728+
Out, ScratchRecord, abbrCode, addDeclBaseNameRef(discriminator));
2729+
}
27122730
auto getFilename = [](FileUnit *enclosingFile,
27132731
const ValueDecl *decl) -> StringRef {
27142732
if (auto *SF = dyn_cast<SourceFile>(enclosingFile)) {
@@ -2718,8 +2736,7 @@ void Serializer::writeDecl(const Decl *D) {
27182736
}
27192737
return StringRef();
27202738
};
2721-
// Only if compiled with -enable-private-imports.
2722-
if (M->arePrivateImportsEnabled()) {
2739+
if (shouldEmitFilenameForPrivate) {
27232740
auto filename = getFilename(enclosingFile, value);
27242741
if (!filename.empty()) {
27252742
auto filenameID = addFilename(filename);

test/Serialization/Inputs/private_import_other.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,10 @@ struct Value {
88
extension Value {
99
fileprivate func foo() {}
1010
}
11+
12+
struct Internal {
13+
private(set) var internalVarWithPrivateSetter : Int = 0
14+
fileprivate(set) var internalVarWithFilePrivateSetter : Int = 0
15+
public private(set) var publicVarWithPrivateSetter : Int = 0
16+
public fileprivate(set) var publicVarWithFilePrivateSetter : Int = 0
17+
}

test/Serialization/private_import.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@
4141
@_private(sourceFile: "private_import_other.swift") import private_import
4242
@_private(sourceFile: "private_import.swift") import client
4343

44+
extension Internal {
45+
mutating func set() {
46+
self.internalVarWithPrivateSetter = 1
47+
self.internalVarWithFilePrivateSetter = 1
48+
self.publicVarWithPrivateSetter = 1
49+
self.publicVarWithFilePrivateSetter = 1
50+
}
51+
}
52+
4453
Base().foo()
4554
// This should not be ambigious.
4655
Base().bar()

0 commit comments

Comments
 (0)