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

Reply via email to