[swift-evolution] [Review] SE-0112: Improved NSError Bridging

Brent Royal-Gordon brent at architechies.com
Fri Jul 1 20:25:25 CDT 2016


> 	* What is your evaluation of the proposal?

Massively in favor overall. I use NSError features heavily in Objective-C, and I'll be very, very glad to get powerful error bridging in Swift.

I don't think it's mentioned anywhere, but are the new protocols in Foundation or Stdlib? I'm hoping they're in Foundation, because I consider localization to be a Foundation-level concern.

I have a number of critiques:

* I think we need the word "localized" on the properties of `LocalizedError`. The fact that they're localized is a very important semantic, and I don't think the fact that they come from a protocol called "Localized" is enough to signal that at use sites. (With "localized" added, `errorDescription` would no longer need the vacuous word "error" to avoid colliding with `CustomStringConvertible`.)

* I'm not sure about including the `helpAnchor` property in `LocalizedError`. It's not even relevant on three of *Apple's* four platforms, let alone on others. Could it be separated?

* I would like to see more work on `RecoverableError`. I know this is a more or less faithful translation of `NSErrorRecoveryAttempting`, but I don't think that's a particularly good API, and I would like to see it revisited.

The design I'd prefer would look more like this:

	protocol RecoverableError: Error {
		var recoveryOptions: [ErrorRecoveryOption] { get }
	}
	
	typealias ErrorRecoveryCompletionHandler = (recovered: Bool) -> Void
	
	protocol ErrorRecoveryOption {
		var localizedName: String { get }
		func attemptRecovery(completion: ErrorRecoveryCompletionHandler) {…}
	}
	
	struct AnyErrorRecoveryOption: ErrorRecoveryOption {
		typealias RecoveryAttempter = (ErrorRecoveryCompletionHandler) -> Void
		
		var localizedName: String
		var attempter: RecoveryAttempter
		
		init(localizedName: String, attempter: RecoveryAttempter) {…}
		
		func attemptRecovery(completion: CompletionHandler) { attempter(completion) }
	}

Though further from the equivalent Foundation API, I think this is a much cleaner design. It requires no `switch` statements, avoids issues with matching indices between the option array and the recovery attempter, and makes it easier for interested subtypes to add or remove recovery options.
		
In particular, in my view, there should be only one way to attempt recovery, and that way should not be application-modal. If a client wants to recover modally, we should invoke the non-modal API and then spin the runloop until the completion handler runs.

If a better `RecoverableError` design isn't feasible in Swift 3, I think we can defer it. In a pinch, `CustomNSError` provides the ability to specify error-handling behavior the old-fashioned way.

* You show an AVError struct with a nested .Code enum. Do you envision people doing similar things for pure-Swift error types? If so, what would that look like, and could it be made more ergonomic? If not, what do you imagine a similarly full-featured error type would look like?

> 	* Is the problem being addressed significant enough to warrant a change to Swift?

Absolutely! NSError provides a remarkably powerful infrastructure, especially on the Mac, and most developers ignore it to their detriment. This stuff ought to be made as easy as possible to implement.

> 	* Does this proposal fit well with the feel and direction of Swift?

Yes. These changes seem very much in line with existing Swift practice.

> 	* If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

N/A.

> 	* How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Quick reading.

-- 
Brent Royal-Gordon
Architechies



More information about the swift-evolution mailing list