Compare commits

...

24 Commits

Author SHA1 Message Date
Carl Meyer
110ae7c7c2 prek 2026-01-12 18:52:31 -08:00
Carl Meyer
7926fb1dc1 Fix dataclass transform function handling after merge
- Fix test expectations in dataclasses.md to match main's expected output
- Restore full dataclass_transform decorated function handling logic that
  was lost during merge - this includes the heuristics to detect whether
  a decorated function is being used as a direct decorator or as a
  decorator factory based on positional arguments and return type

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 18:25:48 -08:00
Carl Meyer
7a10c640c4 cargo fmt 2026-01-12 17:21:10 -08:00
Claude
48c3b5efe6 Remove unused ClassLiteral import
The import is no longer needed after refactoring to use
with_dataclass_params helper method.
2026-01-12 23:47:58 +00:00
Claude
c440f4bc90 Refactor dataclass params to use with_dataclass_params helper
Simplify the code by using the with_dataclass_params method instead
of manually constructing a new ClassLiteral with all parameters.
2026-01-12 23:30:44 +00:00
Claude
f4da2502e5 Merge main into claude/fix-issue-1858-UjARA
- Resolved import conflicts (added GenericAlias from main, kept ClassLiteral and IntersectionType from our branch)
- Added main's new Type::DataclassDecorator with GenericAlias support
- Kept our intersection type test expectations in dataclasses.md
- Added main's new "Dynamic class literals" section
2026-01-12 22:51:42 +00:00
Claude
fa9474f3a8 Layer UnionDiagnostic and IntersectionDiagnostic for nested types
When an intersection fails inside a union, report errors with both
union and intersection context:
- Add LayeredDiagnostic that combines both contexts
- Show the correct intersection type (not the full union)
- Include test with snapshot diagnostics demonstrating the layered output

This addresses review comment 9 from PR #22469.
2026-01-12 22:24:34 +00:00
Claude
fee0888f76 Move retain logic into retain_successful() method
Simplify the call site by moving the is_intersection() and as_result().is_ok()
checks inside retain_successful(). This addresses review comment 8 from PR #22469.
2026-01-12 22:12:57 +00:00
Claude
ac66d4c74c Improve iter()/iter_mut() documentation and add BindingsElement::is_callable()
- Add is_callable() method to BindingsElement for clearer element-level checks
- Update report_diagnostics to iterate over elements instead of flattened bindings
- Add documentation to iter() and iter_mut() clarifying they flatten the structure

This addresses review comments 6 and 7 from PR #22469.
2026-01-12 22:02:30 +00:00
Claude
f0c0c7770c Fix misleading comment about Bindings structure
Update the doc comment to clarify that Bindings represents a union of
callables (possibly size one), where each element is an intersection
(possibly size one). This addresses review comment 5 from PR #22469.
2026-01-12 21:55:13 +00:00
Claude
849e267268 Fix: unify as_result() logic for intersection and single-binding cases
Use error priority to select the appropriate error kind when all bindings
fail, rather than handling intersection and single-binding cases separately.
This addresses review comments 2 and 3 from PR #22469.
2026-01-12 21:47:58 +00:00
Claude
c04fc6b965 Fix: merge argument forms instead of overwriting
When multiple bindings in an intersection (or multiple elements in a union)
return argument forms from type checking (e.g., during argument type expansion),
we should merge them to properly detect conflicting forms, rather than
overwriting with the last one.
2026-01-12 21:06:24 +00:00
Carl Meyer
feb4df1449 review tweaks 2026-01-09 14:29:48 -08:00
Carl Meyer
d9b22cf276 fix up 3.12/3.13 testing 2026-01-09 13:36:10 -08:00
Carl Meyer
fafd6e20dc cargo fmt 2026-01-09 13:17:38 -08:00
Claude
01b1937065 Fix invalid-await for intersections containing dynamic types
This PR fixes false `invalid-await` errors for patterns like:
```python
if inspect.isawaitable(x):
    await x  # x has type Unknown & Awaitable[object]
```

Changes:
1. Add intersection handling to `generator_return_type()` so that await
   operations on intersection types work correctly. When awaiting an
   intersection, we iterate over positive elements, collect return types
   from awaitable elements, and intersect them together. Non-awaitable
   elements are skipped; only if all elements fail to be awaitable do we
   report an error.

2. Add intersection handling to `try_call_dunder_with_policy()` to call
   dunder methods on each intersection element separately and combine the
   results. This avoids intersecting bound methods (which often collapses
   to Never) and instead intersects the return types.

Added tests for:
- Awaiting `Unknown & Awaitable[object]` returns `Unknown`
- Awaiting intersection of two Coroutine types
- Awaiting intersection with non-awaitable elements skips those elements
- Awaiting intersection where all elements are non-awaitable produces error
2026-01-09 21:04:36 +00:00
Claude
930f13da9f Bump freqtrade expected diagnostics from 600 to 650 2026-01-09 17:48:21 +00:00
Claude
cc1ddc5d72 Merge main into claude/fix-issue-1858-UjARA
Resolves conflicts between the two-level Bindings structure and
main's new Type match cases for property descriptors, dataclass
transformers, and other features.
2026-01-09 15:58:43 +00:00
Claude
bc4798f2ee [ty] Support unions containing intersection elements in call bindings
Refactors the `Bindings` structure to use a two-level representation:
- Outer level: union elements (each can be a single callable or an intersection)
- Inner level: bindings within an intersection element

This enables proper handling of types like `(A & B) | C` when calling,
where `A & B` is an intersection that was narrowed by `callable()`.

Key changes:
- Add `BindingsElement` struct to represent a single union element
  (which may contain multiple bindings for intersections)
- Update `from_union` to preserve intersection structure instead of
  flattening
- Update `from_intersection` to create a single element with multiple
  bindings
- Update `return_type`, `check_types_impl`, and `report_diagnostics`
  to handle the two-level structure
- Add test for union-of-intersections case

The priority hierarchy for intersection call errors is preserved: when
all bindings in an intersection fail, only the highest-priority error
type is reported (BindingError > TopCallable > NotCallable).
2026-01-09 06:35:57 +00:00
Claude
4866f6e2ea [ty] Add priority hierarchy for intersection call errors
When all intersection elements fail a call, we now use a priority
hierarchy to determine which errors to show:

1. NotCallable (lowest) - object has no __call__ method
2. TopCallable - object is a top callable with unknown signature
3. BindingError (highest) - specific errors like invalid-argument-type

Only errors from the highest priority category are shown. This prevents
noise from less-specific errors when more informative errors are available.

For example, if an intersection has one element that fails with
invalid-argument-type and another that's not callable, we only show
the invalid-argument-type error since it's more specific and actionable.
2026-01-09 05:17:21 +00:00
Claude
6b4a0b874c Bump sympy expected diagnostics to 13200
More diagnostics are now emitted due to showing individual errors
when all intersection elements fail a call.
2026-01-09 04:41:36 +00:00
Claude
360f1e9e84 [ty] Show individual errors when all intersection elements fail a call
When calling an intersection type where all callable elements reject
the specific call arguments, we now show an error for each failing
element (similar to how unions work) instead of a single generic
"not callable" error.

This is achieved by:
- Not filtering out failed elements when ALL elements fail
- Returning BindingError instead of NotCallable to trigger individual diagnostics
- Adding IntersectionDiagnostic struct and CompoundDiagnostic trait
- Modifying report_diagnostics to iterate over intersection elements
2026-01-09 04:28:12 +00:00
Claude
b3b1b7ba40 Fix markdown formatting in intersection_types.md 2026-01-09 04:09:09 +00:00
Claude
f39370a6f5 [ty] Support calls to intersection types
Implement proper handling for calling intersection types. Previously,
calling an intersection type would return a `@Todo` type that suppressed
errors but provided no useful type information.

Now, when calling an intersection type:
- We try to call each positive element with the given arguments
- Elements where the call fails (wrong arguments, not callable, etc.)
  are discarded
- If at least one element succeeds, the call is valid
- The return type is the intersection of return types from successful
  elements
- If all elements fail, an appropriate error is reported

This approach means that if an intersection contains both a callable
with a known signature and a `Top[Callable[..., object]]` (from
narrowing by `callable()`), the call will succeed using the element
with the known signature, avoiding spurious `call-top-callable` errors.

Fixes https://github.com/astral-sh/ty/issues/1858
2026-01-09 04:00:02 +00:00
10 changed files with 2041 additions and 1191 deletions

View File

@@ -151,7 +151,7 @@ static FREQTRADE: Benchmark = Benchmark::new(
max_dep_date: "2025-06-17",
python_version: PythonVersion::PY312,
},
600,
650,
);
static PANDAS: Benchmark = Benchmark::new(

View File

@@ -129,3 +129,96 @@ async def f():
reveal_type(f()) # revealed: CoroutineType[Any, Any, Unknown]
```
## Awaiting intersection types (3.13+)
```toml
[environment]
python-version = "3.13"
```
Intersection types can be awaited when their elements are awaitable. This is important for patterns
like `inspect.isawaitable()` which narrow types to intersections with `Awaitable`.
```py
import inspect
def get_unknown():
pass
async def test():
x = get_unknown()
if inspect.isawaitable(x):
reveal_type(x) # revealed: Unknown & Awaitable[object]
y = await x
reveal_type(y) # revealed: Unknown
```
The return type of awaiting an intersection is the intersection of the return types of awaiting each
element:
```py
from typing import Coroutine
from ty_extensions import Intersection
class A: ...
class B: ...
async def test(x: Intersection[Coroutine[object, object, A], Coroutine[object, object, B]]):
y = await x
reveal_type(y) # revealed: A & B
```
If some intersection elements are not awaitable, we skip them and use the return types from the
awaitable elements:
```py
from typing import Coroutine
from ty_extensions import Intersection
class NotAwaitable:
pass
async def test(x: Intersection[Coroutine[object, object, str], NotAwaitable]):
y = await x
reveal_type(y) # revealed: str
```
If all intersection elements fail to be awaitable, the await is invalid:
```py
from ty_extensions import Intersection
class NotAwaitable1:
pass
class NotAwaitable2:
pass
async def test(x: Intersection[NotAwaitable1, NotAwaitable2]):
# error: [invalid-await]
await x
```
## Awaiting intersection types (Python 3.12 or lower)
```toml
[environment]
python-version = "3.12"
```
The return type of awaiting an intersection is the intersection of the return types of awaiting each
element:
```py
from typing import Coroutine
from ty_extensions import Intersection
class A: ...
class B: ...
async def test(x: Intersection[Coroutine[object, object, A], Coroutine[object, object, B]]):
y = await x
# TODO: should be `A & B`, but suffers from https://github.com/astral-sh/ty/issues/2426
reveal_type(y) # revealed: A
```

View File

@@ -834,3 +834,34 @@ def _(flag: bool):
# error: [invalid-argument-type] "Argument to function `f` is incorrect: Expected `T`, found `dict[str, int] & dict[Unknown | str, Unknown | int]`"
f({"y": 1})
```
## Union of intersections with failing bindings
<!-- snapshot-diagnostics -->
When calling a union where one element is an intersection of callables, and all bindings in that
intersection fail, we should report errors with both union and intersection context.
```py
from ty_extensions import Intersection
from typing import Callable
class IntCaller:
def __call__(self, x: int) -> int:
return x
class StrCaller:
def __call__(self, x: str) -> str:
return x
class BytesCaller:
def __call__(self, x: bytes) -> bytes:
return x
def test(f: Intersection[IntCaller, StrCaller] | BytesCaller):
# Call with None - should fail for IntCaller, StrCaller, and BytesCaller
# error: [invalid-argument-type]
# error: [invalid-argument-type]
# error: [invalid-argument-type]
f(None)
```

View File

@@ -946,6 +946,194 @@ def mixed(
reveal_type(i4) # revealed: Any
```
## Calling intersection types
When calling an intersection type, we try to call each positive element with the given arguments.
Elements where the call fails (wrong arguments, not callable, etc.) are discarded. The return type
is the intersection of return types from the elements where the call succeeded.
```py
from ty_extensions import Intersection
from typing import Callable
class Foo:
pass
def _(
x: Intersection[type[Foo], Callable[[], str]],
) -> None:
# Both `type[Foo]` and `Callable[[], str]` are callable with no arguments.
# `type[Foo]()` returns `Foo`, `Callable[[], str]()` returns `str`.
# The return type is the intersection of `Foo` and `str`.
reveal_type(x()) # revealed: Foo & str
```
If one element accepts the call but another rejects it (e.g., due to incompatible arguments), the
call still succeeds using only the element that accepts:
```py
from ty_extensions import Intersection
from typing import Callable
class Bar:
pass
def _(
x: Intersection[type[Bar], Callable[[int], str]],
) -> None:
# `type[Bar]()` accepts no arguments and returns `Bar`.
# `Callable[[int], str]` requires an int argument, so it fails for this call.
# We discard the failing element and use only `type[Bar]`.
reveal_type(x()) # revealed: Bar
```
If all elements are callable but all reject the specific call (e.g., incompatible arguments), we
show errors for each failing element:
```py
from ty_extensions import Intersection
from typing import Callable
def _(
x: Intersection[Callable[[int], str], Callable[[str], int]],
) -> None:
# Both callables reject a `float` argument:
# - `Callable[[int], str]` expects `int`
# - `Callable[[str], int]` expects `str`
# error: [invalid-argument-type]
# error: [invalid-argument-type]
x(1.0)
```
When intersection elements fail with different error types, we use a priority hierarchy to determine
which errors to show. More specific errors (like `invalid-argument-type`) take precedence over less
specific ones (like `call-top-callable` or `call-non-callable`).
A specific argument error takes priority over a top-callable error:
```py
from ty_extensions import Intersection, Top
from typing import Callable
def _(
x: Intersection[Callable[[int], str], Top[Callable[..., object]]],
) -> None:
# `Callable[[int], str]` fails with invalid-argument-type (expects int, got str)
# `Top[Callable[..., object]]` would fail with call-top-callable
# We only show the more specific invalid-argument-type error
# error: [invalid-argument-type]
x("hello")
```
A specific argument error takes priority over a not-callable error:
```py
from ty_extensions import Intersection
from typing import Callable
class NotCallable: ...
def _(
x: Intersection[Callable[[int], str], NotCallable],
) -> None:
# `Callable[[int], str]` fails with invalid-argument-type (expects int, got str)
# `NotCallable` would fail with call-non-callable
# We only show the more specific invalid-argument-type error
# error: [invalid-argument-type]
x("hello")
```
A top-callable error takes priority over a not-callable error:
```py
from ty_extensions import Intersection, Top
from typing import Callable
class NotCallable: ...
def _(
x: Intersection[Top[Callable[..., object]], NotCallable],
) -> None:
# `Top[Callable[..., object]]` fails with call-top-callable
# `NotCallable` would fail with call-non-callable
# We only show the call-top-callable error (it's more specific)
# error: [call-top-callable]
x()
```
If no positive element is callable, the intersection is not callable:
```py
from ty_extensions import Intersection
class A: ...
class B: ...
def _(x: Intersection[A, B]) -> None:
# error: [call-non-callable] "Object of type `A & B` is not callable"
reveal_type(x()) # revealed: Unknown
```
## Unions containing intersections
When a union contains intersection elements (e.g., from `callable()` narrowing), the type checker
properly handles each union element. If an intersection element succeeds, it contributes to the
result. If all elements within an intersection fail, the priority hierarchy is used for diagnostics:
```py
from ty_extensions import Intersection, Top
from typing import Callable
def _(
i: Intersection[Callable[[int], str], Top[Callable[..., object]]],
c: Callable[[str], int],
flag: bool,
) -> None:
# Create a union of an intersection and a regular callable:
# (Callable[[int], str] & Top[...]) | Callable[[str], int]
if flag:
f = i
else:
f = c
# When called with a string argument:
# - The intersection element: Callable[[int], str] fails (wrong type),
# Top[...] would fail with call-top-callable. Due to priority hierarchy,
# only the invalid-argument-type error is shown for the intersection.
# - The Callable[[str], int] element succeeds.
# The return type includes both elements' return types:
# - intersection: str (from Callable[[int], str])
# - regular: int (from Callable[[str], int])
# error: [invalid-argument-type]
reveal_type(f("hello")) # revealed: str | int
```
When all union elements fail (including intersection elements), errors are reported for each:
```py
from ty_extensions import Intersection, Top
from typing import Callable
def _(
i: Intersection[Callable[[int], str], Top[Callable[..., object]]],
c: Callable[[str], int],
flag: bool,
) -> None:
if flag:
f = i
else:
f = c
# When called with no arguments:
# - The intersection element: Callable[[int], str] fails (missing argument),
# Top[...] would fail with call-top-callable. Due to priority hierarchy,
# only the missing-argument error is shown.
# - The Callable[[str], int] also fails (missing argument).
# error: [missing-argument]
# error: [missing-argument]
f()
```
## Invalid
```py

View File

@@ -0,0 +1,111 @@
---
source: crates/ty_test/src/lib.rs
assertion_line: 623
expression: snapshot
---
---
mdtest name: union.md - Unions in calls - Union of intersections with failing bindings
mdtest path: crates/ty_python_semantic/resources/mdtest/call/union.md
---
# Python source files
## mdtest_snippet.py
```
1 | from ty_extensions import Intersection
2 | from typing import Callable
3 |
4 | class IntCaller:
5 | def __call__(self, x: int) -> int:
6 | return x
7 |
8 | class StrCaller:
9 | def __call__(self, x: str) -> str:
10 | return x
11 |
12 | class BytesCaller:
13 | def __call__(self, x: bytes) -> bytes:
14 | return x
15 |
16 | def test(f: Intersection[IntCaller, StrCaller] | BytesCaller):
17 | # Call with None - should fail for IntCaller, StrCaller, and BytesCaller
18 | # error: [invalid-argument-type]
19 | # error: [invalid-argument-type]
20 | # error: [invalid-argument-type]
21 | f(None)
```
# Diagnostics
```
error[invalid-argument-type]: Argument to bound method `__call__` is incorrect
--> src/mdtest_snippet.py:21:7
|
19 | # error: [invalid-argument-type]
20 | # error: [invalid-argument-type]
21 | f(None)
| ^^^^ Expected `int`, found `None`
|
info: Method defined here
--> src/mdtest_snippet.py:5:9
|
4 | class IntCaller:
5 | def __call__(self, x: int) -> int:
| ^^^^^^^^ ------ Parameter declared here
6 | return x
|
info: Intersection element `IntCaller` is incompatible with this call site
info: Attempted to call intersection type `IntCaller & StrCaller`
info: Attempted to call union type `(IntCaller & StrCaller) | BytesCaller`
info: rule `invalid-argument-type` is enabled by default
```
```
error[invalid-argument-type]: Argument to bound method `__call__` is incorrect
--> src/mdtest_snippet.py:21:7
|
19 | # error: [invalid-argument-type]
20 | # error: [invalid-argument-type]
21 | f(None)
| ^^^^ Expected `str`, found `None`
|
info: Method defined here
--> src/mdtest_snippet.py:9:9
|
8 | class StrCaller:
9 | def __call__(self, x: str) -> str:
| ^^^^^^^^ ------ Parameter declared here
10 | return x
|
info: Intersection element `StrCaller` is incompatible with this call site
info: Attempted to call intersection type `IntCaller & StrCaller`
info: Attempted to call union type `(IntCaller & StrCaller) | BytesCaller`
info: rule `invalid-argument-type` is enabled by default
```
```
error[invalid-argument-type]: Argument to bound method `__call__` is incorrect
--> src/mdtest_snippet.py:21:7
|
19 | # error: [invalid-argument-type]
20 | # error: [invalid-argument-type]
21 | f(None)
| ^^^^ Expected `bytes`, found `None`
|
info: Method defined here
--> src/mdtest_snippet.py:13:9
|
12 | class BytesCaller:
13 | def __call__(self, x: bytes) -> bytes:
| ^^^^^^^^ -------- Parameter declared here
14 | return x
|
info: Union variant `BytesCaller` is incompatible with this call site
info: Attempted to call union type `(IntCaller & StrCaller) | BytesCaller`
info: rule `invalid-argument-type` is enabled by default
```

View File

@@ -4517,8 +4517,17 @@ impl<'db> Type<'db> {
.map(|element| element.bindings(db)),
),
Type::Intersection(_) => {
Binding::single(self, Signature::todo("Type::Intersection.call")).into()
Type::Intersection(intersection) => {
// For intersections, we try to call each positive element.
// Elements where the call fails are discarded.
// The return type is the intersection of return types from successful calls.
Bindings::from_intersection(
db,
self,
intersection
.positive_elements_or_object(db)
.map(|element| element.bindings(db)),
)
}
Type::DataclassDecorator(_) => {
@@ -4630,6 +4639,36 @@ impl<'db> Type<'db> {
tcx: TypeContext<'db>,
policy: MemberLookupPolicy,
) -> Result<Bindings<'db>, CallDunderError<'db>> {
// For intersection types, call the dunder on each element separately and combine
// the results. This avoids intersecting bound methods (which often collapses to Never)
// and instead intersects the return types. TODO we might be able to remove this after
// fixing https://github.com/astral-sh/ty/issues/2428.
if let Type::Intersection(intersection) = self {
let mut successful_bindings = Vec::new();
let mut last_error = None;
for element in intersection.positive(db) {
match element.try_call_dunder_with_policy(
db,
name,
&mut argument_types.clone(),
tcx,
policy,
) {
Ok(bindings) => successful_bindings.push(bindings),
Err(err) => last_error = Some(err),
}
}
if successful_bindings.is_empty() {
// TODO we are only showing one of the errors here; should we aggregate them
// somehow or show all of them?
return Err(last_error.unwrap_or(CallDunderError::MethodNotAvailable));
}
return Ok(Bindings::from_intersection(db, self, successful_bindings));
}
// Implicit calls to dunder methods never access instance members, so we pass
// `NO_INSTANCE_FALLBACK` here in addition to other policies:
match self
@@ -5123,6 +5162,17 @@ impl<'db> Type<'db> {
}
}
Type::Union(union) => union.try_map(db, |ty| ty.generator_return_type(db)),
Type::Intersection(intersection) => {
let mut builder = IntersectionBuilder::new(db);
let mut any_success = false;
for ty in intersection.positive(db) {
if let Some(return_ty) = ty.generator_return_type(db) {
builder = builder.add_positive(return_ty);
any_success = true;
}
}
any_success.then(|| builder.build())
}
ty @ (Type::Dynamic(_) | Type::Never) => Some(ty),
_ => None,
}

File diff suppressed because it is too large Load Diff

View File

@@ -3055,7 +3055,7 @@ impl<'db> StaticClassLiteral<'db> {
// the `__set__` method can be called. We build a union of all possible options
// to account for possible overloads.
let mut value_types = UnionBuilder::new(db);
for binding in &dunder_set.bindings(db) {
for binding in dunder_set.bindings(db).iter() {
for overload in binding {
if let Some(value_param) =
overload.signature.parameters().get_positional(2)

View File

@@ -517,11 +517,11 @@ pub fn call_signature_details<'db>(
// Extract signature details from all callable bindings
bindings
.into_iter()
.flatten()
.iter()
.flat_map(IntoIterator::into_iter)
.map(|binding| {
let argument_to_parameter_mapping = binding.argument_matches().to_vec();
let signature = binding.signature;
let signature = binding.signature.clone();
let display_details = signature.display(model.db()).to_string_parts();
let parameter_label_offsets = display_details.parameter_ranges;
let parameter_names = display_details.parameter_names;
@@ -591,7 +591,7 @@ pub fn call_type_simplified_by_overloads(
.check_types(db, &args, TypeContext::default(), &[])
// Only use the Ok
.iter()
.flatten()
.flat_map(super::call::bind::Bindings::iter)
.flat_map(|binding| {
binding.matching_overloads().map(|(_, overload)| {
overload
@@ -625,8 +625,8 @@ pub fn definitions_for_bin_op<'db>(
let callable_type = promote_literals_for_self(model.db(), bindings.callable_type());
let definitions: Vec<_> = bindings
.into_iter()
.flatten()
.iter()
.flat_map(IntoIterator::into_iter)
.filter_map(|binding| {
Some(ResolvedDefinition::Definition(
binding.signature.definition?,
@@ -683,8 +683,8 @@ pub fn definitions_for_unary_op<'db>(
let callable_type = promote_literals_for_self(model.db(), bindings.callable_type());
let definitions = bindings
.into_iter()
.flatten()
.iter()
.flat_map(IntoIterator::into_iter)
.filter_map(|binding| {
Some(ResolvedDefinition::Definition(
binding.signature.definition?,

View File

@@ -9477,7 +9477,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
}
};
for binding in &mut bindings {
for binding in bindings.iter_mut() {
let binding_type = binding.callable_type;
for (_, overload) in binding.matching_overloads_mut() {
match binding_type {