Hi everyone
Looking for help with a problem.
I a DI system that uses type as a key. The code to compute key is straightforward:
private func computeKey<Service>(_: Service.Type) -> ObjectIdentifier {
ObjectIdentifier(Service.self)
}
The problem is that with a different project structure, this sometimes produces different identifiers for the same type.
It looks like when the type comes from outside the package it is different from when the package containing type uses it. String(describing:) produces the same result. So the type is supposed to be the same.
What build setting should I look for that could alter this behavior?
The setop that works uses SPM all the way. The setup that fails uses Tuist. I forced all packages built via Tuist to use dynamic framework type as much as possible. But the issue still persists.
Thanks in advance
Do you mean that two values from differing executables output different values for pointers. Depending on the memory location the binary is pointing to the value can be executable dependent, runtime dependent or co-operative interaction dependent. I believe metatypes to be located within the generated executable or object files. It seems like potentially the metatypes might not have shared storage across the entire executable.
If this is not your issue; This does feel like a bug or unintended side-effect of how Tuist operates compared to SPM. This leads me to refer you to GitHub issues or the Community Forums for Tuist.
If you want more background on why ObjectIdentifier behaves as such then you can read more from the sources provided below.
Internally, ObjectIdentifier is just a wrapper for an object's memory address.
public struct ObjectIdentifier {
internal let _value: Builtin.RawPointer
public init(_ x: AnyObject) {
self._value = Builtin.bridgeToRawPointer(x)
}
public init(_ x: Any.Type) {
self._value = unsafeBitCast(x, to: Builtin.RawPointer.self)
}
}
Code Exerpt belongs to the Swift Standard Library
I narrowed it down a bit. The issue happens because of static-dynamic frameworks zoo. I suspect SPM was making everything dynamic, and that was OK. But Tuist uses static frameworks by default for external dependencies. And many of my packages are treated as external because they come from other repos.
Unfortunately the issue goes beyond ObjectIdentifier, casts fail too. E.g. instance as? Service.
The issue seems to happen if dependency chains are a mix of static and dynamic artifacts. E.g.
App - DepA(dynamic) - DepX(dynamic)
App - DepB(static) - DepX(dynamic)
For now the workaround seems to force everything to be either static or dynamic. But with a large dependency graph it is hard. I hoped there is some way to make compiler/linker take care of it with the binary zoo.