Skip to content

Commit 1cdc3cf

Browse files
committed
Proposal to conform Never to Equatable and Hashable
1 parent 577b515 commit 1cdc3cf

File tree

1 file changed

+79
-0
lines changed

1 file changed

+79
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Conform `Never` to `Equatable` and `Hashable`
2+
3+
* Proposal: [SE-NNNN](NNNN-filename.md)
4+
* Author: [Matt Diephouse](https://github.com/mdiep)
5+
* Review Manager: TBD
6+
* Status: **Awaiting implementation**
7+
8+
## Introduction
9+
Extend `Never` so it conforms to `Equatable` and `Hashable`.
10+
11+
Swift-evolution thread: [Conform Never to Equatable and Hashable](https://forums.swift.org/t/conform-never-to-equatable-and-hashable/12934)
12+
13+
## Motivation
14+
`Never` is very useful for representing impossible code. Most people are familiar with it as the return type of functions like `fatalError`, but `Never` is also useful when working with generic classes.
15+
16+
For example, a `Result` type might use `Never` for its `Value` to represent something that _always_ errors or use `Never` for its `Error` to represent something that _never_ errors.
17+
18+
Conditional conformances to `Equatable` and `Hashable` are also very useful when working with `enum`s so you can test easily or work with collections.
19+
20+
But those don’t play well together. Without conformance to `Equatable` and `Hashable`, `Never` disqualifies your generic type from being `Equatable` and `Hashable`.
21+
22+
## Proposed solution
23+
The standard library should add `Equatable` and `Hashable` implementations for `Never`:
24+
25+
```swift
26+
extension Never: Equatable {
27+
public static func == (lhs: Never, rhs: Never) -> Bool {
28+
switch (lhs, rhs) {
29+
}
30+
}
31+
}
32+
33+
extension Never: Hashable {
34+
public func hash(into hasher: inout Hasher) {
35+
}
36+
}
37+
```
38+
39+
## Detailed design
40+
The question that most often comes up is how `Never` should implement `Equatable`. How do you compare to `Never` values?
41+
42+
But there are no `Never` values; it’s an uninhabitable type. Thankfully Swift makes this easy. By switching over the left- and right-hand sides, Swift correctly notices that there are no missing `case`s. Since there are no missing `case`s and every `case` returns a `Bool`, the function compiles.
43+
44+
The new `Hashable` design makes its implementation even easier: the function does nothing.
45+
46+
## Source compatibility
47+
Existing applications may have their own versions of these conformances. In this case, Swift will give a redundant conformance error.
48+
49+
## Effect on ABI stability
50+
None.
51+
52+
## Effect on API resilience
53+
None.
54+
55+
## Alternatives considered
56+
### Make `Never` conform to _all_ protocols
57+
As a bottom type, `Never` could conceivably to every protocol automatically. This would have some advantages and might be ideal, but would require a lot more work to determine the design and implement the behavior.
58+
59+
### Don’t include this functionality in the standard library
60+
This creates a significant headache—particularly for library authors. Since redundant conformance would be an error, the community would need to settle on a de facto library to add this conformance.
61+
62+
### Require generic types to add conditional conformances with `Never`
63+
An example `Result` type could manually add `Equatable` and `Hashable` implementations for `Never`s:
64+
65+
```swift
66+
extension Result: Equatable where Value == Never, Error: Equatable {
67+
68+
}
69+
70+
extension Result: Equatable where Value: Hashable, Error == Never {
71+
72+
}
73+
74+
extension Result: Equatable where Value == Never, Error == Never {
75+
76+
}
77+
```
78+
79+
Adding so many extra conditional conformances is an unreasonable amount of work.

0 commit comments

Comments
 (0)