Swift 2.0b4: Allow `if let` and `guard let` to assign to `self` in failable value type initializers

Originator:rix.rob
Number:rdar://22108400 Date Originated:02-Aug-2015 04:26 PM
Status:Open Resolved:
Product:Developer Tools Product Version:Xcode-beta (7A165t)
Classification:Enhancement Reproducible:Always
 
Summary:
In rdar://problem/22108390, I described allowing `self` to be assigned a value of Optional type in failable value type initializers, automatically returning `nil` if `self` was assigned `nil`.

I personally think that would have better semantics than the semantics of `return` in a failable initializer—it’s inconsistent and confusing that you can return only `nil` but can assign only non-`nil`—but `return` is already established, and assignment to self isn’t a thing for classes anyway, so one might argue that this conflates things unnecessarily.

Therefore I also propose allowing `if let` and `guard let` to assign to `self` in failable value type initializers, which would allow me to replace this:

init?(_ weave: (A -> Location?) -> A -> Location?, _ up: A -> Location?, _ a: A) {
	func into(t1: A) -> Location? {
		return Location(it: t1, down: weave(into), up: up, left: const(nil), right: const(nil))
	}
	guard let location = into(a) else { return nil }
	self = location
}

with the briefer, more idiomatic:

init?(_ weave: (A -> Location?) -> A -> Location?, _ up: A -> Location?, _ a: A) {
	func into(t1: A) -> Location? {
		return Location(it: t1, down: weave(into), up: up, left: const(nil), right: const(nil))
	}
	guard let self = into(a) else { return nil }
}


Steps to Reproduce:
N/A

Expected Results:
N/A

Actual Results:
N/A

Regression:
N/A

Notes:
If you try this today, you get unhelpful error messages:

/Users/rob/Developer/Projects/Manifold/Manifold/Location.swift:64:9: error: pattern matching in a condition requires the 'case' keyword
                guard let self = into(a) else { return nil }
                      ^
                      case 
/Users/rob/Developer/Projects/Manifold/Manifold/Location.swift:64:13: error: binary operator '~=' cannot be applied to operands of type 'Location<A>' and 'Location<A>?'
                guard let self = into(a) else { return nil }
                          ^~~~

Taking its advice and using guard case let self = into(a), you get:

/Users/rob/Developer/Projects/Manifold/Manifold/Location.swift:64:14: warning: 'let' pattern has no effect; sub-pattern didn't bind any variables
                guard case let self = into(a) else { return nil }
                           ^~~~~~~~
                           
/Users/rob/Developer/Projects/Manifold/Manifold/Location.swift:64:18: error: binary operator '~=' cannot be applied to operands of type 'Location<A>' and 'Location<A>?'
                guard case let self = into(a) else { return nil }
                               ^~~~

So you have to bind a pointless temporary either way.

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!