Skip to content

Commit

Permalink
Merge branch 'main' into shared-elements-identifiable
Browse files Browse the repository at this point in the history
  • Loading branch information
stephencelis committed Jun 19, 2024
2 parents 3a9cb25 + bc8f27b commit 42bb609
Show file tree
Hide file tree
Showing 69 changed files with 7,048 additions and 7,166 deletions.
30 changes: 15 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,54 +24,54 @@ jobs:
- release
steps:
- uses: actions/checkout@v4
- name: Select Xcode 15.2
run: sudo xcode-select -s /Applications/Xcode_15.2.app
- name: Select Xcode 15.4
run: sudo xcode-select -s /Applications/Xcode_15.4.app
- name: Build ${{ matrix.config }}
run: make CONFIG=${{ matrix.config }} build-all-platforms
- name: Run ${{ matrix.config }} tests
run: make CONFIG=${{ matrix.config }} test-library

library-evolution:
name: Library (evolution)
runs-on: macos-13
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- name: Select Xcode 15.2
run: sudo xcode-select -s /Applications/Xcode_15.2.app
- name: Select Xcode 15.4
run: sudo xcode-select -s /Applications/Xcode_15.4.app
- name: Build for library evolution
run: make build-for-library-evolution

library-compatibility:
name: Library (Swift 5.7.1)
runs-on: macos-12
name: Library (Swift 5.9)
runs-on: macos-14
strategy:
matrix:
config:
- debug
- release
steps:
- uses: actions/checkout@v4
- name: Select Xcode 14.1
run: sudo xcode-select -s /Applications/Xcode_14.1.app
- name: Select Xcode 15.2
run: sudo xcode-select -s /Applications/Xcode_15.2.app
- name: Build ${{ matrix.config }}
run: swift build -c ${{ matrix.config }}

benchmarks:
name: Benchmarks
runs-on: macos-13
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- name: Select Xcode 15.2
run: sudo xcode-select -s /Applications/Xcode_15.2.app
- name: Select Xcode 15.4
run: sudo xcode-select -s /Applications/Xcode_15.4.app
- name: Run benchmark
run: make benchmark

examples:
name: Examples
runs-on: macos-13
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- name: Select Xcode 15.2
run: sudo xcode-select -s /Applications/Xcode_15.2.app
- name: Select Xcode 15.4
run: sudo xcode-select -s /Applications/Xcode_15.4.app
- name: Run tests
run: make test-examples
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@ struct CityMap {
var downloadAlert: AlertState<DownloadComponent.Action.Alert>?
var downloadMode: Mode

var id: UUID { self.download.id }
var id: UUID { download.id }

var downloadComponent: DownloadComponent.State {
get {
DownloadComponent.State(
alert: self.downloadAlert,
id: self.download.id,
mode: self.downloadMode,
url: self.download.downloadVideoUrl
alert: downloadAlert,
id: download.id,
mode: downloadMode,
url: download.downloadVideoUrl
)
}
set {
self.downloadAlert = newValue.alert
self.downloadMode = newValue.mode
downloadAlert = newValue.alert
downloadMode = newValue.mode
}
}

Expand Down Expand Up @@ -80,10 +80,10 @@ struct CityMapRowView: View {
let store: StoreOf<CityMap>

var body: some View {
WithViewStore(self.store, observe: { $0 }) { viewStore in
WithViewStore(store, observe: { $0 }) { viewStore in
HStack {
NavigationLink(
destination: CityMapDetailView(store: self.store)
destination: CityMapDetailView(store: store)
) {
HStack {
Image(systemName: "map")
Expand All @@ -94,7 +94,7 @@ struct CityMapRowView: View {
Spacer()

DownloadComponentView(
store: self.store.scope(state: \.downloadComponent, action: \.downloadComponent)
store: store.scope(state: \.downloadComponent, action: \.downloadComponent)
)
.padding(.trailing, 8)
}
Expand All @@ -107,7 +107,7 @@ struct CityMapDetailView: View {
let store: StoreOf<CityMap>

var body: some View {
WithViewStore(self.store, observe: { $0 }) { viewStore in
WithViewStore(store, observe: { $0 }) { viewStore in
VStack(spacing: 32) {
Text(viewStore.download.blurb)

Expand All @@ -123,7 +123,7 @@ struct CityMapDetailView: View {
Spacer()

DownloadComponentView(
store: self.store.scope(state: \.downloadComponent, action: \.downloadComponent)
store: store.scope(state: \.downloadComponent, action: \.downloadComponent)
)
}

Expand Down Expand Up @@ -160,7 +160,7 @@ struct CitiesView: View {
Section {
AboutView(readMe: readMe)
}
ForEachStore(self.store.scope(state: \.cityMaps, action: \.cityMaps)) { cityMapStore in
ForEachStore(store.scope(state: \.cityMaps, action: \.cityMaps)) { cityMapStore in
CityMapRowView(store: cityMapStore)
.buttonStyle(.borderless)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ enum LogConfiguration {
case unordered
}

extension Snapshotting where Value == String, Format == String {
extension Snapshotting<String, String> {
fileprivate static nonisolated(unsafe) let _lines = Snapshotting(
pathExtension: "txt",
diffing: Diffing(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public enum Player: Equatable, Sendable {
}
}

extension Three where Element == Three<Player?> {
extension Three<Three<Player?>> {
public static let empty = Self(
.init(nil, nil, nil),
.init(nil, nil, nil),
Expand Down
2 changes: 1 addition & 1 deletion Examples/Todos/Todos/Todos.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ struct AppView: View {
}
}

extension IdentifiedArray where ID == Todo.State.ID, Element == Todo.State {
extension IdentifiedArrayOf<Todo.State> {
static let mock: Self = [
Todo.State(
description: "Check Mail",
Expand Down
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
CONFIG = debug
PLATFORM_IOS = iOS Simulator,id=$(call udid_for,iOS 17.2,iPhone \d\+ Pro [^M])
PLATFORM_IOS = iOS Simulator,id=$(call udid_for,iOS 17.5,iPhone \d\+ Pro [^M])
PLATFORM_MACOS = macOS
PLATFORM_MAC_CATALYST = macOS,variant=Mac Catalyst
PLATFORM_TVOS = tvOS Simulator,id=$(call udid_for,tvOS 17.2,TV)
PLATFORM_VISIONOS = visionOS Simulator,id=$(call udid_for,visionOS 1.0,Vision)
PLATFORM_WATCHOS = watchOS Simulator,id=$(call udid_for,watchOS 10.2,Watch)
PLATFORM_TVOS = tvOS Simulator,id=$(call udid_for,tvOS 17.5,TV)
PLATFORM_VISIONOS = visionOS Simulator,id=$(call udid_for,visionOS 1.2,Vision)
PLATFORM_WATCHOS = watchOS Simulator,id=$(call udid_for,watchOS 10.5,Watch)

default: test-all

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,59 @@ references:
)
)
```

## Migrating to 1.11.1

A few bug fixes landed in 1.11.1 that may be source breaking. They are described below:

### `withLock` is now `@MainActor`

In [version 1.11](<doc:MigratingTo1.11>) of the library we deprecated mutating shared state from
asynchronous contexts, such as effects, and instead recommended using the new
``Shared/withLock(_:)`` method. Doing so made it possible to lock all mutations to the shared state
and prevent race conditions (see the [migration guide](<doc:MigratingTo1.11>) for more info).

However, this did leave open the possibility for deadlocks if shared state was read from and written
to on different threads. To fix this we have now restricted ``Shared/withLock(_:)`` to the
`@MainActor`, and so you will now need to `await` its usage:

```diff
-sharedCount.withLock { $0 += 1 }
+await sharedCount.withLock { $0 += 1 }
```

The compiler should suggest this fix-it for you.

### Optional dynamic member lookup on `Shared` is deprecated/disfavored

When the ``Shared`` property wrapper was first introduced, its dynamic member lookup was overloaded
to automatically unwrap optionals for ergonomic purposes:

```swift
if let sharedUnwrappedProperty = $shared.optionalProperty {
// ...
}
```

This unfortunately made dynamic member lookup a little more difficult to understand:

```swift
$shared.optionalProperty // Shared<Value>?, *not* Shared<Value?>
```

and required casting and other tricks to transform shared values into what one might expect.

And so this dynamic member lookup is deprecated and has been disfavored, and will eventually be
removed entirely. Instead, you can use ``Shared/init(_:)`` to explicitly unwrap a shared optional
value.

Disfavoring it does have the consequence of being source breaking in the case of `if let` and
`guard let` expressions, where Swift does not select the optional overload automatically. To
migrate, use ``Shared/init(_:)``:

```diff
-if let sharedUnwrappedProperty = $shared.optionalProperty {
+if let sharedUnwrappedProperty = Shared($shared.optionalProperty) {
// ...
}
```

This file was deleted.

4 changes: 2 additions & 2 deletions Sources/ComposableArchitecture/Effect.swift
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ extension Effect {
/// - Parameter effects: A sequence of effects.
/// - Returns: A new effect
@inlinable
public static func merge<S: Sequence>(_ effects: S) -> Self where S.Element == Self {
public static func merge(_ effects: some Sequence<Self>) -> Self {
effects.reduce(.none) { $0.merge(with: $1) }
}

Expand Down Expand Up @@ -289,7 +289,7 @@ extension Effect {
/// - Parameter effects: A collection of effects.
/// - Returns: A new effect
@inlinable
public static func concatenate<C: Collection>(_ effects: C) -> Self where C.Element == Self {
public static func concatenate(_ effects: some Collection<Self>) -> Self {
effects.reduce(.none) { $0.concatenate(with: $1) }
}

Expand Down
3 changes: 1 addition & 2 deletions Sources/ComposableArchitecture/Effects/Animation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ private struct TransactionPublisher<Upstream: Publisher>: Publisher {
var upstream: Upstream
var transaction: Transaction

func receive<S: Combine.Subscriber>(subscriber: S)
where S.Input == Output, S.Failure == Failure {
func receive(subscriber: some Combine.Subscriber<Upstream.Output, Upstream.Failure>) {
let conduit = Subscriber(downstream: subscriber, transaction: self.transaction)
self.upstream.receive(subscriber: conduit)
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/ComposableArchitecture/Effects/Cancellation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ public func withTaskCancellation<ID: Hashable, T: Sendable>(
}
}

extension Task where Success == Never, Failure == Never {
extension Task<Never, Never> {
/// Cancel any currently in-flight operation with the given identifier.
///
/// - Parameter id: An identifier.
Expand Down
17 changes: 5 additions & 12 deletions Sources/ComposableArchitecture/Effects/Publisher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,8 @@ extension Effect {
///
/// - Parameter createPublisher: The closure to execute when the effect is performed.
/// - Returns: An effect wrapping a Combine publisher.
public static func publisher<P: Publisher>(_ createPublisher: () -> P) -> Self
where P.Output == Action, P.Failure == Never {
Self(
operation: .publisher(
createPublisher().eraseToAnyPublisher()
)
)
public static func publisher(_ createPublisher: () -> some Publisher<Action, Never>) -> Self {
Self(operation: .publisher(createPublisher().eraseToAnyPublisher()))
}
}

Expand All @@ -25,14 +20,12 @@ public struct _EffectPublisher<Action>: Publisher {
self.effect = effect
}

public func receive<S: Combine.Subscriber>(
subscriber: S
) where S.Input == Action, S.Failure == Failure {
self.publisher.subscribe(subscriber)
public func receive(subscriber: some Combine.Subscriber<Action, Failure>) {
publisher.subscribe(subscriber)
}

private var publisher: AnyPublisher<Action, Failure> {
switch self.effect.operation {
switch effect.operation {
case .none:
return Empty().eraseToAnyPublisher()
case let .publisher(publisher):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ final class CurrentValueRelay<Output>: Publisher {
self.currentValue = value
}

func receive<S: Subscriber>(subscriber: S) where S.Input == Output, S.Failure == Never {
func receive(subscriber: some Subscriber<Output, Never>) {
let subscription = Subscription(downstream: AnySubscriber(subscriber))
self.subscriptions.append(subscription)
subscriber.receive(subscription: subscription)
Expand All @@ -32,8 +32,7 @@ final class CurrentValueRelay<Output>: Publisher {
}

extension CurrentValueRelay {
final class Subscription<Downstream: Subscriber>: Combine.Subscription
where Downstream.Input == Output, Downstream.Failure == Failure {
final class Subscription<Downstream: Subscriber<Output, Failure>>: Combine.Subscription {
private var demandBuffer: DemandBuffer<Downstream>?

init(downstream: Downstream) {
Expand Down
Loading

0 comments on commit 42bb609

Please sign in to comment.