Skip to content

Fix the issue where AtomEffectBuilder fails to demangle witness for the resulting type of multiple blocks #193

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 1 commit into from
Jun 18, 2025

Conversation

ra1028
Copy link
Owner

@ra1028 ra1028 commented Jun 18, 2025

Pull Request Type

  • Bug fix
  • New feature
  • Refactoring
  • Documentation update
  • Chore

…he return type of the builder with multiple blocks in iOS 16
@ra1028 ra1028 marked this pull request as ready for review June 18, 2025 10:14
@Copilot Copilot AI review requested due to automatic review settings June 18, 2025 10:14
@ra1028 ra1028 merged commit 150f350 into main Jun 18, 2025
6 checks passed
@ra1028 ra1028 deleted the fix-demangling-failure branch June 18, 2025 10:15
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR addresses a runtime crash on iOS 16 by replacing the variadic opaque return type in buildBlock(_:) with a concrete BlockEffect and adds a zero-argument overload returning EmptyEffect. It also cleans up legacy conditional types by removing BlockBCEffect and the availability branch.

  • Added buildBlock() overload returning EmptyEffect for empty cases
  • Converted variadic buildBlock<each Effect> to return a concrete BlockEffect
  • Removed legacy BlockBCEffect and iOS 17 availability checks, moved BlockEffect into public API
Comments suppressed due to low confidence (1)

Sources/Atoms/Effect/AtomEffectBuilder.swift:22

  • No tests cover the new zero-argument buildBlock() path. Consider adding a unit test to verify that buildBlock() returns an EmptyEffect and that it behaves as a no-op effect.
    public static func buildBlock() -> some AtomEffect {

@@ -54,6 +56,46 @@ public enum AtomEffectBuilder {
}

public extension AtomEffectBuilder {
// Use type pack once it is available in iOS 17 or newer.
// struct BlockEffect<each Effect: AtomEffect>: AtomEffect
struct BlockEffect: AtomEffect {
Copy link
Preview

Copilot AI Jun 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider annotating BlockEffect (and its initializer and methods) with @MainActor to enforce actor isolation and prevent potential threading issues, aligning with the @MainActor context of AtomEffectBuilder.

Copilot uses AI. Check for mistakes.

Comment on lines +68 to +79
_initializing = { context in
repeat (each effect).initializing(context: context)
}
_initialized = { context in
repeat (each effect).initialized(context: context)
}
_updated = { context in
repeat (each effect).updated(context: context)
}
_released = { context in
repeat (each effect).released(context: context)
}
Copy link
Preview

Copilot AI Jun 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The initializer and the related closure properties (_initializing, _initialized, etc.) are repetitive. Consider abstracting the repeated logic—e.g., iterating over a collection of effects in a single closure—to reduce boilerplate.

Suggested change
_initializing = { context in
repeat (each effect).initializing(context: context)
}
_initialized = { context in
repeat (each effect).initialized(context: context)
}
_updated = { context in
repeat (each effect).updated(context: context)
}
_released = { context in
repeat (each effect).released(context: context)
}
_initializing = createEffectHandler(effect: repeat each effect, method: { $0.initializing(context:) })
_initialized = createEffectHandler(effect: repeat each effect, method: { $0.initialized(context:) })
_updated = createEffectHandler(effect: repeat each effect, method: { $0.updated(context:) })
_released = createEffectHandler(effect: repeat each effect, method: { $0.released(context:) })
}
private func createEffectHandler<each Effect: AtomEffect>(
effect: repeat each Effect,
method: @escaping (Effect) -> (Context) -> Void
) -> @MainActor (Context) -> Void {
return { context in
repeat method(each effect)(context)
}

Copilot uses AI. Check for mistakes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant