Why doesn't "try? funcReturningOptionalInt()" give "Int?"

Related thread: try? with a function that returns an optional.

Consider the following example:

func foo() throws -> Int? { 1 }

let x = try? foo()
type(of: x)  // returns 'Int?' instead of 'Int??'

Why doesn't try? always give an optional of the return type?

Thank you! I'm honestly a bit sad since this implicit flattening removes information. Without it you would be able to directly check if a function has thrown since Optional(nil) is different from nil. I hope it has been considered during the review phase of SE-0230.

I face the similar problem. Thanks for update and quick reply.

official website

Seems to me like a better solution than try?-flattening everything would have been to add a static unwrap method for opting in.

Because this is also an Int?:

let int = try? .unwrap(foo)

As it is, if we get a proper throwing unwrapping method, this will become easy on you.

do {
  // The necessity for explicit typing here is going away, I think.
  let int = try Int?.unwrap(foo)
} catch let error as Optional<Int>.UnwrapError {
  
} catch {

}
public extension Optional {
  final class UnwrapError: AnyOptional.UnwrapError { }

  static func unwrap(
    _ optional: () throws -> Self
  ) throws -> Wrapped {
    try optional().unwrap()
  }

  /// - Note: Useful for emulating `break`, with `map`, `forEach`, etc.
  /// - Throws: if `nil`.
  func unwrap(
    orThrow error: @autoclosure () -> Error = UnwrapError()
  ) throws -> Wrapped {
    if let wrapped = self {
      return wrapped
    } else {
      throw error()
    }
  }
}

public enum AnyOptional {
  public class UnwrapError: Error {
    public init() { }
  }
}