Skip to content

Commit 5e50ee8

Browse files
committed
Add @available attributes on the implicit "extension" for @_nonSendable types
`@_nonSendable` on a type effectively desugars to an unavailable extension that provides (`@unchecked`) conformance to the `Sendable` protocol. Make sure we copy over platform availability so that the extension does not promise greater availability than the type it extends. Fixes rdar://90330588.
1 parent 583efb2 commit 5e50ee8

File tree

2 files changed

+64
-11
lines changed

2 files changed

+64
-11
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4413,6 +4413,43 @@ bool swift::checkSendableConformance(
44134413
return checkSendableInstanceStorage(nominal, conformanceDC, check);
44144414
}
44154415

4416+
/// Add "unavailable" attributes to the given extension.
4417+
static void addUnavailableAttrs(ExtensionDecl *ext, NominalTypeDecl *nominal) {
4418+
ASTContext &ctx = nominal->getASTContext();
4419+
llvm::VersionTuple noVersion;
4420+
4421+
// Add platform-version-specific @available attributes.
4422+
for (auto available : nominal->getAttrs().getAttributes<AvailableAttr>()) {
4423+
if (available->Platform == PlatformKind::none)
4424+
continue;
4425+
4426+
auto attr = new (ctx) AvailableAttr(
4427+
SourceLoc(), SourceRange(),
4428+
available->Platform,
4429+
available->Message,
4430+
"", nullptr,
4431+
available->Introduced.getValueOr(noVersion), SourceRange(),
4432+
available->Deprecated.getValueOr(noVersion), SourceRange(),
4433+
available->Obsoleted.getValueOr(noVersion), SourceRange(),
4434+
PlatformAgnosticAvailabilityKind::Unavailable,
4435+
/*implicit=*/true,
4436+
available->IsSPI);
4437+
ext->getAttrs().add(attr);
4438+
}
4439+
4440+
// Add the blanket "unavailable".
4441+
4442+
auto attr = new (ctx) AvailableAttr(SourceLoc(), SourceRange(),
4443+
PlatformKind::none, "", "", nullptr,
4444+
noVersion, SourceRange(),
4445+
noVersion, SourceRange(),
4446+
noVersion, SourceRange(),
4447+
PlatformAgnosticAvailabilityKind::Unavailable,
4448+
false,
4449+
false);
4450+
ext->getAttrs().add(attr);
4451+
}
4452+
44164453
ProtocolConformance *GetImplicitSendableRequest::evaluate(
44174454
Evaluator &evaluator, NominalTypeDecl *nominal) const {
44184455
// Protocols never get implicit Sendable conformances.
@@ -4468,16 +4505,6 @@ ProtocolConformance *GetImplicitSendableRequest::evaluate(
44684505
-> NormalProtocolConformance * {
44694506
DeclContext *conformanceDC = nominal;
44704507
if (attrMakingUnavailable) {
4471-
llvm::VersionTuple NoVersion;
4472-
auto attr = new (ctx) AvailableAttr(SourceLoc(), SourceRange(),
4473-
PlatformKind::none, "", "", nullptr,
4474-
NoVersion, SourceRange(),
4475-
NoVersion, SourceRange(),
4476-
NoVersion, SourceRange(),
4477-
PlatformAgnosticAvailabilityKind::Unavailable,
4478-
false,
4479-
false);
4480-
44814508
// Conformance availability is currently tied to the declaring extension.
44824509
// FIXME: This is a hack--we should give conformances real availability.
44834510
auto inherits = ctx.AllocateCopy(makeArrayRef(
@@ -4490,7 +4517,7 @@ ProtocolConformance *GetImplicitSendableRequest::evaluate(
44904517
nominal->getModuleScopeContext(),
44914518
nullptr);
44924519
extension->setImplicit();
4493-
extension->getAttrs().add(attr);
4520+
addUnavailableAttrs(extension, nominal);
44944521

44954522
ctx.evaluator.cacheOutput(ExtendedTypeRequest{extension},
44964523
nominal->getDeclaredType());
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -typecheck -enable-library-evolution -target %target-cpu-apple-macosx12.0 -emit-module-interface-path %t/Library.swiftinterface -module-name Library %s
3+
4+
// REQUIRES: concurrency
5+
// REQUIRES: OS=macosx
6+
7+
@available(macOS 11.0, *)
8+
@_nonSendable
9+
public struct X { }
10+
11+
@_nonSendable
12+
public struct Y { }
13+
14+
// RUN: %FileCheck %s <%t/Library.swiftinterface
15+
// CHECK: @available(macOS 11.0, *)
16+
// CHECK-NEXT: public struct X
17+
18+
// CHECK: @available(macOS, unavailable, introduced: 11.0)
19+
// CHECK-NEXT: @available(*, unavailable)
20+
// CHECK-NEXT: extension Library.X{{( )?}}: @unchecked Swift.Sendable {
21+
22+
// CHECK: @available(*, unavailable)
23+
// CHECK-NEXT: extension Library.Y{{( )?}}: @unchecked Swift.Sendable {
24+
25+
// RUN: %target-swift-frontend -typecheck -enable-library-evolution -target %target-cpu-apple-macosx12.0 -emit-module-interface-path %t/Library.swiftinterface -DLIBRARY -module-name Library %s -module-interface-preserve-types-as-written
26+
// RUN: %FileCheck %s <%t/Library.swiftinterface

0 commit comments

Comments
 (0)