[swift-evolution] Proposals: (1) Forbidding custom `==` for value types, (2) `dispatch` keyword, (3) `default`-result for methods with `Self`, and (4) Poor-Mans-Existentials

Johannes Neubauer neubauer at kingsware.de
Sat Jul 16 08:18:42 CDT 2016


Dear Saagar,

> Am 15.07.2016 um 19:05 schrieb Saagar Jha <saagarjha28 at gmail.com>:
> 
> Equatable, where the == operator is defined, will not let you compare two things of a different type. 

This is not true for reference types. Consider the following **bad** (but compiling code):

```swift
class A: Equatable {}

class Aa: A {
    let a: Int
    
    init(a: Int) {
        self.a = a
    }
}

func ==(lhs: A, rhs: A) -> Bool {
    return lhs === rhs
}

func ==(lhs: Aa, rhs: Aa) -> Bool {
    return lhs.a == rhs.a
}
```

Now let us use this:

```swift
let a = A()
let a2 = A()
let aa = Aa(a: 0)
let aa2 = Aa(a: 1)
let aa3 = Aa(a: 1)

// prints `true`
print(a == a)

// prints `false`
print(a == a2)

// prints `false`
print(a == aa)

// prints `false`
print(a == aa3)

// prints `false`
print(aa == aa2)

// prints `true` because it compares the `a: Int` values.
print(aa2 == aa3)

// now mixed-type comparison (returns `false`)
print(a == aa2)
```

Hence, you can do mixed-type equality checks in Swift. Even worse is, you can do this:

```swift
let aa2AsA: A = aa2,
    aa3AsA: A = aa3

// prints `true` because it compares the `a: Int` values.
print(aa2 == aa3)

// prints `false`, because the equals method of `A` is used
print(aa2AsA == aa3AsA)
```

Just by assigning an object to a variable that is typed differently the result is completely different. This is because method parameters are dispatched statically. This is fast, but results in really unintended results, you can do a **lot** of things breaking the contract of `==` with that. This is why I wanted to add a `default` clause (in *3.* of my original proposal) for such methods involving two references to `Self`. Further on, I wanted to add the keyword `dispatch` for method (and operator) parameters, where dispatching is necessary (see *2.* of my original proposal).

I think these changes are crucial for the safety of the language. Now you can write really bad code and the compiler/IDE doesn’t help you. You may do the dynamic dispatch manually, but this is error-prone (and many developers aren’t even aware of the issue).

All the best
Johannes


More information about the swift-evolution mailing list