Skip to content

Commit

Permalink
Swift6 (#490)
Browse files Browse the repository at this point in the history
- [x] InoutRef uses Sendable as a workaround. should be non-sendable
  • Loading branch information
muukii authored Dec 13, 2024
1 parent e55c598 commit 9980b55
Show file tree
Hide file tree
Showing 50 changed files with 613 additions and 390 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/CommitChecks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ jobs:
- name: xcbeautify
run: brew install xcbeautify
- name: Run Test
run: set -o pipefail && xcodebuild -scheme Verge-Package test -destination 'platform=iOS Simulator,name=iPhone 15 Pro,OS=17.0.1' | xcbeautify
run: set -o pipefail && xcodebuild -scheme Verge-Package test -destination 'platform=iOS Simulator,name=iPhone 16 Pro,OS=18.1' | xcbeautify
2 changes: 1 addition & 1 deletion .mise.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[tools]
tuist = "4.10.2"
tuist = "4.24.0"
3 changes: 2 additions & 1 deletion Package.resolved
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"originHash" : "82f71c92629a240db65e931912dfb2240dd0b70609e84bc12a7b6ccab081b14b",
"pins" : [
{
"identity" : "rxswift",
Expand Down Expand Up @@ -73,5 +74,5 @@
}
}
],
"version" : 2
"version" : 3
}
22 changes: 12 additions & 10 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// swift-tools-version:5.9
import PackageDescription
// swift-tools-version: 6.0
import CompilerPluginSupport
import PackageDescription

let package = Package(
name: "Verge",
Expand All @@ -26,7 +26,7 @@ let package = Package(
.package(url: "https://github.com/VergeGroup/swift-concurrency-task-manager", from: "1.1.0"),

/// for testing
.package(url: "https://github.com/nalexn/ViewInspector.git", from: "0.9.3"),
.package(url: "https://github.com/nalexn/ViewInspector.git", from: "0.10.0"),
.package(url: "https://github.com/apple/swift-syntax.git", from: "600.0.0"),
.package(url: "https://github.com/pointfreeco/swift-macro-testing.git", from: "0.2.1")
],
Expand All @@ -37,7 +37,7 @@ let package = Package(
name: "VergeMacrosPlugin",
dependencies: [
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
.product(name: "SwiftCompilerPlugin", package: "swift-syntax")
.product(name: "SwiftCompilerPlugin", package: "swift-syntax"),
]
),

Expand Down Expand Up @@ -115,11 +115,13 @@ let package = Package(
name: "VergeTinyTests",
dependencies: ["VergeTiny"]
),
.testTarget(name: "VergeMacrosTests", dependencies: [
"VergeMacrosPlugin",
.product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"),
.product(name: "MacroTesting", package: "swift-macro-testing"),
])
.testTarget(
name: "VergeMacrosTests",
dependencies: [
"VergeMacrosPlugin",
.product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"),
.product(name: "MacroTesting", package: "swift-macro-testing"),
]),
],
swiftLanguageVersions: [.v5]
swiftLanguageModes: [.v6]
)
6 changes: 3 additions & 3 deletions Sources/Verge/Derived/Derived+Assign.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ extension StoreDriverType {
*/
public func assign(
queue: some TargetQueueType = .passthrough,
to binder: @escaping (Changes<TargetStore.State>) -> Void
to binder: @escaping @Sendable (Changes<TargetStore.State>) -> Void
) -> StoreStateSubscription {
store.asStore().sinkState(queue: queue, receive: binder)
}
Expand All @@ -39,8 +39,8 @@ extension StoreDriverType {
- Returns: a cancellable. See detail of handling cancellable from ``StoreSubscription``'s docs
*/
public func assign(
queue: MainActorTargetQueue,
to binder: @escaping (Changes<TargetStore.State>) -> Void
queue: some MainActorTargetQueueType,
to binder: @escaping @MainActor (Changes<TargetStore.State>) -> Void
) -> StoreStateSubscription {
store.asStore().sinkState(queue: queue, receive: binder)
}
Expand Down
20 changes: 10 additions & 10 deletions Sources/Verge/Derived/Derived.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,13 @@ public class Derived<Value: Equatable>: Store<Value, Never>, DerivedType, @unche
get pipeline: Pipeline,
set: ((Value) -> Void)?,
initialUpstreamState: UpstreamState,
subscribeUpstreamState: (@escaping (UpstreamState) -> Void) -> any Cancellable,
subscribeUpstreamState: (@escaping @Sendable (UpstreamState) -> Void) -> any Cancellable,
retainsUpstream: Any?
) where Pipeline.Input == UpstreamState, Value == Pipeline.Output {

weak var indirectSelf: Derived<Value>?
nonisolated(unsafe) weak var indirectSelf: Derived<Value>?

let s = subscribeUpstreamState { value in
let s = subscribeUpstreamState { @Sendable value in
let update = pipeline.yieldContinuously(value)
switch update {
case .noUpdates:
Expand All @@ -121,7 +121,7 @@ public class Derived<Value: Equatable>: Store<Value, Never>, DerivedType, @unche
}

// TODO: Take over state.modification & state.mutation
indirectSelf._receive {
indirectSelf._receive_sending {
$1.isDerivedFromUpstream = true
$0.append(traces: value.traces)
$0.replace(with: newState)
Expand Down Expand Up @@ -173,7 +173,7 @@ public class Derived<Value: Equatable>: Store<Value, Never>, DerivedType, @unche
private func _combined_sinkValue(
dropsFirst: Bool = false,
queue: some TargetQueueType,
receive: @escaping (Changes<Value>) -> Void
receive: @escaping @Sendable (Changes<Value>) -> Void
) -> StoreStateSubscription {
_primitive_sinkState(
dropsFirst: dropsFirst,
Expand Down Expand Up @@ -226,7 +226,7 @@ extension Derived where Value : Equatable {
public func sinkChangedPrimitiveValue(
dropsFirst: Bool = false,
queue: some TargetQueueType,
receive: @escaping (Value) -> Void
receive: @escaping @Sendable (Value) -> Void
) -> StoreStateSubscription {
sinkState(dropsFirst: dropsFirst, queue: queue) { (changes) in
changes.ifChanged().do { value in
Expand All @@ -242,7 +242,7 @@ extension Derived where Value : Equatable {
/// - Returns: A subscriber that performs the provided closure upon receiving values.
public func sinkChangedPrimitiveValue(
dropsFirst: Bool = false,
queue: MainActorTargetQueue = .mainIsolated(),
queue: some MainActorTargetQueueType = .mainIsolated(),
receive: @escaping @MainActor (Value) -> Void
) -> StoreStateSubscription {
sinkState(dropsFirst: dropsFirst, queue: queue) { @MainActor changes in
Expand Down Expand Up @@ -276,7 +276,7 @@ extension Derived where Value == Never {
let buffer = VergeConcurrency.RecursiveLockAtomic.init(initial)

return Derived<Edge<(Changes<S0>, Changes<S1>)>>(
get: .select({ $0 }),
get: .select(\.self),
set: { _ in },
initialUpstreamState: initial,
subscribeUpstreamState: { callback in
Expand Down Expand Up @@ -340,7 +340,7 @@ extension Derived where Value == Never {
let buffer = VergeConcurrency.RecursiveLockAtomic.init(initial)

return Derived<Edge<(Changes<S0>, Changes<S1>, Changes<S2>)>>(
get: .select { $0 },
get: .select(\.self),
set: { _ in },
initialUpstreamState: initial,
subscribeUpstreamState: { callback in
Expand Down Expand Up @@ -407,7 +407,7 @@ extension Derived where Value == Never {
In most cases, `Store` will be running underlying.
*/
@propertyWrapper
public final class BindingDerived<Value: Equatable>: Derived<Value> {
public final class BindingDerived<Value: Equatable>: Derived<Value>, @unchecked Sendable {

/**
Returns a derived value that created by get-pipeline.
Expand Down
73 changes: 62 additions & 11 deletions Sources/Verge/Library/InoutRef.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,11 @@ public struct InoutRef<Wrapped> {

private(set) var nonatomic_hasModified = false

private var nonatomic_modifiedKeyPaths: Set<PartialKeyPath<Wrapped>> = .init()
nonisolated(unsafe) private var nonatomic_modifiedKeyPaths: Set<PartialKeyPath<Wrapped>> = .init()

private var nonatomic_wasModifiedIndeterminate = false

private let pointer: UnsafeMutablePointer<Wrapped>
nonisolated(unsafe) private let pointer: UnsafeMutablePointer<Wrapped>

/// A wrapped value
/// You may use this property to call the mutating method which `Wrapped` has.
Expand Down Expand Up @@ -318,35 +318,81 @@ public struct InoutRef<Wrapped> {
Returns a tantative InoutRef that projects the value specified by KeyPath.
That InoutRef must be used only in the given perform closure.
*/
public mutating func map<U, Result>(keyPath: WritableKeyPath<Wrapped, U>, perform: (inout InoutRef<U>) throws -> Result) rethrows -> Result {
try withUnsafeMutablePointer(to: &pointer.pointee[keyPath: keyPath]) { (pointer) in
public mutating func map<U, Result>(
keyPath: WritableKeyPath<Wrapped, U>,
perform: (inout InoutRef<U>) throws -> Result
) rethrows -> Result {

try map_sending(keyPath: keyPath, perform: {
let r = try perform(&$0)
/// https://github.com/swiftlang/swift/issues/78135
let workaround = { r }
return workaround()
})

}

public mutating func map_sending<U, Result>(
keyPath: WritableKeyPath<Wrapped, U>,
perform: (inout InoutRef<U>) throws -> sending Result
) rethrows -> sending Result {

let result = try withUnsafeMutablePointer(to: &pointer.pointee[keyPath: keyPath]) { (pointer) in

var ref = InoutRef<U>.init(pointer)

defer {
self.nonatomic_hasModified = ref.nonatomic_hasModified
self.nonatomic_wasModifiedIndeterminate = ref.nonatomic_wasModifiedIndeterminate

let appended = ref.nonatomic_modifiedKeyPaths.compactMap {
(keyPath as PartialKeyPath<Wrapped>).appending(path: $0)
}

self.nonatomic_modifiedKeyPaths.formUnion(appended)

}
return try perform(&ref)

let result = try perform(&ref)

return result
}

let workaround = { result }
return workaround()

}

public mutating func map<U, Result>(
keyPath: WritableKeyPath<Wrapped, U?>,
perform: (inout InoutRef<U>) throws -> Result
) rethrows -> Result? {

try map_sending(keyPath: keyPath, perform: {
let r = try perform(&$0)
/// https://github.com/swiftlang/swift/issues/78135
let workaround = { r }
return workaround()
})
}

/**
Returns a tantative InoutRef that projects the value specified by KeyPath.
That InoutRef must be used only in the given perform closure.
*/
public mutating func map<U, Result>(keyPath: WritableKeyPath<Wrapped, U?>, perform: (inout InoutRef<U>) throws -> Result) rethrows -> Result? {
public mutating func map_sending<U, Result>(
keyPath: WritableKeyPath<Wrapped, U?>,
perform: (inout InoutRef<U>) throws -> sending Result
) rethrows -> sending Result? {

guard pointer.pointee[keyPath: keyPath] != nil else {
return nil
}

return try withUnsafeMutablePointer(to: &pointer.pointee[keyPath: keyPath]!) { (pointer) in
var ref: InoutRef<U> = InoutRef<U>.init(pointer)
let result = try withUnsafeMutablePointer(to: &pointer.pointee[keyPath: keyPath]!) { (pointer) in

var ref = InoutRef<U>.init(pointer)

defer {
self.nonatomic_hasModified = ref.nonatomic_hasModified
self.nonatomic_wasModifiedIndeterminate = ref.nonatomic_wasModifiedIndeterminate
Expand All @@ -358,9 +404,14 @@ public struct InoutRef<Wrapped> {
self.nonatomic_modifiedKeyPaths.formUnion(appended)

}
return try perform(&ref)

let result = try perform(&ref)

return result
}

let workaround = { result }
return workaround()
}

}
Expand Down
1 change: 1 addition & 0 deletions Sources/Verge/Library/Signpost.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import Foundation

nonisolated(unsafe)
public var _verge_signpost_enabled = ProcessInfo.processInfo.environment["VERGE_SIGNPOST_ENABLED"] != nil

@usableFromInline
Expand Down
2 changes: 1 addition & 1 deletion Sources/Verge/Library/VergeAnyCancellable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public final class VergeAnyCancellable: Hashable, Cancellable, @unchecked Sendab
public init() {
}

public convenience init(onDeinit: @escaping @Sendable () -> Void) {
public convenience init(onDeinit: @escaping () -> Void) {
self.init()
self.actions = [onDeinit]
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/Verge/Library/VergeConcurrency.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ import Foundation

public enum VergeConcurrency {

public final class RecursiveLock: NSRecursiveLock {
public final class RecursiveLock: NSRecursiveLock, @unchecked Sendable {

}

public struct UnfairLock: ~Copyable {
public struct UnfairLock: ~Copyable, @unchecked Sendable {
private let _lock: os_unfair_lock_t

public init() {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Verge/Logging/ActivityTrace.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import Foundation

/// A trace that indicates the activity where comes from.
public struct ActivityTrace: Encodable {
public struct ActivityTrace: Encodable, Sendable {

public let createdAt: Date = .init()
public let name: String
Expand Down
Loading

0 comments on commit 9980b55

Please sign in to comment.