# Single matching overload

<!-- snapshot-diagnostics -->

## Limited number of overloads

`overloaded.pyi`:

```pyi
from typing import overload

@overload
def f() -> None: ...
@overload
def f(x: int) -> int: ...
@overload
def f(x: int, y: int) -> int: ...
```

```py
from overloaded import f

f("a")  # error: [invalid-argument-type]
```

## Bound method overloads preserve original positions

When binding `Base().f`, the first overload is filtered out because its `self` parameter only
accepts `Other`. The remaining overloads keep their original source indexes so diagnostics can point
at the matching declaration and list the original non-matching overloads correctly.

```py
from typing import overload

class Other:
    pass

class Base:
    @overload
    def f(self: Other, x: bytes) -> bytes: ...  # error: [invalid-overload]
    @overload
    def f(self, x: int) -> int: ...
    @overload
    def f(self, x: str, y: int) -> str: ...
    def f(
        self,
        x: bytes | int | str,
        y: int = 0,
    ) -> bytes | int | str:
        return x

Base().f("ok", "bad")  # error: [invalid-argument-type]
```

## Call to function with too many unmatched overloads

This has an excessive number of overloads to the point that ty will cut off the list in the
diagnostic and emit a message stating the number of omitted overloads.

`overloaded.pyi`:

```pyi
from typing import overload

@overload
def foo(a: int): ...
@overload
def foo(a: int, b: int, c: int): ...
@overload
def foo(a: str, b: int, c: int): ...
@overload
def foo(a: int, b: str, c: int): ...
@overload
def foo(a: int, b: int, c: str): ...
@overload
def foo(a: str, b: str, c: int): ...
@overload
def foo(a: int, b: str, c: str): ...
@overload
def foo(a: str, b: str, c: str): ...
@overload
def foo(a: int, b: int, c: int): ...
@overload
def foo(a: float, b: int, c: int): ...
@overload
def foo(a: int, b: float, c: int): ...
@overload
def foo(a: int, b: int, c: float): ...
@overload
def foo(a: float, b: float, c: int): ...
@overload
def foo(a: int, b: float, c: float): ...
@overload
def foo(a: float, b: float, c: float): ...
@overload
def foo(a: str, b: str, c: str): ...
@overload
def foo(a: float, b: str, c: str): ...
@overload
def foo(a: str, b: float, c: str): ...
@overload
def foo(a: str, b: str, c: float): ...
@overload
def foo(a: float, b: float, c: str): ...
@overload
def foo(a: str, b: float, c: float): ...
@overload
def foo(a: float, b: float, c: float): ...
@overload
def foo(a: list[int], b: list[int], c: list[int]): ...
@overload
def foo(a: list[str], b: list[int], c: list[int]): ...
@overload
def foo(a: list[int], b: list[str], c: list[int]): ...
@overload
def foo(a: list[int], b: list[int], c: list[str]): ...
@overload
def foo(a: list[str], b: list[str], c: list[int]): ...
@overload
def foo(a: list[int], b: list[str], c: list[str]): ...
@overload
def foo(a: list[str], b: list[str], c: list[str]): ...
@overload
def foo(a: list[int], b: list[int], c: list[int]): ...
@overload
def foo(a: list[float], b: list[int], c: list[int]): ...
@overload
def foo(a: list[int], b: list[float], c: list[int]): ...
@overload
def foo(a: list[int], b: list[int], c: list[float]): ...
@overload
def foo(a: list[float], b: list[float], c: list[int]): ...
@overload
def foo(a: list[int], b: list[float], c: list[float]): ...
@overload
def foo(a: list[float], b: list[float], c: list[float]): ...
@overload
def foo(a: list[str], b: list[str], c: list[str]): ...
@overload
def foo(a: list[float], b: list[str], c: list[str]): ...
@overload
def foo(a: list[str], b: list[float], c: list[str]): ...
@overload
def foo(a: list[str], b: list[str], c: list[float]): ...
@overload
def foo(a: list[float], b: list[float], c: list[str]): ...
@overload
def foo(a: list[str], b: list[float], c: list[float]): ...
@overload
def foo(a: list[float], b: list[float], c: list[float]): ...
@overload
def foo(a: bool, b: bool, c: bool): ...
@overload
def foo(a: str, b: bool, c: bool): ...
@overload
def foo(a: bool, b: str, c: bool): ...
@overload
def foo(a: bool, b: bool, c: str): ...
@overload
def foo(a: str, b: str, c: bool): ...
@overload
def foo(a: bool, b: str, c: str): ...
@overload
def foo(a: str, b: str, c: str): ...
@overload
def foo(a: int, b: int, c: int): ...
@overload
def foo(a: bool, b: int, c: int): ...
@overload
def foo(a: int, b: bool, c: int): ...
@overload
def foo(a: int, b: int, c: bool): ...
@overload
def foo(a: bool, b: bool, c: int): ...
@overload
def foo(a: int, b: bool, c: bool): ...
@overload
def foo(a: str, b: str, c: str): ...
@overload
def foo(a: float, b: bool, c: bool): ...
@overload
def foo(a: bool, b: float, c: bool): ...
@overload
def foo(a: bool, b: bool, c: float): ...
@overload
def foo(a: float, b: float, c: bool): ...
@overload
def foo(a: bool, b: float, c: float): ...
```

```py
from typing import overload

from overloaded import foo

foo("foo")  # error: [invalid-argument-type]
```
