mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Sema: Intro ExportedLevel and use it for isExported
This commit is contained in:
@@ -24,6 +24,19 @@
|
||||
|
||||
namespace swift {
|
||||
|
||||
/// How a decl is exported.
|
||||
enum class ExportedLevel {
|
||||
/// Not exported.
|
||||
None,
|
||||
|
||||
/// Exported implicitly for types in non-library-evolution mode not marked
|
||||
/// `@_implementationOnly`.
|
||||
ImplicitlyExported,
|
||||
|
||||
/// Explicitly marked as exported with public or `@frozen`.
|
||||
Exported
|
||||
};
|
||||
|
||||
/// This visitor determines whether a declaration is "exportable", meaning whether
|
||||
/// it can be referenced by other modules. For example, a function with a public
|
||||
/// access level or with the `@usableFromInline` attribute is exportable.
|
||||
@@ -183,13 +196,13 @@ public:
|
||||
/// Check if a declaration is exported as part of a module's external interface.
|
||||
/// This includes public and @usableFromInline decls.
|
||||
/// FIXME: This is legacy that should be subsumed by `DeclExportabilityVisitor`
|
||||
bool isExported(const Decl *D);
|
||||
ExportedLevel isExported(const Decl *D);
|
||||
|
||||
/// A specialization of `isExported` for `ValueDecl`.
|
||||
bool isExported(const ValueDecl *VD);
|
||||
ExportedLevel isExported(const ValueDecl *VD);
|
||||
|
||||
/// A specialization of `isExported` for `ExtensionDecl`.
|
||||
bool isExported(const ExtensionDecl *ED);
|
||||
ExportedLevel isExported(const ExtensionDecl *ED);
|
||||
|
||||
/// Returns true if the extension declares any protocol conformances that
|
||||
/// require the extension to be exported.
|
||||
|
||||
@@ -972,7 +972,7 @@ bool ASTContext::supportsVersionedAvailability() const {
|
||||
return minimumAvailableOSVersionForTriple(LangOpts.Target).has_value();
|
||||
}
|
||||
|
||||
bool swift::isExported(const Decl *D) {
|
||||
ExportedLevel swift::isExported(const Decl *D) {
|
||||
if (auto *VD = dyn_cast<ValueDecl>(D)) {
|
||||
return isExported(VD);
|
||||
}
|
||||
@@ -982,32 +982,36 @@ bool swift::isExported(const Decl *D) {
|
||||
return isExported(VD);
|
||||
}
|
||||
|
||||
return false;
|
||||
return ExportedLevel::None;
|
||||
}
|
||||
if (auto *ED = dyn_cast<ExtensionDecl>(D)) {
|
||||
return isExported(ED);
|
||||
}
|
||||
|
||||
return true;
|
||||
return ExportedLevel::Exported;
|
||||
}
|
||||
|
||||
bool swift::isExported(const ValueDecl *VD) {
|
||||
ExportedLevel swift::isExported(const ValueDecl *VD) {
|
||||
if (VD->getAttrs().hasAttribute<ImplementationOnlyAttr>())
|
||||
return false;
|
||||
return ExportedLevel::None;
|
||||
if (VD->isObjCMemberImplementation())
|
||||
return false;
|
||||
return ExportedLevel::None;
|
||||
|
||||
// Is this part of the module's API or ABI?
|
||||
AccessScope accessScope =
|
||||
VD->getFormalAccessScope(nullptr,
|
||||
/*treatUsableFromInlineAsPublic*/ true);
|
||||
if (accessScope.isPublic())
|
||||
return true;
|
||||
return ExportedLevel::Exported;
|
||||
|
||||
// Is this a stored property in a @frozen struct or class?
|
||||
if (auto *property = dyn_cast<VarDecl>(VD))
|
||||
if (property->isLayoutExposedToClients(/*applyImplicit=*/true))
|
||||
return true;
|
||||
return ExportedLevel::Exported;
|
||||
|
||||
// Case of an enum not marked @_implementationOnly in a non-resilient module?
|
||||
if (auto *EED = dyn_cast<EnumElementDecl>(VD))
|
||||
return isExported(EED->getParentEnum());
|
||||
|
||||
// Is this a type exposed by default in a non-resilient module?
|
||||
if (isa<NominalTypeDecl>(VD) &&
|
||||
@@ -1016,13 +1020,9 @@ bool swift::isExported(const ValueDecl *VD) {
|
||||
VD->getDeclContext()->getParentModule()->getResilienceStrategy() !=
|
||||
ResilienceStrategy::Resilient &&
|
||||
!VD->getAttrs().hasAttribute<ImplementationOnlyAttr>())
|
||||
return true;
|
||||
return ExportedLevel::Exported;
|
||||
|
||||
// Case of an enum not marked @_implementationOnly in a non-resilient module?
|
||||
if (auto *EED = dyn_cast<EnumElementDecl>(VD))
|
||||
return isExported(EED->getParentEnum());
|
||||
|
||||
return false;
|
||||
return ExportedLevel::None;
|
||||
}
|
||||
|
||||
bool swift::hasConformancesToPublicProtocols(const ExtensionDecl *ED) {
|
||||
@@ -1046,23 +1046,22 @@ bool swift::hasConformancesToPublicProtocols(const ExtensionDecl *ED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool swift::isExported(const ExtensionDecl *ED) {
|
||||
ExportedLevel swift::isExported(const ExtensionDecl *ED) {
|
||||
// An extension can only be exported if it extends an exported type.
|
||||
if (auto *NTD = ED->getExtendedNominal()) {
|
||||
if (!isExported(NTD))
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there are any exported members then the extension is exported.
|
||||
for (const Decl *D : ED->getMembers()) {
|
||||
if (isExported(D))
|
||||
return true;
|
||||
if (isExported(NTD) == ExportedLevel::None)
|
||||
return ExportedLevel::None;
|
||||
}
|
||||
|
||||
// If the extension declares a conformance to a public protocol then the
|
||||
// extension is exported.
|
||||
if (hasConformancesToPublicProtocols(ED))
|
||||
return true;
|
||||
return ExportedLevel::Exported;
|
||||
|
||||
return false;
|
||||
// If there are any exported members then the extension is exported.
|
||||
ExportedLevel exported = ExportedLevel::None;
|
||||
for (const Decl *D : ED->getMembers())
|
||||
exported = std::max(exported, isExported(D));
|
||||
|
||||
return exported;
|
||||
}
|
||||
|
||||
@@ -479,7 +479,7 @@ private:
|
||||
if (decl->isSPI())
|
||||
return true;
|
||||
|
||||
return !isExported(decl);
|
||||
return isExported(decl) == ExportedLevel::None;
|
||||
}
|
||||
|
||||
/// Returns the source range which should be refined by declaration. This
|
||||
|
||||
@@ -2603,7 +2603,7 @@ public:
|
||||
auto *valueMember = dyn_cast<ValueDecl>(member);
|
||||
if (!valueMember)
|
||||
return false;
|
||||
return isExported(valueMember);
|
||||
return isExported(valueMember) == ExportedLevel::Exported;
|
||||
});
|
||||
|
||||
Where = wasWhere.withExported(hasExportedMembers);
|
||||
|
||||
@@ -178,7 +178,7 @@ ExportContext ExportContext::forDeclSignature(Decl *D) {
|
||||
computeExportContextBits(Ctx, D, &spi, &implicit);
|
||||
});
|
||||
|
||||
bool exported = ::isExported(D);
|
||||
bool exported = ::isExported(D) != ExportedLevel::None;
|
||||
|
||||
return ExportContext(DC, availabilityContext, fragileKind, nullptr,
|
||||
spi, exported, implicit);
|
||||
|
||||
@@ -2755,7 +2755,7 @@ static bool requiresCorrespondingUnderscoredCoroutineAccessorImpl(
|
||||
return false;
|
||||
|
||||
// Non-exported storage has no ABI to keep stable.
|
||||
if (!isExported(storage))
|
||||
if (isExported(storage) == ExportedLevel::None)
|
||||
return false;
|
||||
|
||||
// The non-underscored accessor is not present, the underscored accessor
|
||||
|
||||
Reference in New Issue
Block a user