Skip to content

Commit 46be305

Browse files
[ty] Include synthesized arguments in displayed counts for too-many-positional-arguments (#18098)
## Summary Resolves [#290](astral-sh/ty#290). All arguments, synthesized or not, are now accounted for in `too-many-positional-arguments`'s error message. For example, consider this example: ```python class C: def foo(self): ... C().foo(1) # !!! ``` Previously, ty would say: > Too many positional arguments to bound method foo: expected 0, got 1 After this change, it will say: > Too many positional arguments to bound method foo: expected 1, got 2 This is what Python itself does too: ```text Traceback (most recent call last): File "<python-input-0>", line 3, in <module> C().foo() ~~~~~~~^^ TypeError: C.foo() takes 0 positional arguments but 1 was given ``` ## Test Plan Markdown tests.
1 parent c3a4992 commit 46be305

File tree

3 files changed

+15
-21
lines changed

3 files changed

+15
-21
lines changed

crates/ty_python_semantic/resources/mdtest/call/constructor.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class Foo: ...
4747

4848
reveal_type(Foo()) # revealed: Foo
4949

50-
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 0, got 1"
50+
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 1, got 2"
5151
reveal_type(Foo(1)) # revealed: Foo
5252
```
5353

@@ -62,7 +62,7 @@ reveal_type(Foo(1)) # revealed: Foo
6262

6363
# error: [missing-argument] "No argument provided for required parameter `x` of function `__new__`"
6464
reveal_type(Foo()) # revealed: Foo
65-
# error: [too-many-positional-arguments] "Too many positional arguments to function `__new__`: expected 1, got 2"
65+
# error: [too-many-positional-arguments] "Too many positional arguments to function `__new__`: expected 2, got 3"
6666
reveal_type(Foo(1, 2)) # revealed: Foo
6767
```
6868

@@ -84,7 +84,7 @@ reveal_type(Foo(1)) # revealed: Foo
8484

8585
# error: [missing-argument] "No argument provided for required parameter `x` of function `__new__`"
8686
reveal_type(Foo()) # revealed: Foo
87-
# error: [too-many-positional-arguments] "Too many positional arguments to function `__new__`: expected 1, got 2"
87+
# error: [too-many-positional-arguments] "Too many positional arguments to function `__new__`: expected 2, got 3"
8888
reveal_type(Foo(1, 2)) # revealed: Foo
8989
```
9090

@@ -105,7 +105,7 @@ def _(flag: bool) -> None:
105105
# error: [missing-argument] "No argument provided for required parameter `x` of function `__new__`"
106106
# error: [missing-argument] "No argument provided for required parameter `x` of function `__new__`"
107107
reveal_type(Foo()) # revealed: Foo
108-
# error: [too-many-positional-arguments] "Too many positional arguments to function `__new__`: expected 1, got 2"
108+
# error: [too-many-positional-arguments] "Too many positional arguments to function `__new__`: expected 2, got 3"
109109
reveal_type(Foo(1, 2)) # revealed: Foo
110110
```
111111

@@ -198,7 +198,7 @@ reveal_type(Foo(1)) # revealed: Foo
198198

199199
# error: [missing-argument] "No argument provided for required parameter `x` of bound method `__init__`"
200200
reveal_type(Foo()) # revealed: Foo
201-
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 1, got 2"
201+
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 2, got 3"
202202
reveal_type(Foo(1, 2)) # revealed: Foo
203203
```
204204

@@ -217,7 +217,7 @@ reveal_type(Foo(1)) # revealed: Foo
217217

218218
# error: [missing-argument] "No argument provided for required parameter `x` of bound method `__init__`"
219219
reveal_type(Foo()) # revealed: Foo
220-
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 1, got 2"
220+
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 2, got 3"
221221
reveal_type(Foo(1, 2)) # revealed: Foo
222222
```
223223

@@ -238,7 +238,7 @@ def _(flag: bool) -> None:
238238
# error: [missing-argument] "No argument provided for required parameter `x` of bound method `__init__`"
239239
# error: [missing-argument] "No argument provided for required parameter `x` of bound method `__init__`"
240240
reveal_type(Foo()) # revealed: Foo
241-
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 1, got 2"
241+
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 2, got 3"
242242
reveal_type(Foo(1, 2)) # revealed: Foo
243243
```
244244

@@ -344,7 +344,7 @@ class Foo:
344344
reveal_type(Foo()) # revealed: Foo
345345
reveal_type(Foo(1)) # revealed: Foo
346346

347-
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 1, got 2"
347+
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 2, got 3"
348348
reveal_type(Foo(1, 2)) # revealed: Foo
349349
```
350350

@@ -363,7 +363,7 @@ class Foo:
363363
# error: [missing-argument] "No argument provided for required parameter `x` of bound method `__init__`"
364364
reveal_type(Foo()) # revealed: Foo
365365

366-
# error: [too-many-positional-arguments] "Too many positional arguments to function `__new__`: expected 0, got 1"
366+
# error: [too-many-positional-arguments] "Too many positional arguments to function `__new__`: expected 1, got 2"
367367
reveal_type(Foo(42)) # revealed: Foo
368368

369369
class Foo2:
@@ -376,7 +376,7 @@ class Foo2:
376376
# error: [missing-argument] "No argument provided for required parameter `x` of function `__new__`"
377377
reveal_type(Foo2()) # revealed: Foo2
378378

379-
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 0, got 1"
379+
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 1, got 2"
380380
reveal_type(Foo2(42)) # revealed: Foo2
381381

382382
class Foo3(metaclass=abc.ABCMeta):
@@ -389,7 +389,7 @@ class Foo3(metaclass=abc.ABCMeta):
389389
# error: [missing-argument] "No argument provided for required parameter `x` of bound method `__init__`"
390390
reveal_type(Foo3()) # revealed: Foo3
391391

392-
# error: [too-many-positional-arguments] "Too many positional arguments to function `__new__`: expected 0, got 1"
392+
# error: [too-many-positional-arguments] "Too many positional arguments to function `__new__`: expected 1, got 2"
393393
reveal_type(Foo3(42)) # revealed: Foo3
394394

395395
class Foo4(metaclass=abc.ABCMeta):
@@ -402,7 +402,7 @@ class Foo4(metaclass=abc.ABCMeta):
402402
# error: [missing-argument] "No argument provided for required parameter `x` of function `__new__`"
403403
reveal_type(Foo4()) # revealed: Foo4
404404

405-
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 0, got 1"
405+
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 1, got 2"
406406
reveal_type(Foo4(42)) # revealed: Foo4
407407
```
408408

crates/ty_python_semantic/resources/mdtest/call/subclass_of.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def _(subclass_of_c: type[C]):
2424
reveal_type(subclass_of_c("a")) # revealed: C
2525
# error: [missing-argument] "No argument provided for required parameter `x` of bound method `__init__`"
2626
reveal_type(subclass_of_c()) # revealed: C
27-
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 1, got 2"
27+
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 2, got 3"
2828
reveal_type(subclass_of_c(1, 2)) # revealed: C
2929
```
3030

crates/ty_python_semantic/src/types/call/bind.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,14 +1285,8 @@ impl<'db> Binding<'db> {
12851285
first_excess_argument_index,
12861286
num_synthetic_args,
12871287
),
1288-
expected_positional_count: parameters
1289-
.positional()
1290-
.count()
1291-
// using saturating_sub to avoid negative values due to invalid syntax in source code
1292-
.saturating_sub(num_synthetic_args),
1293-
provided_positional_count: next_positional
1294-
// using saturating_sub to avoid negative values due to invalid syntax in source code
1295-
.saturating_sub(num_synthetic_args),
1288+
expected_positional_count: parameters.positional().count(),
1289+
provided_positional_count: next_positional,
12961290
});
12971291
}
12981292
let mut missing = vec![];

0 commit comments

Comments
 (0)