Skip to content

Commit 1e40db1

Browse files
authored
Merge pull request #61105 from xymus/default-require-explicit-avail
[Sema] Require explicit availability on public modules and customizable diagnostics level
2 parents a7e5f28 + 4bec9d5 commit 1e40db1

14 files changed

+109
-47
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ ERROR(error_unknown_library_level, none,
4848
"unknown library level '%0', "
4949
"expected one of 'api', 'spi' or 'other'", (StringRef))
5050

51+
ERROR(error_unknown_require_explicit_availability, none,
52+
"unknown argument '%0', passed to -require-explicit-availability, "
53+
"expected 'error', 'warn' or 'ignore'",
54+
(StringRef))
55+
5156
ERROR(error_unsupported_opt_for_target, none,
5257
"unsupported option '%0' for target '%1'", (StringRef, StringRef))
5358

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5779,9 +5779,9 @@ ERROR(availability_protocol_requires_version,
57795779
NOTE(availability_protocol_requirement_here, none,
57805780
"protocol requirement here", ())
57815781

5782-
WARNING(public_decl_needs_availability, none,
5783-
"public declarations should have an availability attribute when building "
5784-
"with -require-explicit-availability", ())
5782+
ERROR(public_decl_needs_availability, none,
5783+
"public declarations should have an availability attribute "
5784+
"with an introduction version", ())
57855785

57865786
ERROR(attr_requires_decl_availability_for_platform,none,
57875787
"'%0' requires that %1 have explicit availability for %2",

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,9 @@ namespace swift {
193193
/// Enable 'availability' restrictions for App Extensions.
194194
bool EnableAppExtensionRestrictions = false;
195195

196-
/// Require public declarations to declare an introduction OS version.
197-
bool RequireExplicitAvailability = false;
196+
/// Diagnostic level to report when a public declarations doesn't declare
197+
/// an introduction OS version.
198+
Optional<DiagnosticBehavior> RequireExplicitAvailability = None;
198199

199200
/// Introduction platform and version to suggest as fix-it
200201
/// when using RequireExplicitAvailability.

include/swift/Option/Options.td

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,13 @@ def enable_library_evolution : Flag<["-"], "enable-library-evolution">,
411411

412412
def require_explicit_availability : Flag<["-"], "require-explicit-availability">,
413413
Flags<[FrontendOption, NoInteractiveOption]>,
414-
HelpText<"Require explicit availability on public declarations">;
414+
HelpText<"Warn on public declarations without an availability attribute">;
415+
416+
def require_explicit_availability_EQ : Joined<["-"], "require-explicit-availability=">,
417+
MetaVarName<"<error,warn,ignore>">,
418+
Flags<[FrontendOption, NoInteractiveOption]>,
419+
HelpText<"Set diagnostic level to report public declarations without an availability attribute">;
420+
415421
def require_explicit_availability_target : Separate<["-"], "require-explicit-availability-target">,
416422
Flags<[FrontendOption, NoInteractiveOption]>,
417423
HelpText<"Suggest fix-its adding @available(<target>, *) to public declarations without availability">,

lib/Driver/ToolChains.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
241241
inputArgs.AddLastArg(arguments, options::OPT_enable_library_evolution);
242242
inputArgs.AddLastArg(arguments, options::OPT_require_explicit_availability);
243243
inputArgs.AddLastArg(arguments, options::OPT_require_explicit_availability_target);
244+
inputArgs.AddLastArg(arguments, options::OPT_require_explicit_availability_EQ);
244245
inputArgs.AddLastArg(arguments, options::OPT_require_explicit_sendable);
245246
inputArgs.AddLastArg(arguments, options::OPT_check_api_availability_only);
246247
inputArgs.AddLastArg(arguments, options::OPT_enable_testing);

lib/Frontend/CompilerInvocation.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -588,13 +588,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
588588
if (Args.getLastArg(OPT_debug_cycles))
589589
Opts.DebugDumpCycles = true;
590590

591-
if (Args.getLastArg(OPT_require_explicit_availability, OPT_require_explicit_availability_target)) {
592-
Opts.RequireExplicitAvailability = true;
593-
if (const Arg *A = Args.getLastArg(OPT_require_explicit_availability_target)) {
594-
Opts.RequireExplicitAvailabilityTarget = A->getValue();
595-
}
596-
}
597-
598591
Opts.RequireExplicitSendable |= Args.hasArg(OPT_require_explicit_sendable);
599592
for (const Arg *A : Args.filtered(OPT_define_availability)) {
600593
Opts.AvailabilityMacros.push_back(A->getValue());
@@ -722,6 +715,29 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
722715
}
723716
}
724717

718+
if (const Arg *A = Args.getLastArg(OPT_require_explicit_availability_EQ)) {
719+
StringRef diagLevel = A->getValue();
720+
if (diagLevel == "warn") {
721+
Opts.RequireExplicitAvailability = DiagnosticBehavior::Warning;
722+
} else if (diagLevel == "error") {
723+
Opts.RequireExplicitAvailability = DiagnosticBehavior::Error;
724+
} else if (diagLevel == "ignore") {
725+
Opts.RequireExplicitAvailability = None;
726+
} else {
727+
Diags.diagnose(SourceLoc(),
728+
diag::error_unknown_require_explicit_availability,
729+
diagLevel);
730+
}
731+
} else if (Args.getLastArg(OPT_require_explicit_availability,
732+
OPT_require_explicit_availability_target) ||
733+
Opts.LibraryLevel == LibraryLevel::API) {
734+
Opts.RequireExplicitAvailability = DiagnosticBehavior::Warning;
735+
}
736+
737+
if (const Arg *A = Args.getLastArg(OPT_require_explicit_availability_target)) {
738+
Opts.RequireExplicitAvailabilityTarget = A->getValue();
739+
}
740+
725741
Opts.EnableSPIOnlyImports = Args.hasArg(OPT_experimental_spi_only_imports);
726742

727743
if (Opts.EnableSwift3ObjCInference) {

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4276,7 +4276,8 @@ static bool declNeedsExplicitAvailability(const Decl *decl) {
42764276
void swift::checkExplicitAvailability(Decl *decl) {
42774277
// Skip if the command line option was not set and
42784278
// accessors as we check the pattern binding decl instead.
4279-
if (!decl->getASTContext().LangOpts.RequireExplicitAvailability ||
4279+
auto DiagLevel = decl->getASTContext().LangOpts.RequireExplicitAvailability;
4280+
if (!DiagLevel ||
42804281
isa<AccessorDecl>(decl))
42814282
return;
42824283

@@ -4320,6 +4321,7 @@ void swift::checkExplicitAvailability(Decl *decl) {
43204321

43214322
if (declNeedsExplicitAvailability(decl)) {
43224323
auto diag = decl->diagnose(diag::public_decl_needs_availability);
4324+
diag.limitBehavior(*DiagLevel);
43234325

43244326
auto suggestPlatform =
43254327
decl->getASTContext().LangOpts.RequireExplicitAvailabilityTarget;

stdlib/cmake/modules/SwiftSource.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,8 @@ function(_compile_swift_files
483483
# The standard library and overlays are built resiliently when SWIFT_STDLIB_STABLE_ABI=On.
484484
if(SWIFTFILE_IS_STDLIB AND SWIFT_STDLIB_STABLE_ABI)
485485
list(APPEND swift_flags "-enable-library-evolution")
486-
list(APPEND swift_flags "-Xfrontend" "-library-level" "-Xfrontend" "api")
486+
list(APPEND swift_flags "-library-level" "api")
487+
list(APPEND swift_flags "-Xfrontend" "-require-explicit-availability=ignore")
487488
endif()
488489

489490
if("${SWIFT_SDK_${SWIFTFILE_SDK}_THREADING_PACKAGE}" STREQUAL "none")

test/ClangImporter/availability_spi_as_unavailable.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public let c: SPIInterface1 // expected-error{{cannot use class 'SPIInterface1'
1313
public let d: SPIInterface2 // expected-error{{cannot use class 'SPIInterface2' here; it is an SPI imported from 'SPIContainer'}}
1414

1515
@inlinable
16-
public func inlinableUsingSPI() {
16+
public func inlinableUsingSPI() { // expected-warning{{public declarations should have an availability attribute with an introduction version}}
1717
SharedInterface.foo() // expected-error{{class method 'foo()' cannot be used in an '@inlinable' function because it is an SPI imported from 'SPIContainer'}}
1818
}
1919

test/ClangImporter/availability_spi_as_unavailable_bridging_header.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ public let c: SPIInterface1 // expected-error{{cannot use class 'SPIInterface1'
99
public let d: SPIInterface2 // expected-error{{cannot use class 'SPIInterface2' here; it is an SPI imported from '__ObjC'}}
1010

1111
@inlinable
12-
public func inlinableUsingSPI() {
12+
public func inlinableUsingSPI() { // expected-warning{{public declarations should have an availability attribute with an introduction version}}
1313
SharedInterface.foo() // expected-error{{class method 'foo()' cannot be used in an '@inlinable' function because it is an SPI imported from '__ObjC'}}
1414
}

test/SPI/spi-only-and-library-level.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public struct LibStruct {}
2525
@_spiOnly import Lib
2626

2727
public func publicClient() -> LibStruct { fatalError() } // expected-error {{cannot use struct 'LibStruct' here; 'Lib' was imported for SPI only}}
28+
// expected-warning @-1 {{public declarations should have an availability attribute with an introduction version}}
2829
@_spi(X) public func spiClient() -> LibStruct { fatalError() }
2930

3031
//--- SPILib.swift

test/Sema/spi-available-inline.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public class MacOSSPIClass { public init() {} }
1010
@available(macOS 10.4, *)
1111
public class iOSSPIClass { public init() {} }
1212

13-
@inlinable public func foo() {
13+
@inlinable public func foo() { // expected-warning{{public declarations should have an availability attribute with an introduction version}}
1414
_ = MacOSSPIClass() // expected-error {{class 'MacOSSPIClass' cannot be used in an '@inlinable' function because it is SPI}}
1515
_ = iOSSPIClass()
1616
}

test/attr/attr_inlinable_available.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515

1616
// Check that `-library-level api` implies `-target-min-inlining-version min`
17-
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-library-evolution -module-name Test -target %target-next-stable-abi-triple -library-level api
17+
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-library-evolution -module-name Test -target %target-next-stable-abi-triple -library-level api -require-explicit-availability=ignore
1818

1919

2020
// Check that these rules are only applied when requested and that at least some
@@ -24,7 +24,7 @@
2424

2525
// Check that -target-min-inlining-version overrides -library-level, allowing
2626
// library owners to disable this behavior for API libraries if needed.
27-
// RUN: not %target-typecheck-verify-swift -swift-version 5 -enable-library-evolution -module-name Test -target %target-next-stable-abi-triple -target-min-inlining-version target -library-level api 2>&1 | %FileCheck --check-prefix NON_MIN %s
27+
// RUN: not %target-typecheck-verify-swift -swift-version 5 -enable-library-evolution -module-name Test -target %target-next-stable-abi-triple -target-min-inlining-version target -library-level api -require-explicit-availability=ignore 2>&1 | %FileCheck --check-prefix NON_MIN %s
2828

2929

3030
// Check that we respect -target-min-inlining-version by cranking it up high

0 commit comments

Comments
 (0)