Swift currently allows one to make a property wrapper that can throw:
@propertyWrapper
struct Foo {
var wrappedValue: String
enum FooError: Error {
case foo
}
init(wrappedValue x: String) throws {
// try parsing from the wrapped value
throw FooError.foo
}
}
But whenever I try to use such a property wrapper, I get a compiler error:
struct Bar {
@Foo var bar: String // Error: call can throw, but errors cannot
// be thrown out of a property initializer
init(bar: Int?) throws {
try self.bar = bar
}
}
What am I doing wrong? Or are throwing property wrapper inits simply not feasible in current Swift?
The only workarounds currently that I'm aware of is to catch any errors that might be thrown inside the init method of the property wrapper, and then either call fatalError() or use some default value for the wrapped value, neither of which seem very ideal...
Currently, a read-only computed property's accessor can throw, not a property wrapper's accessor or initializer. So, you would see an error like this:
@propertyWrapper
struct Abstraction<T> {
private var value : T
init(_ initial : T) { self.value = initial }
var wrappedValue : T {
// error: property wrappers currently cannot define an 'async' or 'throws' accessor
get throws { return value }
}
}
During the review of SE-310, there was a desire to expand coverage of effectful properties to include a property wrapper's accessors and settable computed properties. I think it's feasible to do it at some point. I'm not sure if effects make sense on a property wrapper's initializer, though.
In my case, the property wrapper is wrapping a property whose creation involves calling a throwing function. It should never actually throw at runtime if everything is setup properly, so I don't want to resort to making the property optional and just returning nil if it fails. However if the initialization does fail, I would prefer to have the tools to handle that situation gracefully, rather than being forced to resort to fatalError() or returning a default value.
If it's really a misconfiguration that shouldn't ever happen with a correctly-written client, fatalError is honestly the more graceful way to fail, rather than forcing clients to deal with a fake source of dynamic failure.
Wondering if there are any current plans to support async/throws on property wrapper accessors?
For context, the use case I'm thinking of is using @propertyWrappers for relationships in an ORM. Right now the relationship needs to be eager loaded otherwise accessing the property will fatalError.
Ideally the @propertyWrapper accessor could be marked as async throws. When accessed, it would would return any eager loaded value immediately or, if not eager loaded, asynchronously load the relationship on the fly.