[ty] Skip parameter accumulation for object variadics (#24976)

This commit is contained in:
Charlie Marsh
2026-05-02 20:41:55 -04:00
committed by GitHub
parent 5ee1d0cd51
commit e002c44494
2 changed files with 53 additions and 0 deletions
@@ -23,6 +23,49 @@ accepts_only_gradual(1, "one", keyword=object())
accepts_only_gradual(**{1: "one"}) # error: [invalid-argument-type]
```
## Object variadic parameters
`*args: object` and `**kwargs: object` can receive many unrelated argument types. Call binding
should not build large unions to remember the exact values that were supplied to these broad sinks.
```py
class C0: ...
class C1: ...
class C2: ...
class C3: ...
class C4: ...
class C5: ...
class C6: ...
class C7: ...
class C8: ...
class C9: ...
def accepts_objects(*args: object, **kwargs: object) -> None: ...
accepts_objects(
C0(),
C1(),
C2(),
C3(),
C4(),
C5(),
C6(),
C7(),
C8(),
C9(),
k0=C0(),
k1=C1(),
k2=C2(),
k3=C3(),
k4=C4(),
k5=C5(),
k6=C6(),
k7=C7(),
k8=C8(),
k9=C9(),
)
```
## Async
```py
@@ -4898,6 +4898,16 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> {
}
// We still update the actual type of the parameter in this binding to match the argument,
// even if the argument type is not assignable to the expected parameter type.
//
// For a broad variadic sink such as `*args: object` or `**kwargs: object`, preserving a
// union of every individual argument type does not improve call checking or special-case
// return inference. Keep the already-declared top type instead of repeatedly growing a
// large union.
if (parameter.is_variadic() || parameter.is_keyword_variadic()) && expected_ty.is_object() {
self.parameter_tys[parameter_index].get_or_insert(expected_ty);
return;
}
if let Some(builder) = self
.parameter_ty_builders
.get_mut(parameter_index)