Skip to content

Commit f26f810

Browse files
authored
Merge pull request swiftlang#62704 from apple/es-pkg2
[NFC] Modify AccessScope to allow checks for package access level
2 parents 65bbe7f + 288dbe3 commit f26f810

File tree

4 files changed

+72
-24
lines changed

4 files changed

+72
-24
lines changed

include/swift/AST/AccessScope.h

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,40 @@
2020

2121
namespace swift {
2222

23+
/// Used to provide the kind of scope limitation in AccessScope::Value
24+
enum class AccessLimitKind : uint8_t { None = 0, Private, Package };
25+
2326
/// The wrapper around the outermost DeclContext from which
2427
/// a particular declaration can be accessed.
2528
class AccessScope {
26-
/// The declaration context (if not public) along with a bit saying
27-
/// whether this scope is private, SPI or not.
28-
/// If the declaration context is set, the bit means that the scope is
29-
/// private or not. If the declaration context is null, the bit means that
30-
/// this scope is SPI or not.
31-
llvm::PointerIntPair<const DeclContext *, 1, bool> Value;
29+
/// The declaration context along with an enum indicating the level of
30+
/// scope limitation.
31+
/// If the declaration context is set, and the limit kind is Private, the
32+
/// access level is considered 'private'. Whether it's 'internal' or
33+
/// 'fileprivate' is determined by what the declaration context casts to. If
34+
/// the declaration context is null, and the limit kind is None, the access
35+
/// level is considered 'public'. If the limit kind is Private, the access
36+
/// level is considered SPI. If it's Package, the access level is considered
37+
/// 'package'. Below is a table showing the combinations.
38+
///
39+
/// AccessLimitKind DC == nullptr DC != nullptr
40+
/// ---------------------------------------------------------------------------
41+
/// None public fileprivate or internal (check DC to tell which)
42+
/// Private `@_spi` public private
43+
/// Package package (unused)
44+
45+
llvm::PointerIntPair<const DeclContext *, 2, AccessLimitKind> Value;
3246

3347
public:
34-
AccessScope(const DeclContext *DC, bool isPrivate = false);
48+
AccessScope(const DeclContext *DC,
49+
AccessLimitKind limitKind = AccessLimitKind::None);
3550

36-
static AccessScope getPublic() { return AccessScope(nullptr, false); }
51+
static AccessScope getPublic() {
52+
return AccessScope(nullptr, AccessLimitKind::None);
53+
}
54+
static AccessScope getPackage() {
55+
return AccessScope(nullptr, AccessLimitKind::Package);
56+
}
3757

3858
/// Check if private access is allowed. This is a lexical scope check in Swift
3959
/// 3 mode. In Swift 4 mode, declarations and extensions of the same type will
@@ -46,25 +66,46 @@ class AccessScope {
4666
bool operator==(AccessScope RHS) const { return Value == RHS.Value; }
4767
bool operator!=(AccessScope RHS) const { return !(*this == RHS); }
4868
bool hasEqualDeclContextWith(AccessScope RHS) const {
69+
if (isPublic())
70+
return RHS.isPublic();
71+
if (isPackage())
72+
return RHS.isPackage();
4973
return getDeclContext() == RHS.getDeclContext();
5074
}
5175

52-
bool isPublic() const { return !Value.getPointer(); }
53-
bool isPrivate() const { return Value.getPointer() && Value.getInt(); }
76+
bool isPublic() const {
77+
return !Value.getPointer() && Value.getInt() == AccessLimitKind::None;
78+
}
79+
bool isPrivate() const {
80+
return Value.getPointer() && Value.getInt() == AccessLimitKind::Private;
81+
}
5482
bool isFileScope() const;
5583
bool isInternal() const;
84+
bool isPackage() const {
85+
return !Value.getPointer() && Value.getInt() == AccessLimitKind::Package;
86+
}
5687

57-
/// Returns true if this is a child scope of the specified other access scope.
58-
///
88+
/// Returns true if this scope is more restrictive than the argument scope.
89+
/// It's often used to compute the min access scope. The order of restrictiveness
90+
/// is: private (most restrictive), fileprivate, internal, package, public (least restrictive).
5991
/// \see DeclContext::isChildContextOf
6092
bool isChildOf(AccessScope AS) const {
61-
if (!isPublic() && !AS.isPublic())
62-
return allowsPrivateAccess(getDeclContext(), AS.getDeclContext());
63-
if (isPublic() && AS.isPublic())
64-
return false;
65-
return AS.isPublic();
93+
if (isInternalOrLess()) {
94+
if (AS.isInternalOrLess())
95+
return allowsPrivateAccess(getDeclContext(), AS.getDeclContext());
96+
else
97+
return AS.isPackage() || AS.isPublic();
98+
}
99+
if (isPackage())
100+
return AS.isPublic();
101+
102+
// If this is public, it can't be less than access level of AS
103+
// so return false
104+
return false;
66105
}
67106

107+
bool isInternalOrLess() const { return getDeclContext() != nullptr; }
108+
68109
/// Returns the associated access level for diagnostic purposes.
69110
AccessLevel accessLevelForDiagnostics() const;
70111

lib/AST/Decl.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3732,11 +3732,13 @@ getAccessScopeForFormalAccess(const ValueDecl *VD,
37323732
while (!resultDC->isModuleScopeContext()) {
37333733
if (isa<TopLevelCodeDecl>(resultDC)) {
37343734
return AccessScope(resultDC->getModuleScopeContext(),
3735-
access == AccessLevel::Private);
3735+
access == AccessLevel::Private
3736+
? AccessLimitKind::Private
3737+
: AccessLimitKind::None);
37363738
}
37373739

37383740
if (resultDC->isLocalContext() || access == AccessLevel::Private)
3739-
return AccessScope(resultDC, /*private*/true);
3741+
return AccessScope(resultDC, AccessLimitKind::Private);
37403742

37413743
if (auto enclosingNominal = dyn_cast<GenericTypeDecl>(resultDC)) {
37423744
auto enclosingAccess =
@@ -3767,7 +3769,9 @@ getAccessScopeForFormalAccess(const ValueDecl *VD,
37673769
case AccessLevel::Private:
37683770
case AccessLevel::FilePrivate:
37693771
assert(resultDC->isModuleScopeContext());
3770-
return AccessScope(resultDC, access == AccessLevel::Private);
3772+
return AccessScope(resultDC, access == AccessLevel::Private
3773+
? AccessLimitKind::Private
3774+
: AccessLimitKind::None);
37713775
case AccessLevel::Internal:
37723776
return AccessScope(resultDC->getParentModule());
37733777
case AccessLevel::Public:

lib/AST/DeclContext.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,11 +1180,13 @@ getPrivateDeclContext(const DeclContext *DC, const SourceFile *useSF) {
11801180
return lastExtension ? lastExtension : DC;
11811181
}
11821182

1183-
AccessScope::AccessScope(const DeclContext *DC, bool isPrivate)
1184-
: Value(DC, isPrivate) {
1185-
if (isPrivate) {
1183+
AccessScope::AccessScope(const DeclContext *DC, AccessLimitKind limitKind)
1184+
: Value(DC, limitKind) {
1185+
auto isPrivate = false;
1186+
if (limitKind == AccessLimitKind::Private) {
11861187
DC = getPrivateDeclContext(DC, DC->getParentSourceFile());
11871188
Value.setPointer(DC);
1189+
isPrivate = true;
11881190
}
11891191
if (!DC || isa<ModuleDecl>(DC))
11901192
assert(!isPrivate && "public or internal scope can't be private");

lib/Sema/TypeCheckAccess.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2098,7 +2098,8 @@ static void checkExtensionGenericParamAccess(const ExtensionDecl *ED) {
20982098
case AccessLevel::FilePrivate: {
20992099
const DeclContext *DC = ED->getModuleScopeContext();
21002100
bool isPrivate = (userSpecifiedAccess == AccessLevel::Private);
2101-
desiredAccessScope = AccessScope(DC, isPrivate);
2101+
desiredAccessScope = AccessScope(DC, isPrivate ? AccessLimitKind::Private
2102+
: AccessLimitKind::None);
21022103
break;
21032104
}
21042105
case AccessLevel::Internal:

0 commit comments

Comments
 (0)