Skip to content

Commit e2d97af

Browse files
committed
Add availability gating for async function and actor type definitions.
Implements rdar://80098709.
1 parent 63668b0 commit e2d97af

File tree

8 files changed

+75
-0
lines changed

8 files changed

+75
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5325,6 +5325,10 @@ ERROR(availability_opaque_types_only_version_newer, none,
53255325
"'some' return types are only available in %0 %1 or newer",
53265326
(StringRef, llvm::VersionTuple))
53275327

5328+
ERROR(availability_concurrency_only_version_newer, none,
5329+
"concurrency is only available in %0 %1 or newer",
5330+
(StringRef, llvm::VersionTuple))
5331+
53285332
NOTE(availability_guard_with_version_check, none,
53295333
"add 'if #available' version check", ())
53305334

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,6 +1658,48 @@ void TypeChecker::diagnosePotentialOpaqueTypeUnavailability(
16581658
fixAvailability(ReferenceRange, ReferenceDC, RequiredRange, Context);
16591659
}
16601660

1661+
static void diagnosePotentialConcurrencyUnavailability(
1662+
SourceRange ReferenceRange, const DeclContext *ReferenceDC,
1663+
const UnavailabilityReason &Reason) {
1664+
ASTContext &Context = ReferenceDC->getASTContext();
1665+
1666+
auto RequiredRange = Reason.getRequiredOSVersionRange();
1667+
{
1668+
auto Err =
1669+
Context.Diags.diagnose(
1670+
ReferenceRange.Start,
1671+
diag::availability_concurrency_only_version_newer,
1672+
prettyPlatformString(targetPlatform(Context.LangOpts)),
1673+
Reason.getRequiredOSVersionRange().getLowerEndpoint());
1674+
1675+
// Direct a fixit to the error if an existing guard is nearly-correct
1676+
if (fixAvailabilityByNarrowingNearbyVersionCheck(ReferenceRange,
1677+
ReferenceDC,
1678+
RequiredRange, Context, Err))
1679+
return;
1680+
}
1681+
fixAvailability(ReferenceRange, ReferenceDC, RequiredRange, Context);
1682+
}
1683+
1684+
1685+
void TypeChecker::checkConcurrencyAvailability(SourceRange ReferenceRange,
1686+
const DeclContext *ReferenceDC) {
1687+
// Check the availability of concurrency runtime support.
1688+
ASTContext &ctx = ReferenceDC->getASTContext();
1689+
if (ctx.LangOpts.DisableAvailabilityChecking)
1690+
return;
1691+
1692+
auto runningOS =
1693+
TypeChecker::overApproximateAvailabilityAtLocation(
1694+
ReferenceRange.Start, ReferenceDC);
1695+
auto availability = ctx.getConcurrencyAvailability();
1696+
if (!runningOS.isContainedIn(availability)) {
1697+
diagnosePotentialConcurrencyUnavailability(
1698+
ReferenceRange, ReferenceDC,
1699+
UnavailabilityReason::requiresVersionRange(availability.getOSVersion()));
1700+
}
1701+
}
1702+
16611703
void TypeChecker::diagnosePotentialUnavailability(
16621704
const ValueDecl *D, SourceRange ReferenceRange,
16631705
const DeclContext *ReferenceDC,

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2423,6 +2423,9 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
24232423

24242424
TypeChecker::checkDeclAttributes(CD);
24252425

2426+
if (CD->isActor())
2427+
TypeChecker::checkConcurrencyAvailability(CD->getLoc(), CD);
2428+
24262429
for (Decl *Member : CD->getABIMembers())
24272430
visit(Member);
24282431

@@ -2718,6 +2721,9 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
27182721

27192722
checkImplementationOnlyOverride(FD);
27202723

2724+
if (FD->getAsyncLoc().isValid())
2725+
TypeChecker::checkConcurrencyAvailability(FD->getAsyncLoc(), FD);
2726+
27212727
if (requiresDefinition(FD) && !FD->hasBody()) {
27222728
// Complain if we should have a body.
27232729
FD->diagnose(diag::func_decl_without_brace);
@@ -2970,6 +2976,9 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
29702976
TypeChecker::checkDeclAttributes(CD);
29712977
TypeChecker::checkParameterList(CD->getParameters(), CD);
29722978

2979+
if (CD->getAsyncLoc().isValid())
2980+
TypeChecker::checkConcurrencyAvailability(CD->getAsyncLoc(), CD);
2981+
29732982
// Check whether this initializer overrides an initializer in its
29742983
// superclass.
29752984
if (!checkOverrides(CD)) {

lib/Sema/TypeChecker.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,9 @@ diagnosePotentialOpaqueTypeUnavailability(SourceRange ReferenceRange,
10211021
const DeclContext *ReferenceDC,
10221022
const UnavailabilityReason &Reason);
10231023

1024+
void checkConcurrencyAvailability(SourceRange ReferenceRange,
1025+
const DeclContext *ReferenceDC);
1026+
10241027
/// Emits a diagnostic for a reference to a storage accessor that is
10251028
/// potentially unavailable.
10261029
void diagnosePotentialAccessorUnavailability(

stdlib/private/StdlibUnittest/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ add_swift_target_library(swiftStdlibUnittest ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES}
5454
SWIFT_MODULE_DEPENDS_HAIKU Glibc
5555
SWIFT_MODULE_DEPENDS_WINDOWS CRT WinSDK
5656
SWIFT_COMPILE_FLAGS ${swift_stdlib_unittest_compile_flags} ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS}
57+
-Xfrontend -define-availability
58+
-Xfrontend \"SwiftStdlib 5.5:macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0\"
5759
INSTALL_IN_COMPONENT stdlib-experimental
5860
DARWIN_INSTALL_NAME_DIR "${SWIFT_DARWIN_STDLIB_PRIVATE_INSTALL_NAME_DIR}"
5961
LINK_LIBRARIES ${swift_stdlib_unittest_link_libraries})

stdlib/private/StdlibUnittest/StdlibUnittest.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,7 @@ func _childProcess() {
876876
}
877877

878878
#if SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY
879+
@available(SwiftStdlib 5.5, *)
879880
@inline(never)
880881
func _childProcessAsync() async {
881882
_installTrapInterceptor()
@@ -1370,6 +1371,7 @@ class _ParentProcess {
13701371
}
13711372

13721373
#if SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY
1374+
@available(SwiftStdlib 5.5, *)
13731375
internal func runOneTestAsync(
13741376
fullTestName: String,
13751377
testSuite: TestSuite,
@@ -1536,6 +1538,7 @@ class _ParentProcess {
15361538
}
15371539

15381540
#if SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY
1541+
@available(SwiftStdlib 5.5, *)
15391542
func runAsync() async {
15401543
if let filter = _filter {
15411544
print("StdlibUnittest: using filter: \(filter)")
@@ -1720,6 +1723,7 @@ public func runAllTests() {
17201723
}
17211724

17221725
#if SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY
1726+
@available(SwiftStdlib 5.5, *)
17231727
public func runAllTestsAsync() async {
17241728
if PersistentState.runNoTestsWasCalled {
17251729
print("runAllTests() called after runNoTests(). Aborting.")
@@ -1907,6 +1911,7 @@ public final class TestSuite {
19071911
}
19081912

19091913
#if SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY
1914+
@available(SwiftStdlib 5.5, *)
19101915
func _runTestAsync(name testName: String, parameter: Int?) async {
19111916
PersistentState.ranSomething = true
19121917
for r in _allResettables {

stdlib/public/Concurrency/Errors.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import Swift
1414
@_implementationOnly import _SwiftConcurrencyShims
1515

16+
@available(SwiftStdlib 5.5, *)
1617
@_silgen_name("swift_deletedAsyncMethodError")
1718
public func swift_deletedAsyncMethodError() async {
1819
fatalError("Fatal error: Call of deleted method")
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-swift-frontend -parse-stdlib -target x86_64-apple-macosx10.15 -typecheck -verify %s
2+
// RUN: %target-swift-frontend -parse-stdlib -target x86_64-apple-macosx12 -typecheck %s
3+
// REQUIRES: OS=macosx
4+
5+
func f() async { } // expected-error{{concurrency is only available in}}
6+
// expected-note@-1{{add @available}}
7+
8+
actor A { } // expected-error{{concurrency is only available in}}
9+
// expected-note@-1{{add @available}}

0 commit comments

Comments
 (0)