I'm trying to implement SwiftUI's @Environment
as a macro (similar to this question). Here's the property wrapper API I am trying to replicate:
@propertyWrapper
public struct Environment<Value>: DynamicProperty {
public init(_ keyPath: KeyPath<EnvironmentValues, Value>)
public var wrappedValue: Value { get }
}
So I tried using an accessor macro that provides the getter and a peer macro that generates the Environment<Value>
storage variable:
@attached(accessor)
@attached(peer, names: prefixed(_))
public macro Environment<V>(_ keyPath: _const KeyPath<EnvironmentValues, V>) = ...
The problem is that clients can invoke the macro with a key path whose value type is, say, Int
, yet the variable declaration can have String
type. For instance:
extension EnvironmentValues {
var myInt: Int { 0 }
}
struct MyType {
@Environment(\.myInt) var myString: String // no errors here
}
Obviously, clients get an error in the expanded macro code, but that's a really bad UX. Ideally, I'd like to have Swift type-check the given key-path literal to ensure its value matches the variable declaration's type. Otherwise, I'd like a way for my macro to check for type equality between the key-path value and the variable declaration. I think the latter was proposed here.
So I wonder if there's an existing way/hack to get unambiguous type-checking on the declaration itself, or if I have to wait for features like context.getType(of:)
. Thanks in advance!