Skip to content

Commit 1adf4ca

Browse files
committed
* Hook up PackageUnit to ModuleDecl
* Use PackageUnit decl context for a package AccessScope * Return the module decl weakly referenced by PackageUnit in module decl context getters * Handle package in access scope checkers * Fix tests Resolves rdar://104987295
1 parent 302180f commit 1adf4ca

File tree

9 files changed

+93
-63
lines changed

9 files changed

+93
-63
lines changed

include/swift/AST/AccessScope.h

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,6 @@ class AccessScope {
6666
bool operator==(AccessScope RHS) const { return Value == RHS.Value; }
6767
bool operator!=(AccessScope RHS) const { return !(*this == RHS); }
6868
bool hasEqualDeclContextWith(AccessScope RHS) const {
69-
if (isPublic())
70-
return RHS.isPublic();
71-
if (isPackage())
72-
return RHS.isPackage();
7369
return getDeclContext() == RHS.getDeclContext();
7470
}
7571

@@ -81,26 +77,23 @@ class AccessScope {
8177
}
8278
bool isFileScope() const;
8379
bool isInternal() const;
84-
bool isPackage() const {
85-
return !Value.getPointer() && Value.getInt() == AccessLimitKind::Package;
86-
}
80+
bool isPackage() const;
8781

8882
/// Returns true if the context of this (use site) is more restrictive than
8983
/// the argument context (decl site). This function does _not_ check the
9084
/// restrictiveness of the access level between this and the argument. \see
9185
/// AccessScope::isInContext
9286
bool isChildOf(AccessScope AS) const {
93-
if (isInContext()) {
87+
if (isPackage())
88+
return AS.isPublic();
89+
else if (isInContext()) {
9490
if (AS.isInContext())
9591
return allowsPrivateAccess(getDeclContext(), AS.getDeclContext());
9692
else
97-
return AS.isPackage() || AS.isPublic();
93+
return AS.isPublic();
9894
}
99-
if (isPackage())
100-
return AS.isPublic();
101-
// If this is public, it can't be less than access level of AS
102-
// so return false
103-
return false;
95+
else // If this is public, it can't be less than access level of AS so return false
96+
return false;
10497
}
10598

10699
/// Result depends on whether it's called at a use site or a decl site:

include/swift/AST/DeclContext.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,9 +512,9 @@ class alignas(1 << DeclContextAlignInBits) DeclContext
512512
return false;
513513
}
514514

515-
/// Returns the package context of the parent module.
515+
/// Returns the package unit of this context.
516516
LLVM_READONLY
517-
PackageUnit *getParentModulePackage() const;
517+
PackageUnit *getPackageContext(bool lookupIfNotCurrent = false) const;
518518

519519
/// Returns the module context that contains this context.
520520
LLVM_READONLY

include/swift/AST/Module.h

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -165,27 +165,36 @@ class ModuleSourceFileLocationMap;
165165
class PackageUnit: public DeclContext {
166166

167167
Identifier PackageName;
168+
ModuleDecl &SourceModule;
168169

169-
PackageUnit(Identifier name);
170+
PackageUnit(Identifier name, ModuleDecl &src)
171+
: DeclContext(DeclContextKind::Package, nullptr), PackageName(name), SourceModule(src) {}
170172

171173
public:
172174
static PackageUnit *
173-
create(Identifier name, ASTContext &ctx) {
174-
return new (ctx) PackageUnit(name);
175+
create(Identifier name, ModuleDecl &src, ASTContext &ctx) {
176+
return new (ctx) PackageUnit(name, src);
175177
}
176178

177179
static bool classof(const DeclContext *DC) {
178180
return DC->getContextKind() == DeclContextKind::Package;
179181
}
180182

181183
static bool classof(const PackageUnit *PU) {
182-
// FIXME: add a correct check
183184
return true;
184185
}
185186

186187
Identifier getName() const {
187188
return PackageName;
188189
}
190+
191+
ModuleDecl &getSourceModule() {
192+
return SourceModule;
193+
}
194+
195+
bool isSamePackageAs(PackageUnit *other) {
196+
return getName() == other->getName();
197+
}
189198
};
190199

191200
/// The minimum unit of compilation.
@@ -202,8 +211,8 @@ class ModuleDecl
202211
/// The ABI name of the module, if it differs from the module name.
203212
mutable Identifier ModuleABIName;
204213

205-
/// The name of the package this module belongs to
206-
mutable Identifier PackageName;
214+
/// The package this module belongs to
215+
PackageUnit *Package;
207216

208217
/// Module name to use when referenced in clients module interfaces.
209218
mutable Identifier ExportAsName;
@@ -440,18 +449,21 @@ class ModuleDecl
440449
ModuleABIName = name;
441450
}
442451

443-
/// Get the package name of the module
444-
Identifier getPackageName() const { return PackageName; }
445-
446-
/// Set the name of the package this module belongs to
447-
void setPackageName(Identifier name) {
448-
PackageName = name;
449-
// TODO: uncomment when PackageUnit gets passed to constructor
450-
// PackageUnit *pkgUnit = PackageUnit::create(name, getASTContext());
451-
// DeclContext newContext = DeclContext(DeclContextKind::Module, pkgUnit);
452-
// setDeclContext(&newContext);
452+
/// Get the package name of this module
453+
/// FIXME: remove this and bump module version rdar://104723918
454+
Identifier getPackageName() const {
455+
if (auto pkg = getPackage())
456+
return pkg->getName();
457+
return Identifier();
453458
}
454459

460+
/// Get the package associated with this module
461+
PackageUnit *getPackage() const { return Package; }
462+
463+
/// Set the package this module is associated with
464+
/// FIXME: rename this with setPackage(name) rdar://104723918
465+
void setPackageName(Identifier name);
466+
455467
Identifier getExportAsName() const { return ExportAsName; }
456468

457469
void setExportAsName(Identifier name) {

lib/AST/ASTVerifier.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -963,12 +963,6 @@ class Verifier : public ASTWalker {
963963
if (D->hasAccess()) {
964964
PrettyStackTraceDecl debugStack("verifying access", D);
965965
if (!D->getASTContext().isAccessControlDisabled()) {
966-
if (D->getFormalAccessScope().isPackage() &&
967-
D->getFormalAccess() < AccessLevel::Package) {
968-
Out << "non-package decl has no formal access scope\n";
969-
D->dump(Out);
970-
abort();
971-
}
972966
if (D->getFormalAccessScope().isPublic() &&
973967
D->getFormalAccess() < AccessLevel::Public) {
974968
Out << "non-public decl has no formal access scope\n";

lib/AST/Decl.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3773,6 +3773,8 @@ static AccessLevel getAdjustedFormalAccess(const ValueDecl *VD,
37733773
}
37743774

37753775
if (useDC) {
3776+
if (auto usePkg = useDC->getPackageContext())
3777+
return access;
37763778
// Check whether we need to modify the access level based on
37773779
// @testable/@_private import attributes.
37783780
auto *useSF = dyn_cast<SourceFile>(useDC->getModuleScopeContext());
@@ -3925,8 +3927,11 @@ getAccessScopeForFormalAccess(const ValueDecl *VD,
39253927
: AccessLimitKind::None);
39263928
case AccessLevel::Internal:
39273929
return AccessScope(resultDC->getParentModule());
3928-
case AccessLevel::Package:
3929-
return AccessScope::getPackage();
3930+
case AccessLevel::Package: {
3931+
auto pkg = resultDC->getPackageContext(true);
3932+
assert(pkg && "decl has a package access level but there's no associated package; pass -package-name");
3933+
return AccessScope(pkg);
3934+
}
39303935
case AccessLevel::Public:
39313936
case AccessLevel::Open:
39323937
return AccessScope::getPublic();
@@ -3965,10 +3970,6 @@ static bool checkAccessUsingAccessScopes(const DeclContext *useDC,
39653970
// useDC is null only when caller wants to skip non-public type checks.
39663971
if (!useDC) return true;
39673972

3968-
// Check package access; accessing package decl should not be allowed if package names are different
3969-
if (accessScope.isPackage())
3970-
return VD->getDeclContext()->getParentModule()->getPackageName() == useDC->getParentModule()->getPackageName();
3971-
39723973
// Check SPI access
39733974
if (!VD->isSPI()) return true;
39743975
auto useSF = dyn_cast<SourceFile>(useDC->getModuleScopeContext());
@@ -4083,7 +4084,11 @@ static bool checkAccess(const DeclContext *useDC, const ValueDecl *VD,
40834084
auto *useSF = dyn_cast<SourceFile>(useFile);
40844085
return useSF && useSF->hasTestableOrPrivateImport(access, sourceModule);
40854086
}
4086-
case AccessLevel::Package:
4087+
case AccessLevel::Package: {
4088+
auto srcPkg = sourceDC->getPackageContext(true);
4089+
auto usePkg = useDC->getPackageContext(true);
4090+
return usePkg->isSamePackageAs(srcPkg);
4091+
}
40874092
case AccessLevel::Public:
40884093
case AccessLevel::Open:
40894094
return true;

lib/AST/DeclContext.cpp

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -274,15 +274,24 @@ DeclContext *DeclContext::getParentForLookup() const {
274274
return getParent();
275275
}
276276

277-
PackageUnit *DeclContext::getParentModulePackage() const {
278-
auto parentModule = getParentModule();
279-
auto pkg = parentModule->getParent();
280-
if (pkg)
281-
return const_cast<PackageUnit *>(cast<PackageUnit>(pkg));
282-
return nullptr;
277+
PackageUnit *DeclContext::getPackageContext(bool lookupIfNotCurrent) const {
278+
if (ParentAndKind.getInt() == ASTHierarchy::Package) {
279+
return const_cast<PackageUnit *>(cast<PackageUnit>(this));
280+
}
281+
282+
if (lookupIfNotCurrent) {
283+
auto mdecl = getParentModule();
284+
return mdecl->getPackage();
285+
}
286+
return nullptr;
283287
}
284288

285289
ModuleDecl *DeclContext::getParentModule() const {
290+
if (auto pkg = getPackageContext()) {
291+
auto &mdecl = pkg->getSourceModule();
292+
return &mdecl;
293+
}
294+
286295
const DeclContext *DC = this;
287296
while (!DC->isModuleContext())
288297
DC = DC->getParent();
@@ -292,7 +301,7 @@ ModuleDecl *DeclContext::getParentModule() const {
292301
SourceFile *DeclContext::getParentSourceFile() const {
293302
const DeclContext *DC = this;
294303
SourceLoc loc;
295-
while (!DC->isModuleScopeContext()) {
304+
while (DC && !DC->isModuleScopeContext()) {
296305
// If we don't have a source location yet, try to grab one from this
297306
// context.
298307
if (loc.isInvalid()) {
@@ -323,6 +332,9 @@ SourceFile *DeclContext::getParentSourceFile() const {
323332
DC = DC->getParent();
324333
}
325334

335+
if (!DC)
336+
return nullptr;
337+
326338
auto fallbackSF = const_cast<SourceFile *>(dyn_cast<SourceFile>(DC));
327339
if (auto module = DC->getParentModule()) {
328340
if (auto sf = module->getSourceFileContainingLocation(loc))
@@ -345,15 +357,19 @@ SourceFile *DeclContext::getOutermostParentSourceFile() const {
345357
}
346358

347359
DeclContext *DeclContext::getModuleScopeContext() const {
348-
auto DC = const_cast<DeclContext*>(this);
360+
if (auto pkg = getPackageContext()) {
361+
auto &mdecl = pkg->getSourceModule();
362+
return &mdecl;
363+
}
349364

365+
auto DC = const_cast<DeclContext*>(this);
350366
while (true) {
351367
if (DC->ParentAndKind.getInt() == ASTHierarchy::FileUnit)
352368
return DC;
353369
if (auto NextDC = DC->getParent()) {
354370
DC = NextDC;
355371
} else {
356-
assert(isa<ModuleDecl>(DC->getAsDecl()));
372+
assert(DC && isa<ModuleDecl>(DC->getAsDecl()) && "no module decl context found!");
357373
return DC;
358374
}
359375
}
@@ -1235,6 +1251,11 @@ bool AccessScope::isInternal() const {
12351251
return DC && isa<ModuleDecl>(DC);
12361252
}
12371253

1254+
bool AccessScope::isPackage() const {
1255+
auto DC = getDeclContext();
1256+
return DC && isa<PackageUnit>(DC);
1257+
}
1258+
12381259
AccessLevel AccessScope::accessLevelForDiagnostics() const {
12391260
if (isPublic())
12401261
return AccessLevel::Public;
@@ -1254,6 +1275,11 @@ bool AccessScope::allowsPrivateAccess(const DeclContext *useDC, const DeclContex
12541275
if (useDC->isChildContextOf(sourceDC))
12551276
return true;
12561277

1278+
if (auto srcPkg = sourceDC->getPackageContext()) {
1279+
if (auto usePkg = sourceDC->getPackageContext(true)) {
1280+
return usePkg->isSamePackageAs(srcPkg);
1281+
}
1282+
}
12571283
// Do not allow access if the sourceDC is in a different file
12581284
auto useSF = useDC->getParentSourceFile();
12591285
if (useSF != sourceDC->getParentSourceFile())

lib/AST/Module.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -543,11 +543,6 @@ void SourceLookupCache::invalidate() {
543543
(void)SameSizeSmallVector{std::move(AllVisibleValues)};
544544
}
545545

546-
PackageUnit::PackageUnit(Identifier name)
547-
: DeclContext(DeclContextKind::Package, nullptr) {
548-
PackageName = name;
549-
}
550-
551546
//===----------------------------------------------------------------------===//
552547
// Module Implementation
553548
//===----------------------------------------------------------------------===//
@@ -3068,6 +3063,11 @@ SourceFile::getImportAccessLevel(const ModuleDecl *targetModule) const {
30683063
return restrictiveImport;
30693064
}
30703065

3066+
void ModuleDecl::setPackageName(Identifier name) {
3067+
PackageName = name;
3068+
Package = PackageUnit::create(name, *this, getASTContext());
3069+
}
3070+
30713071
bool ModuleDecl::isImportedImplementationOnly(const ModuleDecl *module) const {
30723072
if (module == this) return false;
30733073

lib/Sema/TypeCheckAccess.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2286,7 +2286,7 @@ static void checkExtensionGenericParamAccess(const ExtensionDecl *ED) {
22862286
desiredAccessScope = AccessScope(ED->getModuleContext());
22872287
break;
22882288
case AccessLevel::Package:
2289-
desiredAccessScope = AccessScope::getPackage();
2289+
desiredAccessScope = AccessScope(ED->getPackageContext(true));
22902290
break;
22912291
case AccessLevel::Public:
22922292
case AccessLevel::Open:

test/Sema/accessibility.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -enable-objc-interop -disable-objc-attr-requires-foundation-module -swift-version 5
1+
// RUN: %target-typecheck-verify-swift -enable-objc-interop -disable-objc-attr-requires-foundation-module -swift-version 5 -package-name mylib
22

33
/// Test structs with protocols and extensions
44
public protocol PublicProto {
@@ -1021,8 +1021,8 @@ public struct PublicWithInternalSettersConformPublic : PublicMutationOperations
10211021
}
10221022

10231023
public struct PublicWithPackageSettersConformPublic : PublicMutationOperations {
1024-
public package(set) var size = 0 // FIXME: rdar://104987295 this should error
1025-
public package(set) subscript (_: Int) -> Int { // FIXME: rdar://104987295 this should error
1024+
public package(set) var size = 0 // expected-error {{setter for property 'size' must be declared public because it matches a requirement in public protocol 'PublicMutationOperations'}} {{none}} expected-note {{mark the property as 'public' to satisfy the requirement}} {{10-23=}}
1025+
public package(set) subscript (_: Int) -> Int { // expected-error {{subscript setter must be declared public because it matches a requirement in public protocol 'PublicMutationOperations'}} {{none}} expected-note {{mark the subscript as 'public' to satisfy the requirement}} {{10-23=}}
10261026
get { return 42 }
10271027
set {}
10281028
}

0 commit comments

Comments
 (0)