SE-0230: Flatten nested optionals resulting from `try?`

Question 1:

Are the following statements about the current behavior in Swift (4.2) correct?

  1. try? exprOfTypeT always result in type T?

  2. try! exprOfTypeT always result in type T (or traps)

  3. exprOfTypeU as? T always result in type T?

  4. exprOfTypeU as! T always result in type T (or traps)

(Please note that T and U are any type, which of course includes T and U being eg V? and W?, or X???? and Y??????? for that matter. So if T is V?? then T? is V???.)

Some code that provides details behind the above statements.
let o0: Int = 123
let o1: Int? = 123
let o2: Int?? = 123
let o3: Int??? = 123

func throwingIdentity<T>(_ v: T) throws -> T { return v }

// NOTE 1: try? exprOfTypeT always returns a value of type T?
let tryQ0: Int? = try? throwingIdentity(o0)    // T = Int    -> Int?    = T?
let tryQ1: Int?? = try? throwingIdentity(o1)   // T = Int?   -> Int??   = T?
let tryQ2: Int??? = try? throwingIdentity(o2)  // T = Int??  -> Int???  = T?
let tryQ3: Int???? = try? throwingIdentity(o3) // T = Int??? -> Int???? = T?

// NOTE 2: try! exprOfTypeT always returns a value of type T (or traps)
let tryE0: Int  = try! throwingIdentity(o0)    // T = Int    -> Int     = T
let tryE1: Int?  = try! throwingIdentity(o1)   // T = Int?   -> Int?    = T
let tryE2: Int??  = try! throwingIdentity(o2)  // T = Int??  -> Int??   = T
let tryE3: Int???  = try! throwingIdentity(o3) // T = Int??? -> Int???  = T

// NOTE 3: exprOfTypeU as? T always returns a value of type T?
let asQ0: Int? = o0 as? Int        // U = Int    as? T = Int   ->  Int? = T?
let asQ1: Int? = o1 as? Int        // U = Int?   as? T = Int   ->  Int? = T?
let asQ2: Int? = o2 as? Int        // U = Int??  as? T = Int   ->  Int? = T?
let asQ3: Int? = o3 as? Int        // U = Int??? as? T = Int   ->  Int? = T?

// NOTE 4: exprOfTypeU as! T always returns a value of type T (or traps)
let asE0: Int  = o0 as! Int        // U = Int    as? T = Int   ->  Int? = T?
let asE1: Int  = o1 as! Int        // U = Int?   as? T = Int   ->  Int? = T?
let asE2: Int  = o2 as! Int        // U = Int??  as? T = Int   ->  Int? = T?
let asE3: Int  = o3 as! Int        // U = Int??? as? T = Int   ->  Int? = T?

Question 2:

Will the proposal, if implemented, introduce the context dependent symmetry break reflected by the following modification of the above statements?

  1. try? exprOfTypeT results in type T? unless T is statically known to be some type V?

  2. try! exprOfTypeT always results in type T (or traps)

  3. exprOfTypeU as? T always results in type T?

  4. exprOfTypeU as! T always results in type T (or traps)


Question 3

Can the proposal be described as changing the behavior of try? so that it moves away from
try!, as?, and as!
in order to align more with optional chaining, for which the following statement is correct:

  • exprOfTypeU?.propertyOfTypeT results in type T? unless T is statically known to be some type V?

?

(U must of course be some optional type W? there, or it would not be possible to use optional chaining, but T can be any type, including some optional X? or non-optional Y)