Skip to content

Commit

Permalink
feat(Swift6.0): Introduce Sendable APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
maximkrouk committed Sep 21, 2024
1 parent 1c9e08e commit be2fd3a
Show file tree
Hide file tree
Showing 8 changed files with 1,237 additions and 736 deletions.
53 changes: 31 additions & 22 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,35 @@
import PackageDescription

let package = Package(
name: "swift-capture",
products: [
.library(
name: "Capture",
targets: ["Capture"]
)
],
dependencies: [
.package(
url: "https://github.com/apple/swift-docc-plugin.git",
from: "1.3.0"
),
],
targets: [
.target(name: "Capture"),
.testTarget(
name: "CaptureTests",
dependencies: [
.target(name: "Capture")
]
),
]
name: "swift-capture",
products: [
.library(
name: "Capture",
targets: ["Capture"]
)
],
dependencies: [
.package(
url: "https://github.com/apple/swift-docc-plugin.git",
from: "1.4.0"
),
],
targets: [
.target(name: "Capture"),
.testTarget(
name: "CaptureTests",
dependencies: [
.target(name: "Capture")
]
),
]
)

#if compiler(>=6)
for target in package.targets where target.type != .system && target.type != .test {
target.swiftSettings = target.swiftSettings ?? []
target.swiftSettings?.append(contentsOf: [
.enableUpcomingFeature("InferSendableFromCaptures")
])
}
#endif
37 changes: 37 additions & 0 deletions [email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// swift-tools-version:6.0

import PackageDescription

let package = Package(
name: "swift-capture",
products: [
.library(
name: "Capture",
targets: ["Capture"]
)
],
dependencies: [
.package(
url: "https://github.com/apple/swift-docc-plugin.git",
from: "1.4.0"
),
],
targets: [
.target(name: "Capture"),
.testTarget(
name: "CaptureTests",
dependencies: [
.target(name: "Capture")
]
),
],
swiftLanguageModes: [.v6]
)

for target in package.targets where target.type == .system || target.type == .test {
target.swiftSettings?.append(contentsOf: [
.swiftLanguageMode(.v5),
.enableExperimentalFeature("StrictConcurrency"),
.enableUpcomingFeature("InferSendableFromCaptures"),
])
}
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# swift-capture

[![test](https://github.com/CaptureContext/swift-capture/actions/workflows/Test.yml/badge.svg)](https://github.com/CaptureContext/swift-capture/actions/workflows/Test.yml) [![SwiftPM 5.9](https://img.shields.io/badge/📦_swiftpm-5.9-ED523F.svg?style=flat)](https://github.com/CaptureContext/swift-declarative-configuration/actions/workflows/Test.yml) ![Platforms](https://img.shields.io/badge/platforms-iOS_|_macOS_|_tvOS_|_watchOS_|_Catalyst-ED523F.svg?style=flat)
[![test](https://github.com/CaptureContext/swift-capture/actions/workflows/Test.yml/badge.svg)](https://github.com/CaptureContext/swift-capture/actions/workflows/Test.yml) ![SwiftPM 5.9](https://img.shields.io/badge/📦_swiftpm-5.9_|_6.0-ED523F.svg?style=flat) ![Platforms](https://img.shields.io/badge/platforms-iOS_|_macOS_|_tvOS_|_watchOS_|_Catalyst-ED523F.svg?style=flat)
[![docs](https://img.shields.io/badge/docs-spi-ED523F.svg?style=flat)]([https://twitter.com/capture_context](https://swiftpackageindex.com/CaptureContext/swift-capture/3.0.1/documentation)) [![@capture_context](https://img.shields.io/badge/contact-@capture__context-1DA1F2.svg?style=flat&logo=twitter)](https://twitter.com/capture_context)

A mechanism for ergonomic and safe capturing & weakifying objects in Swift.
Expand Down Expand Up @@ -47,7 +47,7 @@ capture { _self, a, b, c in
}
```

---
----

Methods

Expand Down Expand Up @@ -77,6 +77,13 @@ let object.dataSource = { [weak self] in
let object.dataSource = capture(orReturn: [], in: \.data)
```

----

Sendable closures (_beta_)

> Prefix `capture` methods with an underscore to use explicit sendable closures
> Tho closures should implicitly infer sendable conformance (see [Package.swift](./Package.swift#L34))
## Installation

### Basic
Expand All @@ -94,7 +101,7 @@ If you use SwiftPM for your project, you can add `weak` to your package file. Al
```swift
.package(
url: "[email protected]:capturecontext/swift-capture.git",
.upToNextMajor("3.0.0")
.upToNextMajor("4.0.0-beta")
)
```

Expand Down
142 changes: 115 additions & 27 deletions Sources/Capture/Capture.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,69 +5,128 @@ import Foundation
/// Weakly captures an object in non-parametrized void result closure.
@inlinable
public func capture<Object: AnyObject>(
_ object: Object,
in closure: @escaping (Object) -> Void
_ object: Object,
in closure: @escaping (Object) -> Void
) -> () -> Void {
return Weak(object).capture(in: closure)
return Weak(object).capture(in: closure)
}

/// Weakly captures an object in non-parametrized lazy void result closure.
@inlinable
public func capture<Object: AnyObject>(
_ object: Object,
in closure: @escaping (Object) -> () -> Void
_ object: Object,
in closure: @escaping (Object) -> () -> Void
) -> () -> Void {
Weak(object).capture(in: closure)
Weak(object).capture(in: closure)
}

/// Weakly captures an object in parametrized void result closure.
public func capture<Object: AnyObject, each Arg>(
_ object: Object,
in closure: @escaping (Object, repeat each Arg) -> Void
_ object: Object,
in closure: @escaping (Object, repeat each Arg) -> Void
) -> (repeat each Arg) -> Void {
Weak(object).capture(in: closure)
Weak(object).capture(in: closure)
}

// MARK: Sendable

/// Weakly captures an object in non-parametrized void result closure.
@inlinable
public func capture<Object: AnyObject & Sendable>(
_ object: Object,
in closure: @escaping @Sendable (Object) -> Void
) -> @Sendable () -> Void {
return Weak(object)._capture(in: closure)
}

/// Weakly captures an object in non-parametrized lazy void result closure.
@inlinable
public func capture<Object: AnyObject & Sendable>(
_ object: Object,
in closure: @escaping @Sendable (Object) -> () -> Void
) -> @Sendable () -> Void {
Weak(object)._capture(in: closure)
}

/// Weakly captures an object in parametrized void result closure.
public func _capture<Object: AnyObject & Sendable, each Arg>(
_ object: Object,
in closure: @escaping @Sendable (Object, repeat each Arg) -> Void
) -> @Sendable (repeat each Arg) -> Void {
Weak(object)._capture(in: closure)
}

// MARK: - Non-void result closures

/// Weakly captures an object in non-parametrized non-void result closure.
@inlinable
public func capture<Object: AnyObject, Output>(
_ object: Object,
orReturn defaultValue: @escaping @autoclosure () -> Output,
in closure: @escaping (Object) -> Output
_ object: Object,
orReturn defaultValue: @escaping @autoclosure () -> Output,
in closure: @escaping (Object) -> Output
) -> () -> Output {
Weak(object).capture(orReturn: defaultValue(), in: closure)
Weak(object).capture(orReturn: defaultValue(), in: closure)
}

/// Weakly captures an object in non-parametrized lazy non-void result closure.
@inlinable
public func capture<Object: AnyObject, Output>(
_ object: Object,
orReturn defaultValue: @escaping @autoclosure () -> Output,
in closure: @escaping (Object) -> () -> Output
_ object: Object,
orReturn defaultValue: @escaping @autoclosure () -> Output,
in closure: @escaping (Object) -> () -> Output
) -> () -> Output {
Weak(object).capture(orReturn: defaultValue(), in: closure)
Weak(object).capture(orReturn: defaultValue(), in: closure)
}

/// Weakly captures an object in parametrized non-void result closure.
public func capture<Object: AnyObject, each Arg, Output>(
_ object: Object,
orReturn defaultValue: @escaping @autoclosure () -> Output,
in closure: @escaping (Object, repeat each Arg) -> Output
_ object: Object,
orReturn defaultValue: @escaping @autoclosure () -> Output,
in closure: @escaping (Object, repeat each Arg) -> Output
) -> (repeat each Arg) -> Output {
Weak(object).capture(orReturn: defaultValue(), in: closure)
Weak(object).capture(orReturn: defaultValue(), in: closure)
}

// MARK: Sendable

/// Weakly captures an object in non-parametrized non-void result closure.
@inlinable
public func _capture<Object: AnyObject & Sendable, Output>(
_ object: Object,
orReturn defaultValue: @escaping @autoclosure () -> Output,
in closure: @escaping (Object) -> Output
) -> () -> Output {
Weak(object).capture(orReturn: defaultValue(), in: closure)
}

/// Weakly captures an object in non-parametrized lazy non-void result closure.
@inlinable
public func _capture<Object: AnyObject & Sendable, Output>(
_ object: Object,
orReturn defaultValue: @escaping @autoclosure () -> Output,
in closure: @escaping (Object) -> () -> Output
) -> () -> Output {
Weak(object).capture(orReturn: defaultValue(), in: closure)
}

/// Weakly captures an object in parametrized non-void result closure.
public func _capture<Object: AnyObject & Sendable, each Arg, Output>(
_ object: Object,
orReturn defaultValue: @escaping @autoclosure @Sendable () -> Output,
in closure: @escaping @Sendable (Object, repeat each Arg) -> Output
) -> @Sendable (repeat each Arg) -> Output {
Weak(object)._capture(orReturn: defaultValue(), in: closure)
}

// MARK: - Non-void optional result closures

/// Weakly captures an object in non-parametrized non-void optional result closure.
@inlinable
public func capture<Object: AnyObject, Output>(
_ object: Object,
in closure: @escaping (Object) -> Output?
_ object: Object,
in closure: @escaping (Object) -> Output?
) -> () -> Output? {
Weak(object).capture(in: closure)
Weak(object).capture(in: closure)
}

/// Weakly captures an object in non-parametrized lazy non-void optional result closure.
Expand All @@ -81,8 +140,37 @@ public func capture<Object: AnyObject, Output>(

/// Weakly captures an object in parametrized non-void optional result closure.
public func capture<Object: AnyObject, each Arg, Output>(
_ object: Object,
in closure: @escaping (Object, repeat each Arg) -> Output?
_ object: Object,
in closure: @escaping (Object, repeat each Arg) -> Output?
) -> (repeat each Arg) -> Output? {
Weak(object).capture(in: closure)
Weak(object).capture(in: closure)
}

// MARK: Sendable

/// Weakly captures an object in non-parametrized non-void optional result closure.
@inlinable
public func _capture<Object: AnyObject & Sendable, Output>(
_ object: Object,
in closure: @escaping @Sendable (Object) -> Output?
) -> @Sendable () -> Output? {
Weak(object)._capture(in: closure)
}

/// Weakly captures an object in non-parametrized lazy non-void optional result closure.
@inlinable
public func _capture<Object: AnyObject & Sendable, Output>(
_ object: Object,
in closure: @escaping @Sendable (Object) -> () -> Output?
) -> @Sendable () -> Output? {
Weak(object)._capture(in: closure)
}

/// Weakly captures an object in parametrized non-void optional result closure.
public func _capture<Object: AnyObject & Sendable, each Arg, Output>(
_ object: Object,
in closure: @escaping @Sendable (Object, repeat each Arg) -> Output?
) -> @Sendable (repeat each Arg) -> Output? {
Weak(object)._capture(in: closure)
}

Loading

0 comments on commit be2fd3a

Please sign in to comment.