Merge pull request #85868 from xymus/exportability-nle-split

Sema: Distinguish implicitly visible memory layouts from the typical `@frozen` ones
This commit is contained in:
Alexis Laferrière
2025-12-08 13:29:16 -08:00
committed by GitHub
13 changed files with 268 additions and 165 deletions

View File

@@ -81,6 +81,7 @@ namespace swift {
class DiagnosticEngine;
class DynamicSelfType;
class Type;
enum class ExportedLevel;
class Expr;
struct ExternalSourceLocs;
class CaptureListExpr;
@@ -6755,10 +6756,7 @@ public:
///
/// From the standpoint of access control and exportability checking, this
/// var will behave as if it was public, even if it is internal or private.
///
/// If \p applyImplicit, consider implicitly exposed layouts as well.
/// This applies to non-resilient modules.
bool isLayoutExposedToClients(bool applyImplicit = false) const;
ExportedLevel isLayoutExposedToClients() const;
/// Is this a special debugger variable?
bool isDebuggerVar() const { return Bits.VarDecl.IsDebuggerVar; }

View File

@@ -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.
@@ -102,7 +115,7 @@ public:
}
bool visitVarDecl(const VarDecl *var) {
if (var->isLayoutExposedToClients())
if (var->isLayoutExposedToClients() == ExportedLevel::Exported)
return true;
// Consider all lazy var storage as 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.

View File

@@ -3840,14 +3840,18 @@ NOTE(enum_raw_value_incrementing_from_zero,none,
NOTE(construct_raw_representable_from_unwrapped_value,none,
"construct %0 from unwrapped %1 value", (Type, Type))
#define EXPORTABILITY_REASON_SELECT "select{" \
"here|as property wrapper here|" \
"as result builder here|" \
"in an extension with public or '@usableFromInline' members|" \
"in an extension with conditional conformances|" \
"in a public or '@usableFromInline' conformance|" \
"in an '@available' attribute here|" \
"in a property declaration marked public or in a '@frozen' or '@usableFromInline' context|" \
"in a property declaration member of a type not marked '@_implementationOnly'}"
ERROR(decl_from_hidden_module,none,
"cannot use %kind0 %select{here|as property wrapper here|"
"as result builder here|"
"in an extension with public or '@usableFromInline' members|"
"in an extension with conditional conformances|"
"in a public or '@usableFromInline' conformance|"
"in an '@available' attribute here|"
"in a property declaration marked public or in a '@frozen' or '@usableFromInline' context}1; "
"cannot use %kind0 %" EXPORTABILITY_REASON_SELECT "1; "
"%select{%2 has been imported as implementation-only|"
"it is an SPI imported from %2|"
"it is SPI|"
@@ -3859,14 +3863,7 @@ ERROR(decl_from_hidden_module,none,
"%0 is marked '@_implementationOnly'}3",
(const Decl *, unsigned, Identifier, unsigned))
ERROR(typealias_desugars_to_type_from_hidden_module,none,
"%0 aliases '%1.%2' and cannot be used %select{here|"
"as property wrapper here|"
"as result builder here|"
"in an extension with public or '@usableFromInline' members|"
"in an extension with conditional conformance|"
"in a public or '@usableFromInline' conformance|"
"<<ERROR>>|"
"in a property declaration marked public or in a '@frozen' or '@usableFromInline' context}3 "
"%0 aliases '%1.%2' and cannot be used %" EXPORTABILITY_REASON_SELECT "3 "
"because %select{%4 has been imported as implementation-only|"
"it is an SPI imported from %4|"
"<<ERROR>>|"
@@ -3878,12 +3875,7 @@ ERROR(typealias_desugars_to_type_from_hidden_module,none,
"%0 is marked '@_implementationOnly'}5",
(const TypeAliasDecl *, StringRef, StringRef, unsigned, Identifier, unsigned))
ERROR(conformance_from_implementation_only_module,none,
"cannot use conformance of %0 to %1 %select{here|as property wrapper here|"
"as result builder here|"
"in an extension with public or '@usableFromInline' members|"
"in an extension with conditional conformances|"
"<<ERROR>>|<<ERROR>>|"
"in a property declaration marked public or in a '@frozen' or '@usableFromInline' context}2; "
"cannot use conformance of %0 to %1 %" EXPORTABILITY_REASON_SELECT "2; "
"%select{%3 has been imported as implementation-only|"
"the conformance is declared as SPI in %3|"
"the conformance is declared as SPI|"