Skip to content

Commit f083c4b

Browse files
authored
Merge pull request #85919 from slavapestov/strict-access-control
Sema: New StrictAccessControl upcoming feature
2 parents 7cea2b8 + ea58732 commit f083c4b

File tree

7 files changed

+71
-24
lines changed

7 files changed

+71
-24
lines changed

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ MIGRATABLE_UPCOMING_FEATURE(MemberImportVisibility, 444, 7)
303303
MIGRATABLE_UPCOMING_FEATURE(InferIsolatedConformances, 470, 7)
304304
MIGRATABLE_UPCOMING_FEATURE(NonisolatedNonsendingByDefault, 461, 7)
305305
UPCOMING_FEATURE(ImmutableWeakCaptures, 481, 7)
306+
UPCOMING_FEATURE(StrictAccessControl, 0, 7)
306307

307308
// Optional language features / modes
308309

lib/AST/FeatureSet.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ static bool usesFeatureTildeSendable(Decl *decl) {
500500
}
501501

502502
UNINTERESTING_FEATURE(AnyAppleOSAvailability)
503+
UNINTERESTING_FEATURE(StrictAccessControl)
503504

504505
// ----------------------------------------------------------------------------
505506
// MARK: - FeatureSet

lib/Sema/ResilienceDiagnostics.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,9 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
119119
}
120120

121121
// Swift 5.0 did not check the underlying types of local typealiases.
122-
if (isa<TypeAliasDecl>(DC) && !Context.isLanguageModeAtLeast(6))
122+
if (isa<TypeAliasDecl>(DC) &&
123+
!Context.LangOpts.hasFeature(Feature::StrictAccessControl) &&
124+
!Context.isLanguageModeAtLeast(6))
123125
downgradeToWarning = DowngradeToWarning::Yes;
124126

125127
auto diagID = diag::resilience_decl_unavailable;
@@ -207,7 +209,8 @@ static bool diagnoseTypeAliasDeclRefExportability(SourceLoc loc,
207209
}
208210
D->diagnose(diag::kind_declared_here, DescriptiveDeclKind::Type);
209211

210-
if (originKind == DisallowedOriginKind::MissingImport &&
212+
if (!ctx.LangOpts.hasFeature(Feature::StrictAccessControl) &&
213+
originKind == DisallowedOriginKind::MissingImport &&
211214
!ctx.isLanguageModeAtLeast(6))
212215
addMissingImport(loc, D, where);
213216

@@ -460,7 +463,8 @@ TypeChecker::diagnoseConformanceExportability(SourceLoc loc,
460463
originKind == DisallowedOriginKind::MissingImport,
461464
6);
462465

463-
if (originKind == DisallowedOriginKind::MissingImport &&
466+
if (!ctx.LangOpts.hasFeature(Feature::StrictAccessControl) &&
467+
originKind == DisallowedOriginKind::MissingImport &&
464468
!ctx.isLanguageModeAtLeast(6))
465469
addMissingImport(loc, ext, where);
466470

lib/Sema/TypeCheckAccess.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -550,11 +550,12 @@ void AccessControlCheckerBase::checkGenericParamAccess(
550550
if (minAccessScope.isPublic())
551551
return;
552552

553-
// FIXME: Promote these to an error in the next -swift-version break.
554-
if (isa<SubscriptDecl>(ownerDecl) || isa<TypeAliasDecl>(ownerDecl))
553+
auto &Context = ownerDecl->getASTContext();
554+
555+
if (!Context.LangOpts.hasFeature(Feature::StrictAccessControl) &&
556+
(isa<SubscriptDecl>(ownerDecl) || isa<TypeAliasDecl>(ownerDecl)))
555557
downgradeToWarning = DowngradeToWarning::Yes;
556558

557-
auto &Context = ownerDecl->getASTContext();
558559
if (checkUsableFromInline) {
559560
if (!Context.isLanguageModeAtLeast(5))
560561
downgradeToWarning = DowngradeToWarning::Yes;
@@ -2042,14 +2043,16 @@ swift::getDisallowedOriginKind(const Decl *decl,
20422043
downgradeToWarning = DowngradeToWarning::No;
20432044
ModuleDecl *M = decl->getModuleContext();
20442045
auto *SF = where.getDeclContext()->getParentSourceFile();
2046+
auto &Context = M->getASTContext();
20452047

20462048
RestrictedImportKind howImported = SF->getRestrictedImportKind(M);
20472049
if (howImported != RestrictedImportKind::None) {
20482050
// Temporarily downgrade implementation-only exportability in SPI to
20492051
// a warning.
2050-
if (where.isSPI() &&
2052+
if (!Context.LangOpts.hasFeature(Feature::StrictAccessControl) &&
2053+
where.isSPI() &&
20512054
where.getFragileFunctionKind().kind == FragileFunctionKind::None &&
2052-
!SF->getASTContext().LangOpts.EnableSPIOnlyImports)
2055+
!Context.LangOpts.EnableSPIOnlyImports)
20532056
downgradeToWarning = DowngradeToWarning::Yes;
20542057

20552058
if (where.isSPI() && howImported == RestrictedImportKind::SPIOnly)
@@ -2058,8 +2061,9 @@ swift::getDisallowedOriginKind(const Decl *decl,
20582061
// Before Swift 6, implicit imports were not reported unless an
20592062
// implementation-only import was also present. Downgrade to a warning
20602063
// just in this case.
2061-
if (howImported == RestrictedImportKind::MissingImport &&
2062-
!SF->getASTContext().isLanguageModeAtLeast(6) &&
2064+
if (!Context.LangOpts.hasFeature(Feature::StrictAccessControl) &&
2065+
howImported == RestrictedImportKind::MissingImport &&
2066+
!Context.isLanguageModeAtLeast(6) &&
20632067
!SF->hasImportsWithFlag(ImportFlags::ImplementationOnly)) {
20642068
downgradeToWarning = DowngradeToWarning::Yes;
20652069
}
@@ -2087,7 +2091,7 @@ swift::getDisallowedOriginKind(const Decl *decl,
20872091
if (!owningModule)
20882092
continue;
20892093
auto moduleWrapper =
2090-
decl->getASTContext().getClangModuleLoader()->getWrapperForModule(
2094+
Context.getClangModuleLoader()->getWrapperForModule(
20912095
owningModule);
20922096
auto visibleAccessPath =
20932097
find_if(sfImportedModules, [&moduleWrapper](auto importedModule) {
@@ -2150,7 +2154,7 @@ swift::getDisallowedOriginKind(const Decl *decl,
21502154
}
21512155

21522156
// C++ APIs do not support library evolution.
2153-
if (SF->getASTContext().LangOpts.EnableCXXInterop && where.getDeclContext() &&
2157+
if (Context.LangOpts.EnableCXXInterop && where.getDeclContext() &&
21542158
where.getDeclContext()->getAsDecl() &&
21552159
where.getDeclContext()->getAsDecl()->getModuleContext()->isResilient() &&
21562160
!where.getDeclContext()
@@ -2159,13 +2163,13 @@ swift::getDisallowedOriginKind(const Decl *decl,
21592163
->getUnderlyingModuleIfOverlay() &&
21602164
decl->hasClangNode() && !decl->getModuleContext()->isSwiftShimsModule() &&
21612165
isFragileClangNode(decl->getClangNode()) &&
2162-
!SF->getASTContext().LangOpts.hasFeature(
2166+
!Context.LangOpts.hasFeature(
21632167
Feature::AssumeResilientCxxTypes))
21642168
return DisallowedOriginKind::FragileCxxAPI;
21652169

21662170
// Implementation-only memory layouts for non-library-evolution mode.
21672171
if (isa<NominalTypeDecl>(decl) &&
2168-
decl->getASTContext().LangOpts.hasFeature(
2172+
Context.LangOpts.hasFeature(
21692173
Feature::CheckImplementationOnly) &&
21702174
decl->getAttrs().hasAttribute<ImplementationOnlyAttr>())
21712175
return DisallowedOriginKind::ImplementationOnlyMemoryLayout;

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,7 +1087,7 @@ static bool diagnosePotentialUnavailability(
10871087
// Don't downgrade
10881088
} else if (behaviorLimit >= DiagnosticBehavior::Warning) {
10891089
err.limitBehavior(behaviorLimit);
1090-
} else {
1090+
} else if (!ctx.LangOpts.hasFeature(Feature::StrictAccessControl)) {
10911091
err.warnUntilLanguageMode(6);
10921092
}
10931093

@@ -2179,7 +2179,8 @@ bool diagnoseExplicitUnavailability(
21792179
// obsolete decls still map to valid ObjC runtime names, so behave correctly
21802180
// at runtime, even though their use would produce an error outside of a
21812181
// #keyPath expression.
2182-
auto limit = Flags.contains(DeclAvailabilityFlag::ForObjCKeyPath)
2182+
auto limit = (!ctx.LangOpts.hasFeature(Feature::StrictAccessControl) &&
2183+
Flags.contains(DeclAvailabilityFlag::ForObjCKeyPath))
21832184
? DiagnosticBehavior::Warning
21842185
: DiagnosticBehavior::Unspecified;
21852186

@@ -2968,10 +2969,12 @@ diagnoseDeclAsyncAvailability(const ValueDecl *D, SourceRange R,
29682969
attr->getMessage());
29692970
if (D->preconcurrency()) {
29702971
diag.limitBehavior(DiagnosticBehavior::Warning);
2971-
} else if (shouldWarnUntilFutureVersion()) {
2972-
diag.warnUntilFutureLanguageMode();
2973-
} else {
2974-
diag.warnUntilLanguageMode(6);
2972+
} else if (!ctx.LangOpts.hasFeature(Feature::StrictAccessControl)) {
2973+
if (shouldWarnUntilFutureVersion()) {
2974+
diag.warnUntilFutureLanguageMode();
2975+
} else {
2976+
diag.warnUntilLanguageMode(6);
2977+
}
29752978
}
29762979

29772980
if (!attr->getRename().empty()) {
@@ -2992,10 +2995,12 @@ diagnoseDeclAsyncAvailability(const ValueDecl *D, SourceRange R,
29922995
SourceLoc diagLoc = call ? call->getLoc() : R.Start;
29932996
auto diag = ctx.Diags.diagnose(diagLoc, diag::async_unavailable_decl, D,
29942997
attr->Message);
2995-
if (shouldWarnUntilFutureVersion()) {
2996-
diag.warnUntilFutureLanguageMode();
2997-
} else {
2998-
diag.warnUntilLanguageMode(6);
2998+
if (!ctx.LangOpts.hasFeature(Feature::StrictAccessControl)) {
2999+
if (shouldWarnUntilFutureVersion()) {
3000+
diag.warnUntilFutureLanguageMode();
3001+
} else {
3002+
diag.warnUntilLanguageMode(6);
3003+
}
29993004
}
30003005
}
30013006
D->diagnose(diag::decl_declared_here, D);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
public struct ImplementationOnly {}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/Other.swiftmodule %S/Inputs/strict_access_control_other.swift -module-name Other -swift-version 5
3+
// RUN: %target-typecheck-verify-swift -enable-upcoming-feature StrictAccessControl -swift-version 5 -enable-library-evolution -I %t -verify-ignore-unrelated
4+
5+
// REQUIRES: swift_feature_StrictAccessControl
6+
7+
@_implementationOnly import Other
8+
// expected-warning@-1 {{'@_implementationOnly' is deprecated, use 'internal import' instead}}
9+
10+
private struct PrivateType {}
11+
// expected-note@-1 {{struct 'PrivateType' is not '@usableFromInline' or public}}
12+
13+
@inlinable public func localTypeAliasTest() {
14+
typealias Bad = PrivateType
15+
// expected-error@-1 {{struct 'PrivateType' is private and cannot be referenced from an '@inlinable' function}}
16+
}
17+
18+
private protocol PrivateProtocol {}
19+
// expected-note@-1 2{{type declared here}}
20+
21+
public typealias BadRequirements<T> = T where T: PrivateProtocol
22+
// expected-error@-1 {{generic type alias cannot be declared public because its generic requirement uses a private type}}
23+
24+
public struct S {
25+
public subscript<T>(_: T) -> T where T: PrivateProtocol { fatalError() }
26+
// expected-error@-1 {{subscript cannot be declared public because its generic requirement uses a private type}}
27+
}
28+
29+
@_spi(Testing)
30+
public func badImplementationOnlyExport(_: ImplementationOnly) {}
31+
// expected-error@-1 {{cannot use struct 'ImplementationOnly' here; 'Other' has been imported as implementation-only}}

0 commit comments

Comments
 (0)