Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -3855,9 +3855,12 @@ NOTE(construct_raw_representable_from_unwrapped_value,none,
"in an extension with public or '@usableFromInline' members|" \
"in an extension with conditional conformances|" \
"in a public or '@usableFromInline' conformance|" \
"in a conformance on a type not marked '@_implementationOnly'|" \
"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'}"
"in a property declaration member of a type not marked '@_implementationOnly'|" \
"in an associated value of a public or '@usableFromInline' enum|" \
"in an associated value of an enum not marked '@_implementationOnly'}"

ERROR(decl_from_hidden_module,none,
"cannot use %kind0 %" EXPORTABILITY_REASON_SELECT "1; "
Expand Down Expand Up @@ -3958,9 +3961,6 @@ ERROR(implementation_only_override_import_without_attr,none,
"override of %kindonly0 imported as implementation-only must be declared "
"'@_implementationOnly'",
(const ValueDecl *))
ERROR(implementation_only_on_types_feature,none,
"'@_implementationOnly' on a type requires "
"'-enable-experimental-feature CheckImplementationOnly'", ())

ERROR(import_attr_conflict,none,
"%0 inconsistently imported with %1",
Expand Down
14 changes: 8 additions & 6 deletions lib/AST/Availability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1047,20 +1047,22 @@ bool swift::hasConformancesToPublicProtocols(const ExtensionDecl *ED) {

ExportedLevel swift::isExported(const ExtensionDecl *ED) {
// An extension can only be exported if it extends an exported type.
ExportedLevel exported = ExportedLevel::None;
if (auto *NTD = ED->getExtendedNominal()) {
if (isExported(NTD) == ExportedLevel::None)
return ExportedLevel::None;
exported = isExported(NTD);
if (exported == ExportedLevel::None)
return exported;
}

// If the extension declares a conformance to a public protocol then the
// extension is exported.
if (hasConformancesToPublicProtocols(ED))
return ExportedLevel::Exported;
return exported;

// If there are any exported members then the extension is exported.
ExportedLevel exported = ExportedLevel::None;
ExportedLevel membersExported = ExportedLevel::None;
for (const Decl *D : ED->getMembers())
exported = std::max(exported, isExported(D));
membersExported = std::max(membersExported, isExported(D));

return exported;
return membersExported;
}
3 changes: 3 additions & 0 deletions lib/Sema/ResilienceDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ static bool shouldDiagnoseDeclAccess(const ValueDecl *D,
case ExportabilityReason::ExtensionWithConditionalConformances:
return true;
case ExportabilityReason::Inheritance:
case ExportabilityReason::ImplicitlyPublicInheritance:
return isa<ProtocolDecl>(D);
case ExportabilityReason::AvailableAttribute:
// If the context is an extension and that extension has an explicit
Expand All @@ -262,6 +263,8 @@ static bool shouldDiagnoseDeclAccess(const ValueDecl *D,
case ExportabilityReason::PropertyWrapper:
case ExportabilityReason::PublicVarDecl:
case ExportabilityReason::ImplicitlyPublicVarDecl:
case ExportabilityReason::AssociatedValue:
case ExportabilityReason::ImplicitlyPublicAssociatedValue:
return false;
}
}
Expand Down
18 changes: 15 additions & 3 deletions lib/Sema/TypeCheckAccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2493,9 +2493,13 @@ class DeclAvailabilityChecker : public DeclVisitor<DeclAvailabilityChecker> {
flags |= DeclAvailabilityFlag::
AllowPotentiallyUnavailableAtOrBelowDeploymentTarget;

ExportabilityReason reason =
Where.getExportedLevel() == ExportedLevel::ImplicitlyExported ?
ExportabilityReason::ImplicitlyPublicInheritance :
ExportabilityReason::Inheritance;
for (TypeLoc inherited : nominal->getInherited().getEntries()) {
checkType(inherited.getType(), inherited.getTypeRepr(), nominal,
ExportabilityReason::Inheritance,
reason,
flags | DeclAvailabilityFlag::DisableUnsafeChecking);
}
}
Expand Down Expand Up @@ -2559,8 +2563,12 @@ class DeclAvailabilityChecker : public DeclVisitor<DeclAvailabilityChecker> {
void visitEnumElementDecl(EnumElementDecl *EED) {
if (!EED->hasAssociatedValues())
return;
ExportabilityReason reason =
Where.getExportedLevel() == ExportedLevel::ImplicitlyExported ?
ExportabilityReason::ImplicitlyPublicAssociatedValue :
ExportabilityReason::AssociatedValue;
for (auto &P : *EED->getParameterList())
checkType(P->getInterfaceType(), P->getTypeRepr(), EED);
checkType(P->getInterfaceType(), P->getTypeRepr(), EED, reason);
}

void visitMacroDecl(MacroDecl *MD) {
Expand Down Expand Up @@ -2597,9 +2605,13 @@ class DeclAvailabilityChecker : public DeclVisitor<DeclAvailabilityChecker> {
// must be exported.
DeclAvailabilityFlags flags = DeclAvailabilityFlag::AllowPotentiallyUnavailableProtocol;
flags |= DeclAvailabilityFlag::DisableUnsafeChecking;
ExportabilityReason inheritanceReason =
Where.getExportedLevel() == ExportedLevel::ImplicitlyExported ?
ExportabilityReason::ImplicitlyPublicInheritance :
ExportabilityReason::Inheritance;
for (TypeLoc inherited : ED->getInherited().getEntries()) {
checkType(inherited.getType(), inherited.getTypeRepr(), ED,
ExportabilityReason::Inheritance, flags);
inheritanceReason, flags);
}

auto wasWhere = Where;
Expand Down
6 changes: 0 additions & 6 deletions lib/Sema/TypeCheckAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5058,12 +5058,6 @@ AttributeChecker::visitImplementationOnlyAttr(ImplementationOnlyAttr *attr) {

// @_implementationOnly on types only applies to non-public types.
if (isa<NominalTypeDecl>(D)) {
if (!Ctx.LangOpts.hasFeature(Feature::CheckImplementationOnly) &&
!Ctx.LangOpts.hasFeature(Feature::CheckImplementationOnlyStrict)) {
diagnoseAndRemoveAttr(attr, diag::implementation_only_on_types_feature);
return;
}

auto access =
VD->getFormalAccessScope(/*useDC=*/nullptr,
/*treatUsableFromInlineAsPublic=*/true);
Expand Down
3 changes: 1 addition & 2 deletions lib/Sema/TypeCheckAvailability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,9 @@ bool ExportContext::canReferenceOrigin(DisallowedOriginKind originKind) const {
// than the library-evolution ones. Implicitly always emit into client code
// in embedded mode and implicitly exported layouts in non-library-evolution
// mode can reference SPIs and non-public dependencies.
auto reason = getExportabilityReason();
if (getFragileFunctionKind().kind ==
FragileFunctionKind::EmbeddedAlwaysEmitIntoClient ||
(reason && *reason == ExportabilityReason::ImplicitlyPublicVarDecl)) {
getExportedLevel() == ExportedLevel::ImplicitlyExported) {
switch (originKind) {
case DisallowedOriginKind::None:
case DisallowedOriginKind::NonPublicImport:
Expand Down
3 changes: 3 additions & 0 deletions lib/Sema/TypeCheckAvailability.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,12 @@ enum class ExportabilityReason : unsigned {
ExtensionWithPublicMembers,
ExtensionWithConditionalConformances,
Inheritance,
ImplicitlyPublicInheritance,
AvailableAttribute,
PublicVarDecl,
ImplicitlyPublicVarDecl,
AssociatedValue,
ImplicitlyPublicAssociatedValue,
};

/// A description of the restrictions on what declarations can be referenced
Expand Down
2 changes: 1 addition & 1 deletion test/SPI/spi_enum_element.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public struct PublicStruct {}

public enum PublicEnumWithPayloads {
case publicCasePublicPayload(_ s: PublicStruct)
case publicCaseSPIPayload(_ s: SPIStruct) // expected-error {{cannot use struct 'SPIStruct' here; it is SPI}}
case publicCaseSPIPayload(_ s: SPIStruct) // expected-error {{cannot use struct 'SPIStruct' in an associated value of a public or '@usableFromInline' enum; it is SPI}}
@_spi(S) case spiCasePublicPayload(_ s: PublicStruct)
@_spi(S) case spiCaseSPIPayload(_ s: SPIStruct)
}
Expand Down
Loading