Joe also referred to the following model in a thread about Typed Throws. () -> () == () throws Never -> () () throws -> () == () throws Error -> ()
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170213/032267.html It means `Never` must be a subtype of `Error`. I think it is an interesting use case of "Never as bottom type". 2017-05-15 7:27 GMT+09:00 André Videla via swift-evolution <swift-evolution@swift.org>: > Hi Swift-Evolution, > > At the end of SE-0102 > (https://github.com/apple/swift-evolution/blob/master/proposals/0102-noreturn-bottom-type.md) > it is mentioned that the Never type could be used as a universal bottom type > but that is currently not the case. > > As of today the Never type is used as a return type of `fatalError` and as > function which do not return by the virtue of calling `fatalError`. > This allows for very useful behaviours for example: > > let anything: Any = … > > switch anything { > case let view as UIView: … > case let str as String: … > default: fatalError("we got an unexpected type") > } > > But it has its limits, most notably, it cannot be used as an expression > > let dunno: Int = fatalError("what should I put here?") // cannot convert > value of type 'Never' > > It makes sense because Never is not a bottom type. If it were, this > statement would be absolutely valid. > > Having a bottom type and a value for it has several advantages: > > - More informative error messages with forced unwrap: > > protocol WonkyAPI { > func apiCall() -> Int? //this always return an Int, why is it optional? > } > > func mycode() { > let valueFromAPI = apiCall() ?? fatalError("The API used to always > return a value, but now it does not!") > … > } > > It sometimes happen that some part of the code uses an optional but in your > particular codepath, the optional is always containing a value (for example > after an assignment). > As of today, you can write > guard let value = value else { fatalError("something terrible happened") } > for the same effect with a more verbose syntax. > > - Use as a hole/placeholder during development > During development it is very likely that you will want to write a piece of > functionality but be stuck on an intermediate part of the computation. > Assume we have an identifier `undefined` of type `Never` which would > represent an impossible value as a bottom type. We would ben able to write: > > func transform(point: CGPoint) -> CGPoint { > let translation = Matrix3D(1, 0, 2, > 0, 1, -2, > 0, 0, 1) > let rotation: Matrix3D = undefined //what was it? I forgot > return (translation * rotation * point.homogenous).toPoint() > } > > We can debate on the right naming for undefined. Haskell uses 'undefined', > Scala uses `???`. `unimplemented`, `impossible`, `void`are all valid > contenders. > > - Eliminate type annotations for generic covariant types > As of today this is not valid > > struct Person { > let name: String > } > > var maybeSomeone = nil > maybeSomeone = Person(name: "Doug”) > > Even though it is clear that maybeSomeone is of type Optional<Person>. > That is because the compiler cannot guess which type the Optional wraps when > `maybeSomeone` is declared. But with a bottom type, a naked nil can be > mapped to `Optional<Never>` until the type inference figures out from the > context what is the type of Optional. If it cannot because no use or no > assignment is done, the compiler could emit an “unreachable” warning just > like it does for > > func unreach() { > fatalError("stop here") > print("not printed”) // warning: will never be executed > } > > Should I write a proposal? > > André Videla > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution > _______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution