Skip to content

[6.1] Add version checks & fix pointer auth for nonisolated deinit #78107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/swift/ABI/MetadataValues.h
Original file line number Diff line number Diff line change
Expand Up @@ -1704,6 +1704,9 @@ namespace SpecialPointerAuthDiscriminators {
const uint16_t RelativeProtocolWitnessTable = 0xb830; // = 47152

const uint16_t TypeLayoutString = 0x8b65; // = 35685

/// Isolated deinit body function pointer
const uint16_t DeinitWorkFunction = 0x8438; // = 33848
}

/// The number of arguments that will be passed directly to a generic
Expand Down
5 changes: 5 additions & 0 deletions include/swift/AST/DiagnosticsSIL.def
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,11 @@ NOTE(box_to_stack_cannot_promote_box_to_stack_due_to_escape_location, none,

WARNING(semantic_function_improper_nesting, none, "'@_semantics' function calls non-'@_semantics' function with nested '@_semantics' calls", ())

// SDK mismatch diagnostics
ERROR(missing_deinit_on_executor_function, none,
"Missing 'swift_task_deinitOnExecutor' function! "
"This is likely due to an outdated/incompatible SDK.", ())

// Capture promotion diagnostics
WARNING(capturepromotion_concurrentcapture_mutation, none,
"'%0' mutated after capture by sendable closure", (StringRef))
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -5963,6 +5963,9 @@ ERROR(isolated_deinit_no_isolation,none,
ERROR(isolated_deinit_on_value_type,none,
"only classes and actors can have isolated deinit",
())
ERROR(isolated_deinit_unavailable,none,
"isolated deinit is only available in %0 %1 or newer",
(StringRef, llvm::VersionTuple))
ERROR(isolated_deinit_experimental,none,
"'isolated' deinit requires frontend flag -enable-experimental-feature IsolatedDeinit "
"to enable the usage of this language feature", ())
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/FeatureAvailability.def
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ FEATURE(InitRawStructMetadata, (6, 0))

FEATURE(LayoutStringValueWitnesses, (6, 1))
FEATURE(CreateTaskWithConsumedFunction, (6, 1))
FEATURE(IsolatedDeinit, (6, 1))

FEATURE(TaskExecutor, FUTURE)
FEATURE(Differentiation, FUTURE)
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ EXPERIMENTAL_FEATURE(SafeInterop, true)
EXPERIMENTAL_FEATURE(AssumeResilientCxxTypes, true)

// Isolated deinit
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(IsolatedDeinit, true)
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(IsolatedDeinit, false)

// Enable values in generic signatures, e.g. <let N: Int>
EXPERIMENTAL_FEATURE(ValueGenerics, true)
Expand Down
15 changes: 15 additions & 0 deletions include/swift/Runtime/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,9 @@ extern uintptr_t __COMPATIBILITY_LIBRARIES_CANNOT_CHECK_THE_IS_SWIFT_BIT_DIRECTL
#define __ptrauth_swift_type_layout_string \
__ptrauth(ptrauth_key_process_independent_data, 1, \
SpecialPointerAuthDiscriminators::TypeLayoutString)
#define __ptrauth_swift_deinit_work_function \
__ptrauth(ptrauth_key_function_pointer, 1, \
SpecialPointerAuthDiscriminators::DeinitWorkFunction)

#if __has_attribute(ptrauth_struct)
#define swift_ptrauth_struct(key, discriminator) \
Expand Down Expand Up @@ -364,6 +367,7 @@ extern uintptr_t __COMPATIBILITY_LIBRARIES_CANNOT_CHECK_THE_IS_SWIFT_BIT_DIRECTL
#define swift_ptrauth_sign_opaque_read_resume_function(__fn, __buffer) (__fn)
#define swift_ptrauth_sign_opaque_modify_resume_function(__fn, __buffer) (__fn)
#define __ptrauth_swift_type_layout_string
#define __ptrauth_swift_deinit_work_function
#define swift_ptrauth_struct(key, discriminator)
#define swift_ptrauth_struct_derived(from)
#endif
Expand Down Expand Up @@ -542,6 +546,17 @@ swift_auth_code(T value, unsigned extra) {
#endif
}

template <typename T>
SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE static inline T
swift_auth_code_function(T value, unsigned extra) {
#if SWIFT_PTRAUTH
return (T)ptrauth_auth_function((void *)value,
ptrauth_key_function_pointer, extra);
#else
return value;
#endif
}

/// Does this platform support backtrace-on-crash?
#ifdef __APPLE__
# include <TargetConditionals.h>
Expand Down
7 changes: 5 additions & 2 deletions lib/SILGen/SILGenDestructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "SwitchEnumBuilder.h"
#include "swift/AST/ConformanceLookup.h"
#include "swift/AST/Decl.h"
#include "swift/AST/DiagnosticsSIL.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/Basic/Assertions.h"
Expand Down Expand Up @@ -373,8 +374,10 @@ void SILGenFunction::emitIsolatingDestructor(DestructorDecl *dd) {

// Get deinitOnExecutor
FuncDecl *swiftDeinitOnExecutorDecl = SGM.getDeinitOnExecutor();
assert(swiftDeinitOnExecutorDecl &&
"Failed to find swift_task_deinitOnExecutor function decl");
if (!swiftDeinitOnExecutorDecl) {
dd->diagnose(diag::missing_deinit_on_executor_function);
return;
}
SILFunction *swiftDeinitOnExecutorSILFunc = SGM.getFunction(
SILDeclRef(swiftDeinitOnExecutorDecl, SILDeclRef::Kind::Func),
NotForDefinition);
Expand Down
8 changes: 8 additions & 0 deletions lib/Sema/TypeCheckAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
return;
}
}

TypeChecker::checkAvailability(
attr->getRange(), C.getIsolatedDeinitAvailability(),
D->getDeclContext(),
[&](StringRef platformName, llvm::VersionTuple version) {
return diagnoseAndRemoveAttr(
attr, diag::isolated_deinit_unavailable, platformName, version);
});
}
}

Expand Down
6 changes: 5 additions & 1 deletion stdlib/public/Concurrency/Actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "swift/Runtime/Concurrency.h"
#include <atomic>
#include <new>
#include <ptrauth.h>

#include "../CompatibilityOverride/CompatibilityOverride.h"
#include "swift/ABI/Actor.h"
Expand Down Expand Up @@ -2322,7 +2323,7 @@ namespace {
class IsolatedDeinitJob : public Job {
private:
void *Object;
DeinitWorkFunction *Work;
DeinitWorkFunction *__ptrauth_swift_deinit_work_function Work;

public:
IsolatedDeinitJob(JobPriority priority, void *object,
Expand Down Expand Up @@ -2351,6 +2352,9 @@ static void swift_task_deinitOnExecutorImpl(void *object,
DeinitWorkFunction *work,
SerialExecutorRef newExecutor,
size_t rawFlags) {
// Sign the function pointer
work = swift_auth_code_function(
work, SpecialPointerAuthDiscriminators::DeinitWorkFunction);
// If the current executor is compatible with running the new executor,
// we can just immediately continue running with the resume function
// we were passed in.
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/Concurrency/Executor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ internal final class DispatchQueueShim: @unchecked Sendable, SerialExecutor {
#endif // SWIFT_CONCURRENCY_USES_DISPATCH


@available(SwiftStdlib 5.6, *) // TODO: Clarify version
@available(SwiftStdlib 6.1, *)
@_silgen_name("swift_task_deinitOnExecutor")
@usableFromInline
internal func _deinitOnExecutor(_ object: __owned AnyObject,
Expand Down
4 changes: 2 additions & 2 deletions test/Concurrency/Runtime/actor_deinit_escaping_self.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// RUN: %target-run-simple-swift( -enable-experimental-feature IsolatedDeinit -target %target-swift-5.1-abi-triple %import-libdispatch -parse-as-library)
// RUN: %target-run-simple-swift( -enable-experimental-feature IsolatedDeinit -target %target-future-triple %import-libdispatch -parse-as-library)

// REQUIRES: executable_test
// REQUIRES: libdispatch
// REQUIRES: concurrency
// REQUIRES: concurrency_runtime
// REQUIRES: swift_feature_IsolatedDeinit
// UNSUPPORTED: back_deployment_runtime
// REQUIRES: swift_feature_IsolatedDeinit

import _Concurrency
import Dispatch
Expand Down
4 changes: 2 additions & 2 deletions test/Concurrency/Runtime/actor_recursive_deinit.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// RUN: %target-run-simple-swift(-enable-experimental-feature IsolatedDeinit -target %target-swift-5.1-abi-triple -parse-stdlib -parse-as-library) | %FileCheck %s
// RUN: %target-run-simple-swift(-enable-experimental-feature IsolatedDeinit -target %target-future-triple -parse-stdlib -parse-as-library) | %FileCheck %s

// REQUIRES: executable_test
// REQUIRES: concurrency

// REQUIRES: concurrency_runtime
// REQUIRES: swift_feature_IsolatedDeinit
// UNSUPPORTED: back_deployment_runtime
// REQUIRES: swift_feature_IsolatedDeinit

// Compiler crashes because builtin "ifdef_SWIFT_STDLIB_PRINT_DISABLED"() gets lowered as "i32 0",
// which triggers assertion in LLVM, which expects it to be i1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -enable-experimental-feature IsolatedDeinit -plugin-path %swift-plugin-dir -enable-experimental-feature IsolatedDeinit -target %target-swift-5.1-abi-triple -parse-stdlib %import-libdispatch %s -o %t/a.out
// RUN: %target-build-swift -enable-experimental-feature IsolatedDeinit -plugin-path %swift-plugin-dir -target %target-future-triple -parse-stdlib %import-libdispatch %s -o %t/a.out
// RUN: %target-codesign %t/a.out
// RUN: %env-SWIFT_IS_CURRENT_EXECUTOR_LEGACY_MODE_OVERRIDE=swift6 %target-run %t/a.out

Expand Down
2 changes: 1 addition & 1 deletion test/Concurrency/Runtime/isolated_deinit_main_sync.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-run-simple-swift(-enable-experimental-feature IsolatedDeinit -target %target-swift-5.1-abi-triple) | %FileCheck %s
// RUN: %target-run-simple-swift(-enable-experimental-feature IsolatedDeinit -target %target-future-triple) | %FileCheck %s

// REQUIRES: executable_test
// REQUIRES: concurrency
Expand Down
6 changes: 3 additions & 3 deletions test/Concurrency/deinit_isolation.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -target %target-swift-5.1-abi-triple -parse-as-library -enable-experimental-feature IsolatedDeinit -emit-silgen -verify %s
// RUN: %target-swift-frontend -target %target-swift-5.1-abi-triple -parse-as-library -enable-experimental-feature IsolatedDeinit -emit-silgen -DSILGEN %s | %FileCheck %s
// RUN: %target-swift-frontend -target %target-swift-5.1-abi-triple -parse-as-library -enable-experimental-feature IsolatedDeinit -emit-silgen -DSILGEN %s | %FileCheck -check-prefix=CHECK-SYMB %s
// RUN: %target-swift-frontend -target %target-future-triple -parse-as-library -enable-experimental-feature IsolatedDeinit -emit-silgen -verify %s
// RUN: %target-swift-frontend -target %target-future-triple -parse-as-library -enable-experimental-feature IsolatedDeinit -emit-silgen -DSILGEN %s | %FileCheck %s
// RUN: %target-swift-frontend -target %target-future-triple -parse-as-library -enable-experimental-feature IsolatedDeinit -emit-silgen -DSILGEN %s | %FileCheck -check-prefix=CHECK-SYMB %s

// REQUIRES: concurrency
// REQUIRES: swift_feature_IsolatedDeinit
Expand Down
2 changes: 1 addition & 1 deletion test/Concurrency/deinit_isolation_import/test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// RUN: cp -R $INPUT_DIR/Alpha.framework %t/Frameworks/
// RUN: %empty-directory(%t/Frameworks/Alpha.framework/Modules/Alpha.swiftmodule)
// RUN: %empty-directory(%t/Frameworks/Alpha.framework/Headers/)
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-feature IsolatedDeinit -disable-implicit-string-processing-module-import -parse-as-library -module-name Alpha \
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-feature IsolatedDeinit -disable-implicit-string-processing-module-import -parse-as-library -disable-availability-checking -module-name Alpha \
// RUN: -emit-module -o %t/Frameworks/Alpha.framework/Modules/Alpha.swiftmodule/%module-target-triple.swiftmodule \
// RUN: -enable-objc-interop -disable-objc-attr-requires-foundation-module \
// RUN: -emit-objc-header -emit-objc-header-path %t/Frameworks/Alpha.framework/Headers/Alpha-Swift.h $INPUT_DIR/Alpha.swift
Expand Down
2 changes: 1 addition & 1 deletion test/Concurrency/deinit_isolation_in_value_types.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -target %target-swift-5.1-abi-triple -enable-experimental-feature IsolatedDeinit -parse-as-library -emit-silgen -verify %s
// RUN: %target-swift-frontend -target %target-future-triple -enable-experimental-feature IsolatedDeinit -parse-as-library -emit-silgen -verify %s

// REQUIRES: swift_feature_IsolatedDeinit

Expand Down
6 changes: 3 additions & 3 deletions test/Concurrency/deinit_isolation_objc.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-feature IsolatedDeinit -disable-implicit-string-processing-module-import -target %target-swift-5.1-abi-triple -parse-as-library -emit-silgen -verify %s
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-feature IsolatedDeinit -disable-implicit-string-processing-module-import -target %target-swift-5.1-abi-triple -parse-as-library -emit-silgen -DSILGEN %s | %FileCheck %s
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-feature IsolatedDeinit -disable-implicit-string-processing-module-import -target %target-swift-5.1-abi-triple -parse-as-library -emit-silgen -DSILGEN %s | %FileCheck -check-prefix=CHECK-SYMB %s
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-feature IsolatedDeinit -disable-implicit-string-processing-module-import -target %target-future-triple -parse-as-library -emit-silgen -verify %s
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-feature IsolatedDeinit -disable-implicit-string-processing-module-import -target %target-future-triple -parse-as-library -emit-silgen -DSILGEN %s | %FileCheck %s
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-feature IsolatedDeinit -disable-implicit-string-processing-module-import -target %target-future-triple -parse-as-library -emit-silgen -DSILGEN %s | %FileCheck -check-prefix=CHECK-SYMB %s

// REQUIRES: concurrency
// REQUIRES: objc_interop
Expand Down
2 changes: 1 addition & 1 deletion test/Concurrency/deinit_isolation_tbd.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-feature IsolatedDeinit -emit-ir %s | %FileCheck %s
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-feature IsolatedDeinit -disable-availability-checking -emit-ir %s | %FileCheck %s

// REQUIRES: swift_feature_IsolatedDeinit

Expand Down
10 changes: 5 additions & 5 deletions test/Concurrency/flow_isolation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ actor Demons {
self.ns = x
}

nonisolated deinit {
deinit {
let _ = self.ns // expected-warning {{cannot access property 'ns' with a non-sendable type 'NonSendableType' from nonisolated deinit; this is an error in the Swift 6 language mode}}
}
}
Expand Down Expand Up @@ -159,7 +159,7 @@ actor ExampleFromProposal {
}


nonisolated deinit {
deinit {
_ = self.immutableSendable // ok
_ = self.mutableSendable // ok
_ = self.nonSendable // expected-warning {{cannot access property 'nonSendable' with a non-sendable type 'NonSendableType' from nonisolated deinit; this is an error in the Swift 6 language mode}}
Expand Down Expand Up @@ -199,7 +199,7 @@ class CheckGAIT1 {
silly += 2 // expected-warning {{cannot access property 'silly' here in nonisolated initializer; this is an error in the Swift 6 language mode}}
}

nonisolated deinit {
deinit {
_ = ns // expected-warning {{cannot access property 'ns' with a non-sendable type 'NonSendableType' from nonisolated deinit; this is an error in the Swift 6 language mode}}
f() // expected-note {{after calling instance method 'f()', only nonisolated properties of 'self' can be accessed from a deinit}}
_ = silly // expected-warning {{cannot access property 'silly' here in deinitializer; this is an error in the Swift 6 language mode}}
Expand Down Expand Up @@ -623,7 +623,7 @@ actor Ahmad {
prop += 1 // expected-warning {{cannot access property 'prop' here in nonisolated initializer; this is an error in the Swift 6 language mode}}
}

nonisolated deinit {
deinit {
// expected-warning@+2 {{actor-isolated property 'computedProp' can not be referenced from a nonisolated context; this is an error in the Swift 6 language mode}}
// expected-note@+1 {{after accessing property 'computedProp', only nonisolated properties of 'self' can be accessed from a deinit}}
let x = computedProp
Expand Down Expand Up @@ -679,7 +679,7 @@ actor NonIsolatedDeinitExceptionForSwift5 {
}
}

@available(SwiftStdlib 5.5, *)
@available(SwiftStdlib 6.1, *)
actor IsolatedDeinitExceptionForSwift5 {
var x: Int = 0

Expand Down
77 changes: 41 additions & 36 deletions test/Concurrency/voucher_propagation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ actor Counter {
func get() -> Int { n }
}

@available(SwiftStdlib 6.1, *)
actor ActorWithSelfIsolatedDeinit {
let expectedVoucher: voucher_t?
let group: DispatchGroup
Expand All @@ -102,6 +103,7 @@ actor ActorWithSelfIsolatedDeinit {
}
}

@available(SwiftStdlib 6.1, *)
actor ActorWithDeinitIsolatedOnAnother {
let expectedVoucher: voucher_t?
let group: DispatchGroup
Expand All @@ -121,6 +123,7 @@ actor ActorWithDeinitIsolatedOnAnother {
}
}

@available(SwiftStdlib 6.1, *)
class ClassWithIsolatedDeinit {
let expectedVoucher: voucher_t?
let group: DispatchGroup
Expand Down Expand Up @@ -427,47 +430,49 @@ if #available(SwiftStdlib 5.1, *) {
group.wait()
}
}

tests.test("voucher propagation in isolated deinit [fast path]") {
withVouchers { v1, v2, v3 in
let group = DispatchGroup()
group.enter()
group.enter()
group.enter()
Task {
await AnotherActor.shared.performTesting {
adopt(voucher: v1)
_ = ClassWithIsolatedDeinit(expectedVoucher: v1, group: group)
}
await AnotherActor.shared.performTesting {
adopt(voucher: v2)
_ = ActorWithSelfIsolatedDeinit(expectedVoucher: v2, group: group)
}
await AnotherActor.shared.performTesting {
adopt(voucher: v3)
_ = ActorWithDeinitIsolatedOnAnother(expectedVoucher: v3, group: group)

if #available(SwiftStdlib 6.1, *) {
tests.test("voucher propagation in isolated deinit [fast path]") {
withVouchers { v1, v2, v3 in
let group = DispatchGroup()
group.enter()
group.enter()
group.enter()
Task {
await AnotherActor.shared.performTesting {
adopt(voucher: v1)
_ = ClassWithIsolatedDeinit(expectedVoucher: v1, group: group)
}
await AnotherActor.shared.performTesting {
adopt(voucher: v2)
_ = ActorWithSelfIsolatedDeinit(expectedVoucher: v2, group: group)
}
await AnotherActor.shared.performTesting {
adopt(voucher: v3)
_ = ActorWithDeinitIsolatedOnAnother(expectedVoucher: v3, group: group)
}
}
group.wait()
}
group.wait()
}
}

tests.test("voucher propagation in isolated deinit [slow path]") {
withVouchers { v1, v2, v3 in
let group = DispatchGroup()
group.enter()
group.enter()
Task {
do {
adopt(voucher: v1)
_ = ActorWithDeinitIsolatedOnAnother(expectedVoucher: v1, group: group)
}
do {
adopt(voucher: v2)
_ = ClassWithIsolatedDeinit(expectedVoucher: v2, group: group)

tests.test("voucher propagation in isolated deinit [slow path]") {
withVouchers { v1, v2, v3 in
let group = DispatchGroup()
group.enter()
group.enter()
Task {
do {
adopt(voucher: v1)
_ = ActorWithDeinitIsolatedOnAnother(expectedVoucher: v1, group: group)
}
do {
adopt(voucher: v2)
_ = ClassWithIsolatedDeinit(expectedVoucher: v2, group: group)
}
}
group.wait()
}
group.wait()
}
}
}
Expand Down
Loading