Skip to content

Commit d6baec9

Browse files
committed
Add availability gating for async function and actor type definitions.
Implements rdar://80098709.
1 parent 22dd46f commit d6baec9

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
@@ -5254,6 +5254,10 @@ ERROR(availability_opaque_types_only_version_newer, none,
52545254
"'some' return types are only available in %0 %1 or newer",
52555255
(StringRef, llvm::VersionTuple))
52565256

5257+
ERROR(availability_concurrency_only_version_newer, none,
5258+
"concurrency is only available in %0 %1 or newer",
5259+
(StringRef, llvm::VersionTuple))
5260+
52575261
NOTE(availability_guard_with_version_check, none,
52585262
"add 'if #available' version check", ())
52595263

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,6 +1616,48 @@ void TypeChecker::diagnosePotentialOpaqueTypeUnavailability(
16161616
fixAvailability(ReferenceRange, ReferenceDC, RequiredRange, Context);
16171617
}
16181618

1619+
static void diagnosePotentialConcurrencyUnavailability(
1620+
SourceRange ReferenceRange, const DeclContext *ReferenceDC,
1621+
const UnavailabilityReason &Reason) {
1622+
ASTContext &Context = ReferenceDC->getASTContext();
1623+
1624+
auto RequiredRange = Reason.getRequiredOSVersionRange();
1625+
{
1626+
auto Err =
1627+
Context.Diags.diagnose(
1628+
ReferenceRange.Start,
1629+
diag::availability_concurrency_only_version_newer,
1630+
prettyPlatformString(targetPlatform(Context.LangOpts)),
1631+
Reason.getRequiredOSVersionRange().getLowerEndpoint());
1632+
1633+
// Direct a fixit to the error if an existing guard is nearly-correct
1634+
if (fixAvailabilityByNarrowingNearbyVersionCheck(ReferenceRange,
1635+
ReferenceDC,
1636+
RequiredRange, Context, Err))
1637+
return;
1638+
}
1639+
fixAvailability(ReferenceRange, ReferenceDC, RequiredRange, Context);
1640+
}
1641+
1642+
1643+
void TypeChecker::checkConcurrencyAvailability(SourceRange ReferenceRange,
1644+
const DeclContext *ReferenceDC) {
1645+
// Check the availability of concurrency runtime support.
1646+
ASTContext &ctx = ReferenceDC->getASTContext();
1647+
if (ctx.LangOpts.DisableAvailabilityChecking)
1648+
return;
1649+
1650+
auto runningOS =
1651+
TypeChecker::overApproximateAvailabilityAtLocation(
1652+
ReferenceRange.Start, ReferenceDC);
1653+
auto availability = ctx.getConcurrencyAvailability();
1654+
if (!runningOS.isContainedIn(availability)) {
1655+
diagnosePotentialConcurrencyUnavailability(
1656+
ReferenceRange, ReferenceDC,
1657+
UnavailabilityReason::requiresVersionRange(availability.getOSVersion()));
1658+
}
1659+
}
1660+
16191661
void TypeChecker::diagnosePotentialUnavailability(
16201662
const ValueDecl *D, SourceRange ReferenceRange,
16211663
const DeclContext *ReferenceDC,

lib/Sema/TypeCheckDeclPrimary.cpp

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

23162316
TypeChecker::checkDeclAttributes(CD);
23172317

2318+
if (CD->isActor())
2319+
TypeChecker::checkConcurrencyAvailability(CD->getLoc(), CD);
2320+
23182321
for (Decl *Member : CD->getABIMembers())
23192322
visit(Member);
23202323

@@ -2609,6 +2612,9 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
26092612

26102613
checkImplementationOnlyOverride(FD);
26112614

2615+
if (FD->getAsyncLoc().isValid())
2616+
TypeChecker::checkConcurrencyAvailability(FD->getAsyncLoc(), FD);
2617+
26122618
if (requiresDefinition(FD) && !FD->hasBody()) {
26132619
// Complain if we should have a body.
26142620
FD->diagnose(diag::func_decl_without_brace);
@@ -2859,6 +2865,9 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
28592865
TypeChecker::checkDeclAttributes(CD);
28602866
TypeChecker::checkParameterList(CD->getParameters(), CD);
28612867

2868+
if (CD->getAsyncLoc().isValid())
2869+
TypeChecker::checkConcurrencyAvailability(CD->getAsyncLoc(), CD);
2870+
28622871
// Check whether this initializer overrides an initializer in its
28632872
// superclass.
28642873
if (!checkOverrides(CD)) {

lib/Sema/TypeChecker.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,9 @@ diagnosePotentialOpaqueTypeUnavailability(SourceRange ReferenceRange,
10171017
const DeclContext *ReferenceDC,
10181018
const UnavailabilityReason &Reason);
10191019

1020+
void checkConcurrencyAvailability(SourceRange ReferenceRange,
1021+
const DeclContext *ReferenceDC);
1022+
10201023
/// Emits a diagnostic for a reference to a storage accessor that is
10211024
/// potentially unavailable.
10221025
void diagnosePotentialAccessorUnavailability(

stdlib/private/StdlibUnittest/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ add_swift_target_library(swiftStdlibUnittest ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES}
4949
SWIFT_MODULE_DEPENDS_HAIKU Glibc _Concurrency
5050
SWIFT_MODULE_DEPENDS_WINDOWS CRT WinSDK _Concurrency
5151
SWIFT_COMPILE_FLAGS ${swift_stdlib_unittest_compile_flags} ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS}
52+
-Xfrontend -define-availability
53+
-Xfrontend \"SwiftStdlib 5.5:macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0\"
5254
INSTALL_IN_COMPONENT stdlib-experimental
5355
DARWIN_INSTALL_NAME_DIR "${SWIFT_DARWIN_STDLIB_PRIVATE_INSTALL_NAME_DIR}"
5456
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)