# Strange error in operator overload resolution

**URL:** <https://forums.swift.org/t/strange-error-in-operator-overload-resolution/66583>\
**Category:** Using Swift\
**Tags:** operators, type-inference, overloading\
**Created:** [August 4, 2023, 4:02pm UTC](https://forums.swift.org/t/strange-error-in-operator-overload-resolution/66583 "2023-08-04T16:02:39Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![bbrk24](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bbrk24/32/27370_2.png) [@bbrk24](https://forums.swift.org/u/bbrk24)\
**Post date:** [August 4, 2023, 4:02pm UTC](https://forums.swift.org/t/strange-error-in-operator-overload-resolution/66583/1 "2023-08-04T16:02:39Z")

</div>

Continuing from [Associative arithmetic operation order matters in Swift? - #8 by tera](https://forums.swift.org/t/associative-arithmetic-operation-order-matters-in-swift/66571/8).

The MRE is merely:

```swift
struct Foo {
    static func + (lhs: Foo, rhs: Foo) -> Foo { .init() }
}
struct Bar {
    static func + (lhs: Bar, rhs: Bar) -> Foo { .init() }
}

let a = Bar()
let b = Bar()
let foo: Foo = (a + b) + (a + b)

```

In 5.8, any of the following changes allow it to compile:

- Initializing `foo` out-of-line:

```swift
let foo: Foo
foo = (a + b) + (a + b)

```

- Replacing any of the four operands with `Bar()`, e.g:

```swift
let foo: Foo = (a + Bar()) + (a + b)

```

Curiously, spelling this as `.init()` instead of `Bar()` does not work.
- Adding `as Foo` after the first parenthesized expression:

```swift
let foo = (a + b) as Foo + (a + b)

```

Putting the `as Foo` at the end of the line instead does not fix the problem.

However, as written, the compiler assumes I mean [this overload](https://github.com/apple/swift/blob/bf666d1a79a2a4afcc76908fcfa3a193f530ee69/stdlib/public/core/RangeReplaceableCollection.swift#L1091) of the operator on `RangeReplaceableCollection`, and complains that:

1. The expression as a whole is of type `Bar`, not `Foo`;
2. `Bar` does not conform to that protocol.

Where on earth does it get `RangeReplaceableCollection` collection from, and why does it not see the definition that's right there?

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [August 4, 2023, 5:10pm UTC](https://forums.swift.org/t/strange-error-in-operator-overload-resolution/66583/2 "2023-08-04T17:10:12Z")

</div>

cc @hborla @xedin based on the heterogeneous typing of the `+` overload typing in the correct solution here this smells like it's related to some of the performance heuristics in operator overloading. This should be accepted, right?

> [@bbrk24](#):
>
> Where on earth does it get `RangeReplaceableCollection` collection from

When typechecking fails in the face of an overloaded declaration, the compiler will try to make a best guess about which overload you actually meant to call based on a bunch of heuristics that roughly boil down to "how close were you to calling this overload." Overloads which would require entirely different types are in a very blurry sense more 'distant' than overloads which 'only' require you to declare a conformance.

With a _heavily_ overloaded declaration like `+` this can have very surprising results because the 'closest' match based on heuristics might be an overload that you had no idea about and no intention of ever using. And IME especially in cases where there's a correct overload which the compiler fails to see for some reason, the overload we actually end up diagnosing can appear very surprising.

---

<div class="post-metadata">

**Author:** ![bbrk24](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bbrk24/32/27370_2.png) [@bbrk24](https://forums.swift.org/u/bbrk24)\
**Post date:** [August 4, 2023, 5:29pm UTC](https://forums.swift.org/t/strange-error-in-operator-overload-resolution/66583/3 "2023-08-04T17:29:01Z")

</div>

Interestingly, if I make `Foo` conform to `AdditiveArithmetic` (adding `static let zero` and `static func -`), the errors change, but the solutions/workarounds don't. At the very least the errors cease to be misleading, but they aren't exactly helpful, either:

```swift
main.swift:12:19: error: cannot convert value of type 'Foo' to expected argument type 'Bar'
let foo: Foo = (a + b) + (a + b)
                  ^
main.swift:12:29: error: cannot convert value of type 'Foo' to expected argument type 'Bar'
let foo: Foo = (a + b) + (a + b)
                            ^

```
