Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

Depency liveValue cannot be accessed in static library #1640

Closed
3 tasks done
thd-bs opened this issue Nov 9, 2022 · 5 comments
Closed
3 tasks done

Depency liveValue cannot be accessed in static library #1640

thd-bs opened this issue Nov 9, 2022 · 5 comments
Labels
apple bug Something isn't working due to a bug on Apple's platforms.

Comments

@thd-bs
Copy link

thd-bs commented Nov 9, 2022

Description

When using a static library that defines a new DependencyValues property and defines its TestDependencyKey and DependencyKey conformance in two separate extensions, force-accessing the liveValue from a test using DependencyValues.withValue(\.context, .live) does not work and falls back on the testValue.

This only happens with a static library. Doing this with a dynamic framework works as expected.
It also seems to happen just by running the app and using the dependency (which would make sense).

It seems in _liveValue(_ key: Any.Type) function of the OpenExistential file, that the cast to DependencyKey fails.
Probably linked to how static libraries are compiled, not sure you can do anything about it on your side. Maybe if DependencyKey did not extend TestDependencyKey ? But that's maybe not an option.

I have attached a sample vanilla project that reproduces this issue.

Checklist

  • I have determined whether this bug is also reproducible in a vanilla SwiftUI project.
  • If possible, I've reproduced the issue using the main branch of this package.
  • This issue hasn't been addressed in an existing GitHub issue or discussion.

Expected behavior

Accessing the liveValue from a static library splitting its DependencyKey/TestDependencyKey conformance in 2 extension works.

Actual behavior

Accessing the liveValue from a static library splitting its DependencyKey/TestDependencyKey conformance in 2 extension fallbacks to the testValue.

Steps to reproduce

DependencyIssue.zip

  1. Download the attached project.
  2. Run the test, it will fail because the testValue is accessed instead of the liveValue, as expected by the forced live context.
  3. Run the app, the testValue should also be used.

If you do the same by repackaging the DoSomethingStatic library as a dynamic framework, it works as expected.

The Composable Architecture version information

0.45.0

Destination operating system

iOS 16.1

Xcode version information

Xcode 14.1

Swift Compiler version information

swift-driver version: 1.62.15 Apple Swift version 5.7.1 (swiftlang-5.7.1.135.3 clang-1400.0.29.51)
Target: arm64-apple-macosx12.0
@thd-bs thd-bs added the bug Something isn't working due to a bug in the library. label Nov 9, 2022
@mbrandonw
Copy link
Member

Hi @thd-bs, thank you very much for the easily reproducible sample project. I'm seeing the same. I also tried this with the version of _openExistential that works in 5.6 with the same effect. 🫤

One thing that does fix it is to move the DependencyKey conformance to the same file as the TestDependencyKey conformance. But then that's a bummer because it means you couldn't separate the interface from implementation if you want to use static libraries, but at least it does workaround the issue.

This does feel like a Swift/Xcode bug, but it needs more exploration. Maybe a discussion needs to be opened on the Swift forums or an issue on the Swift repo.

@tgrapperon
Copy link
Contributor

tgrapperon commented Nov 9, 2022

From a quick test, it seems that the compiler thinks that it doesn't need the file and simply doesn't compile it. Adding something in the same file as .liveValue and referencing it in your app's target seems to be enough to make this file build, but I didn't manage to make it works for tests:

extension DoSomethingClient: DependencyKey {
  public static var token: Void = ()

  public static let liveValue: Self = .init(
    doSomething: { print("Do something") }
  )
}

And in your app:

let _ = DoSomethingClient.token

When building a dynamic framework, it doesn't makes assumptions about clients and the file is compiled unconditionally. I don't know if there is a specific attribute to add that could help in this situation.

@mbrandonw
Copy link
Member

@tgrapperon Wild stuff. So seems certainly an Apple/Swift bug.

@mbrandonw mbrandonw added apple bug Something isn't working due to a bug on Apple's platforms. and removed bug Something isn't working due to a bug in the library. labels Nov 10, 2022
@mbrandonw
Copy link
Member

I filed an issue in the Swift repo and feedback on this.

@mbrandonw
Copy link
Member

This seems to be expected behavior of static libraries. See here. That comment also provides a few potential work arounds.

Since this isn't a bug with the library I'm going to convert it to a discussion.

@pointfreeco pointfreeco locked and limited conversation to collaborators Nov 11, 2022
@mbrandonw mbrandonw converted this issue into discussion #1657 Nov 11, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
apple bug Something isn't working due to a bug on Apple's platforms.
Projects
None yet
Development

No branches or pull requests

3 participants