[swift-evolution] [Pitch] Consistent bridging for NSErrors at the language boundary

Shawn Erickson shawnce at gmail.com
Mon Jun 20 13:39:52 CDT 2016


Thanks, overlooked the proposal (or forgot about it)... will try to get
some time to look it over.

On Mon, Jun 20, 2016 at 11:03 AM Charles Srstka <cocoadev at charlessoft.com>
wrote:

> It was deferred until after Swift 3.0.
>
> https://github.com/apple/swift-evolution/pull/331
>
> I plan to resubmit the proposal after Swift 3.0 comes out. Do you have any
> improvements or suggestions for it?
>
> Charles
>
> On Jun 20, 2016, at 12:51 PM, Shawn Erickson <shawnce at gmail.com> wrote:
>
>
> I am curious on the disposition of this discussion / proposal pitch. Has
> any additional effort taken place since this email thread tampered off?
>
> On Sat, May 14, 2016 at 2:40 AM Charles Srstka via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> On May 14, 2016, at 3:51 AM, Michael Peternell <michael.peternell at gmx.at>
>> wrote:
>>
>>
>> For interoperability, ErrorType and NSError should be toll-free-bridged,
>> like CFStringRef and NSString. Converting between them should be a no-op at
>> runtime.
>>
>>
>> That would be technically infeasible without restricting ErrorType to
>> reference types using the Objective-C runtime, which I don’t think anyone
>> wants to do.
>>
>> I prefer runtime/ABI consistency over syntax/language consistency.
>> MyErrorType2 should be represented as an NSError with domain
>> @"MyErrorType2", whatever code is defined in that error type, and if you
>> want userInfo you have to create the beast as an NSError object in the
>> first place. I think userInfo is not visible in the
>> Swift-enum-representation. If you want to have a Swift Error representation
>> that includes userInfo, you'd have to either change the architecture or
>> introduce special support on the language level (e.g. a magic `er.userInfo`
>> of type `Dictionary<String,AnyObject>` for every `er: ErrorType` and a
>> `er.withUserInfo(userInfo)` to add a userInfo dictionary to an error type:
>> e.g.
>> `MyErrorType2.fooConditionFound.withUserInfo([NSLocalizedDescriptionKey:
>> "that was really bad"])` and maybe even a convenience method as a protocol
>> extension like
>> `MyErrorType.fooConditionFound.withLocalizedDescription(localizedString:
>> "ReallyBad")`.
>>
>>
>> Adding a userInfo property to the protocol declaration (with a default
>> implementation for those that don’t want to implement it) would solve this
>> without any low-level hacking.
>>
>> And the key of a dictionary should really always be a String, not just an
>> NSObject.)
>>
>>
>> I actually agree; I used [NSObject : AnyObject] since that’s what
>> NSError’s userInfo is currently defined as. Putting [String : AnyObject] in
>> the protocol instead would be fine, although you’d have to do a little
>> sanity checking in the bridging to filter out non-string keys from the
>> dictionary.
>>
>> (I know if you have something like `case SpecialError(Int)` in your
>> ErrorType declaration, the above method does not work; you'd have to create
>> an NSError-subclass for it. Or maybe not? Just add a "SpecialError_arg0"
>> key to userInfo, value can be an NSNumber? There are more edge cases here
>> but they are all solvable.)
>>
>> On the other hand, I don't think that enumerations in general should
>> support instance variables. One of the nice things for an enum is that I as
>> a programmer can always be sure that it *is* just an enum, and nothing
>> else. Adding iVars to enums would effectively turning enums to structs, and
>> each time I see a switch statement I'll have to think "is this really all?
>> or is there some stealth value attached to this enum? is every
>> .MadeAMistake object always the same?" Keeping the inconsistency
>> constrained to the ErrorType is much nicer than turning every enum into a
>> struct.
>>
>>
>> Adding instance variables to enums is not necessary for this. The
>> userInfo here can be implemented as a computed property, as it would be in
>> enums (in classes and structs, of course, it would be up to the developer
>> whether to make it a stored or computed property).
>>
>> There will always be rough edges when converting between two languages,
>> that's unavoidable. Try to translate a text that contains a lot of the
>> words "safety" and "security" into German. Good luck, they both translate
>> to the same word. And so there also cannot be a perfectly consistent
>> translation between ErrorType and NSError. If you want to achieve a good
>> translation, you'd have to change the ErrorType to something different.
>> E.g. a special language construct `def-error MyErrorType { case
>> MadeAMistake; case RanOutOfCake }` - matching works the same as now and you
>> have a userInfo property. And on non-objc-platforms, the NSError() name
>> becomes unavailable and .userInfo always returns `[:]`. I'm not saying that
>> this would be a beautiful solution; I'm saying that there is no beautiful
>> solution to this problem.
>>
>>
>> I think that creating wrappers for both directions could work pretty well
>> if we had a userInfo property on ErrorType/Protocol. We’ve got one going in
>> one direction already.
>>
>> Charles
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160620/7eef378f/attachment.html>


More information about the swift-evolution mailing list