mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Look to enclosing declarations for @available attributes on @_nonSendable types
`@_nonSendable` types get a synthesized, unavailable extension that declares the Sendable conformance. This extension also needs to have appropriate platform availability for the type that is being marked non-Sendable, so the platform-specific attributes are copied from the nominal type declaration. However, for nested types, we might need to copy those attributes from an enclosing declarations. Do so when appropriate. Fixes rdar://90330588.
This commit is contained in:
@@ -4341,23 +4341,37 @@ static void addUnavailableAttrs(ExtensionDecl *ext, NominalTypeDecl *nominal) {
|
||||
ASTContext &ctx = nominal->getASTContext();
|
||||
llvm::VersionTuple noVersion;
|
||||
|
||||
// Add platform-version-specific @available attributes.
|
||||
for (auto available : nominal->getAttrs().getAttributes<AvailableAttr>()) {
|
||||
if (available->Platform == PlatformKind::none)
|
||||
continue;
|
||||
// Add platform-version-specific @available attributes. Search from nominal
|
||||
// type declaration through its enclosing declarations to find the first one
|
||||
// with platform-specific attributes.
|
||||
for (Decl *enclosing = nominal;
|
||||
enclosing;
|
||||
enclosing = enclosing->getDeclContext()
|
||||
? enclosing->getDeclContext()->getAsDecl()
|
||||
: nullptr) {
|
||||
bool anyPlatformSpecificAttrs = false;
|
||||
for (auto available: enclosing->getAttrs().getAttributes<AvailableAttr>()) {
|
||||
if (available->Platform == PlatformKind::none)
|
||||
continue;
|
||||
|
||||
auto attr = new (ctx) AvailableAttr(
|
||||
SourceLoc(), SourceRange(),
|
||||
available->Platform,
|
||||
available->Message,
|
||||
"", nullptr,
|
||||
available->Introduced.getValueOr(noVersion), SourceRange(),
|
||||
available->Deprecated.getValueOr(noVersion), SourceRange(),
|
||||
available->Obsoleted.getValueOr(noVersion), SourceRange(),
|
||||
PlatformAgnosticAvailabilityKind::Unavailable,
|
||||
/*implicit=*/true,
|
||||
available->IsSPI);
|
||||
ext->getAttrs().add(attr);
|
||||
auto attr = new (ctx) AvailableAttr(
|
||||
SourceLoc(), SourceRange(),
|
||||
available->Platform,
|
||||
available->Message,
|
||||
"", nullptr,
|
||||
available->Introduced.getValueOr(noVersion), SourceRange(),
|
||||
available->Deprecated.getValueOr(noVersion), SourceRange(),
|
||||
available->Obsoleted.getValueOr(noVersion), SourceRange(),
|
||||
PlatformAgnosticAvailabilityKind::Unavailable,
|
||||
/*implicit=*/true,
|
||||
available->IsSPI);
|
||||
ext->getAttrs().add(attr);
|
||||
anyPlatformSpecificAttrs = true;
|
||||
}
|
||||
|
||||
// If we found any platform-specific availability attributes, we're done.
|
||||
if (anyPlatformSpecificAttrs)
|
||||
break;
|
||||
}
|
||||
|
||||
// Add the blanket "unavailable".
|
||||
|
||||
@@ -12,6 +12,16 @@ public struct X { }
|
||||
@_nonSendable
|
||||
public struct Y { }
|
||||
|
||||
@available(macOS 11.0, *)
|
||||
extension X {
|
||||
@available(macOS 12.0, *)
|
||||
@_nonSendable
|
||||
public struct A { }
|
||||
|
||||
@_nonSendable
|
||||
public struct B { }
|
||||
}
|
||||
|
||||
// RUN: %FileCheck %s <%t/Library.swiftinterface
|
||||
// CHECK: @available(macOS 11.0, *)
|
||||
// CHECK-NEXT: public struct X
|
||||
@@ -23,6 +33,14 @@ public struct Y { }
|
||||
// CHECK: @available(*, unavailable)
|
||||
// CHECK-NEXT: extension Library.Y{{( )?}}: @unchecked Swift.Sendable {
|
||||
|
||||
// CHECK: @available(macOS, unavailable, introduced: 12.0)
|
||||
// CHECK-NEXT: @available(*, unavailable)
|
||||
// CHECK-NEXT: extension Library.X.A{{( )?}}: @unchecked Swift.Sendable {
|
||||
|
||||
// CHECK: @available(macOS, unavailable, introduced: 11.0)
|
||||
// CHECK-NEXT: @available(*, unavailable)
|
||||
// CHECK-NEXT: extension Library.X.B{{( )?}}: @unchecked Swift.Sendable {
|
||||
|
||||
// RUN: %target-swift-emit-module-interface(%t/Library.swiftinterface) %s -target %target-cpu-apple-macosx12.0 -DLIBRARY -module-name Library -module-interface-preserve-types-as-written
|
||||
// RUN: %target-swift-typecheck-module-from-interface(%t/Library.swiftinterface) -module-name Library
|
||||
// RUN: %FileCheck %s <%t/Library.swiftinterface
|
||||
|
||||
Reference in New Issue
Block a user