Skip to content

Commit bf951b1

Browse files
committed
Sema: Intro ExportedLevel and use it for isExported
1 parent 834bb63 commit bf951b1

File tree

6 files changed

+44
-32
lines changed

6 files changed

+44
-32
lines changed

include/swift/AST/DeclExportabilityVisitor.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,19 @@
2424

2525
namespace swift {
2626

27+
/// How a decl is exported.
28+
enum class ExportedLevel {
29+
/// Not exported.
30+
None,
31+
32+
/// Exported implicitly for types in non-library-evolution mode not marked
33+
/// `@_implementationOnly`.
34+
ImplicitlyExported,
35+
36+
/// Explicitly marked as exported with public or `@frozen`.
37+
Exported
38+
};
39+
2740
/// This visitor determines whether a declaration is "exportable", meaning whether
2841
/// it can be referenced by other modules. For example, a function with a public
2942
/// access level or with the `@usableFromInline` attribute is exportable.
@@ -183,13 +196,13 @@ class DeclExportabilityVisitor
183196
/// Check if a declaration is exported as part of a module's external interface.
184197
/// This includes public and @usableFromInline decls.
185198
/// FIXME: This is legacy that should be subsumed by `DeclExportabilityVisitor`
186-
bool isExported(const Decl *D);
199+
ExportedLevel isExported(const Decl *D);
187200

188201
/// A specialization of `isExported` for `ValueDecl`.
189-
bool isExported(const ValueDecl *VD);
202+
ExportedLevel isExported(const ValueDecl *VD);
190203

191204
/// A specialization of `isExported` for `ExtensionDecl`.
192-
bool isExported(const ExtensionDecl *ED);
205+
ExportedLevel isExported(const ExtensionDecl *ED);
193206

194207
/// Returns true if the extension declares any protocol conformances that
195208
/// require the extension to be exported.

lib/AST/Availability.cpp

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,7 @@ bool ASTContext::supportsVersionedAvailability() const {
972972
return minimumAvailableOSVersionForTriple(LangOpts.Target).has_value();
973973
}
974974

975-
bool swift::isExported(const Decl *D) {
975+
ExportedLevel swift::isExported(const Decl *D) {
976976
if (auto *VD = dyn_cast<ValueDecl>(D)) {
977977
return isExported(VD);
978978
}
@@ -982,32 +982,36 @@ bool swift::isExported(const Decl *D) {
982982
return isExported(VD);
983983
}
984984

985-
return false;
985+
return ExportedLevel::None;
986986
}
987987
if (auto *ED = dyn_cast<ExtensionDecl>(D)) {
988988
return isExported(ED);
989989
}
990990

991-
return true;
991+
return ExportedLevel::Exported;
992992
}
993993

994-
bool swift::isExported(const ValueDecl *VD) {
994+
ExportedLevel swift::isExported(const ValueDecl *VD) {
995995
if (VD->getAttrs().hasAttribute<ImplementationOnlyAttr>())
996-
return false;
996+
return ExportedLevel::None;
997997
if (VD->isObjCMemberImplementation())
998-
return false;
998+
return ExportedLevel::None;
999999

10001000
// Is this part of the module's API or ABI?
10011001
AccessScope accessScope =
10021002
VD->getFormalAccessScope(nullptr,
10031003
/*treatUsableFromInlineAsPublic*/ true);
10041004
if (accessScope.isPublic())
1005-
return true;
1005+
return ExportedLevel::Exported;
10061006

10071007
// Is this a stored property in a @frozen struct or class?
10081008
if (auto *property = dyn_cast<VarDecl>(VD))
10091009
if (property->isLayoutExposedToClients(/*applyImplicit=*/true))
1010-
return true;
1010+
return ExportedLevel::Exported;
1011+
1012+
// Case of an enum not marked @_implementationOnly in a non-resilient module?
1013+
if (auto *EED = dyn_cast<EnumElementDecl>(VD))
1014+
return isExported(EED->getParentEnum());
10111015

10121016
// Is this a type exposed by default in a non-resilient module?
10131017
if (isa<NominalTypeDecl>(VD) &&
@@ -1016,13 +1020,9 @@ bool swift::isExported(const ValueDecl *VD) {
10161020
VD->getDeclContext()->getParentModule()->getResilienceStrategy() !=
10171021
ResilienceStrategy::Resilient &&
10181022
!VD->getAttrs().hasAttribute<ImplementationOnlyAttr>())
1019-
return true;
1020-
1021-
// Case of an enum not marked @_implementationOnly in a non-resilient module?
1022-
if (auto *EED = dyn_cast<EnumElementDecl>(VD))
1023-
return isExported(EED->getParentEnum());
1023+
return ExportedLevel::Exported;
10241024

1025-
return false;
1025+
return ExportedLevel::None;
10261026
}
10271027

10281028
bool swift::hasConformancesToPublicProtocols(const ExtensionDecl *ED) {
@@ -1046,23 +1046,22 @@ bool swift::hasConformancesToPublicProtocols(const ExtensionDecl *ED) {
10461046
return false;
10471047
}
10481048

1049-
bool swift::isExported(const ExtensionDecl *ED) {
1049+
ExportedLevel swift::isExported(const ExtensionDecl *ED) {
10501050
// An extension can only be exported if it extends an exported type.
10511051
if (auto *NTD = ED->getExtendedNominal()) {
1052-
if (!isExported(NTD))
1053-
return false;
1054-
}
1055-
1056-
// If there are any exported members then the extension is exported.
1057-
for (const Decl *D : ED->getMembers()) {
1058-
if (isExported(D))
1059-
return true;
1052+
if (isExported(NTD) == ExportedLevel::None)
1053+
return ExportedLevel::None;
10601054
}
10611055

10621056
// If the extension declares a conformance to a public protocol then the
10631057
// extension is exported.
10641058
if (hasConformancesToPublicProtocols(ED))
1065-
return true;
1059+
return ExportedLevel::Exported;
10661060

1067-
return false;
1061+
// If there are any exported members then the extension is exported.
1062+
ExportedLevel exported = ExportedLevel::None;
1063+
for (const Decl *D : ED->getMembers())
1064+
exported = std::max(exported, isExported(D));
1065+
1066+
return exported;
10681067
}

lib/AST/AvailabilityScopeBuilder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ class AvailabilityScopeBuilder : private ASTWalker {
479479
if (decl->isSPI())
480480
return true;
481481

482-
return !isExported(decl);
482+
return isExported(decl) == ExportedLevel::None;
483483
}
484484

485485
/// Returns the source range which should be refined by declaration. This

lib/Sema/TypeCheckAccess.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2603,7 +2603,7 @@ class DeclAvailabilityChecker : public DeclVisitor<DeclAvailabilityChecker> {
26032603
auto *valueMember = dyn_cast<ValueDecl>(member);
26042604
if (!valueMember)
26052605
return false;
2606-
return isExported(valueMember);
2606+
return isExported(valueMember) == ExportedLevel::Exported;
26072607
});
26082608

26092609
Where = wasWhere.withExported(hasExportedMembers);

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ ExportContext ExportContext::forDeclSignature(Decl *D) {
178178
computeExportContextBits(Ctx, D, &spi, &implicit);
179179
});
180180

181-
bool exported = ::isExported(D);
181+
bool exported = ::isExported(D) != ExportedLevel::None;
182182

183183
return ExportContext(DC, availabilityContext, fragileKind, nullptr,
184184
spi, exported, implicit);

lib/Sema/TypeCheckStorage.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2755,7 +2755,7 @@ static bool requiresCorrespondingUnderscoredCoroutineAccessorImpl(
27552755
return false;
27562756

27572757
// Non-exported storage has no ABI to keep stable.
2758-
if (!isExported(storage))
2758+
if (isExported(storage) == ExportedLevel::None)
27592759
return false;
27602760

27612761
// The non-underscored accessor is not present, the underscored accessor

0 commit comments

Comments
 (0)