With this discussion thread I would like to discuss one idea about the possible behaviors when using Never
. I'm not a compiler developer and have really limited knowledge so please bear with me.
As for today the compiler is smart enough to undestand a function that returns Never when called will trap (fatalError
), as that function really never returns. It is also able to make enum cases with a single associated value unavailable this way (e.g. Result<_, Never>.failure
).
- Would it be possible to make stored
Never
properties be unavailable as well?
If the user happens to call them, well the application will trap just like with a fatalError
or a computed Never
property.
Since Never
has literally no value and is impossible to be instantiated, we will run into a small issue when we would want to initialize a type with stored Never
properties. To solve this puzzle here's the follow up question:
- Would it be possible to make
Never
parameters be omittable?
Here are a few snippets that shows this in action:
struct S<Result, PartialResult> {
var result: Result
var partialResult: PartialResult
init(result: Result, partialResult: PartialResult) { ⌠}
}
// today
S<Int, Never>(result: 42, partialResult: fatalError())
^~~~~~~~~~~~~ required đ
// new
// `partialResult` can be omitted as it's `Never`
// `result` is initialized with 42, `partialResult` is not initialized
let s = S<Int, Never>(result: 42)
s.result // 42
s.partialResult // traps like `fatalError`
func someFunction(_: Never) { print("swift is great") }
// today
someFunction(fatalError()) // can never be called and it will trap
// new
// `Never` parameter omitted
// prints "swift is great"
someFunction()
enum E<Context> {
case something(value: Int, context: Context)
...
}
// today
let e1 = E<Never>.something(value: 42, context: fatalError()) // will trap
// pattern matching
if case .something(let value, _) = e1 { ... } // not possible, will trap
// new
// successfully instantiates a new value of type `E`
// `context` associated value does not exist
let e2 = E<Never>.something(value: 42)
// pattern matching can be extended as well
// `context` associated value can be omitted
if case .something(let value) = e2 { ... }
Would that be actually possible? I think this could be a very useful feature and it would make strange workaround that use a single value type like Void
fade away and make such structures and functions more ergonomic.