Skip to content

Commit 7640a14

Browse files
committed
[red-knot] add call signature checking
1 parent 8a98d88 commit 7640a14

File tree

12 files changed

+1105
-226
lines changed

12 files changed

+1105
-226
lines changed

crates/red_knot_python_semantic/resources/mdtest/assignment/augmented.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ class C:
4040
return 42
4141

4242
x = C()
43+
# error: [invalid-argument-type]
4344
x -= 1
4445

45-
# TODO: should error, once operand type check is implemented
4646
reveal_type(x) # revealed: int
4747
```
4848

crates/red_knot_python_semantic/resources/mdtest/call/function.md

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,186 @@ def _(flag: bool):
6464
# error: [possibly-unresolved-reference]
6565
reveal_type(foo()) # revealed: int
6666
```
67+
68+
## Wrong argument type
69+
70+
### Positional argument, positional-or-keyword parameter
71+
72+
```py
73+
def f(x: int) -> int:
74+
return 1
75+
76+
# error: 15 [invalid-argument-type] "Cannot assign type `Literal["foo"]` to parameter `x` of type `int`"
77+
reveal_type(f("foo")) # revealed: int
78+
```
79+
80+
### Positional argument, positional-only parameter
81+
82+
```py
83+
def f(x: int, /) -> int:
84+
return 1
85+
86+
# error: 15 [invalid-argument-type] "Cannot assign type `Literal["foo"]` to parameter `x` of type `int`"
87+
reveal_type(f("foo")) # revealed: int
88+
```
89+
90+
### Positional argument, variadic parameter
91+
92+
```py
93+
def f(*args: int) -> int:
94+
return 1
95+
96+
# error: 15 [invalid-argument-type] "Cannot assign type `Literal["foo"]` to parameter `args` of type `int`"
97+
reveal_type(f("foo")) # revealed: int
98+
```
99+
100+
### Keyword argument, positional-or-keyword parameter
101+
102+
```py
103+
def f(x: int) -> int:
104+
return 1
105+
106+
# error: 15 [invalid-argument-type] "Cannot assign type `Literal["foo"]` to parameter `x` of type `int`"
107+
reveal_type(f(x="foo")) # revealed: int
108+
```
109+
110+
### Keyword argument, keyword-only parameter
111+
112+
```py
113+
def f(*, x: int) -> int:
114+
return 1
115+
116+
# error: 15 [invalid-argument-type] "Cannot assign type `Literal["foo"]` to parameter `x` of type `int`"
117+
reveal_type(f(x="foo")) # revealed: int
118+
```
119+
120+
### Keyword argument, keywords parameter
121+
122+
```py
123+
def f(**kwargs: int) -> int:
124+
return 1
125+
126+
# error: 15 [invalid-argument-type] "Cannot assign type `Literal["foo"]` to parameter `kwargs` of type `int`"
127+
reveal_type(f(x="foo")) # revealed: int
128+
```
129+
130+
### Correctly match keyword out-of-order
131+
132+
```py
133+
def f(x: int = 1, y: str = "foo") -> int:
134+
return 1
135+
136+
# error: 15 [invalid-argument-type] "Cannot assign type `Literal[2]` to parameter `y` of type `str`"
137+
# error: 20 [invalid-argument-type] "Cannot assign type `Literal["bar"]` to parameter `x` of type `int`"
138+
reveal_type(f(y=2, x="bar")) # revealed: int
139+
```
140+
141+
## Too many positional arguments
142+
143+
### One too many
144+
145+
```py
146+
def f() -> int:
147+
return 1
148+
149+
# error: 15 [too-many-positional-arguments] "Too many positional arguments: expected 0, got 1"
150+
reveal_type(f("foo")) # revealed: int
151+
```
152+
153+
### Two too many
154+
155+
```py
156+
def f() -> int:
157+
return 1
158+
159+
# error: 15 [too-many-positional-arguments] "Too many positional arguments: expected 0, got 2"
160+
reveal_type(f("foo", "bar")) # revealed: int
161+
```
162+
163+
### No too-many-positional if variadic is taken
164+
165+
```py
166+
def f(*args: int) -> int:
167+
return 1
168+
169+
reveal_type(f(1, 2, 3)) # revealed: int
170+
```
171+
172+
## Missing arguments
173+
174+
### No defaults or variadic
175+
176+
```py
177+
def f(x: int) -> int:
178+
return 1
179+
180+
# error: 13 [missing-argument] "No argument provided for required parameter `x`"
181+
reveal_type(f()) # revealed: int
182+
```
183+
184+
### With default
185+
186+
```py
187+
def f(x: int, y: str = "foo") -> int:
188+
return 1
189+
190+
# error: 13 [missing-argument] "No argument provided for required parameter `x`"
191+
reveal_type(f()) # revealed: int
192+
```
193+
194+
### Defaulted argument is not required
195+
196+
```py
197+
def f(x: int = 1) -> int:
198+
return 1
199+
200+
reveal_type(f()) # revealed: int
201+
```
202+
203+
### With variadic
204+
205+
```py
206+
def f(x: int, *y: str) -> int:
207+
return 1
208+
209+
# error: 13 [missing-argument] "No argument provided for required parameter `x`"
210+
reveal_type(f()) # revealed: int
211+
```
212+
213+
### Variadic argument is not required
214+
215+
```py
216+
def f(*args: int) -> int:
217+
return 1
218+
219+
reveal_type(f()) # revealed: int
220+
```
221+
222+
### Keywords argument is not required
223+
224+
```py
225+
def f(**kwargs: int) -> int:
226+
return 1
227+
228+
reveal_type(f()) # revealed: int
229+
```
230+
231+
## Unknown argument
232+
233+
```py
234+
def f(x: int) -> int:
235+
return 1
236+
237+
# error: 20 [unknown-argument] "Argument `y` does not match any known parameter"
238+
reveal_type(f(x=1, y=2)) # revealed: int
239+
```
240+
241+
## Parameter already assigned
242+
243+
```py
244+
def f(x: int) -> int:
245+
return 1
246+
247+
# error: 18 [parameter-already-assigned] "Parameter `x` is already assigned"
248+
reveal_type(f(1, x=2)) # revealed: int
249+
```

crates/red_knot_python_semantic/resources/mdtest/narrow/isinstance.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,7 @@ def _(flag: bool):
169169
def _(flag: bool):
170170
x = 1 if flag else "a"
171171

172-
# TODO: this should cause us to emit a diagnostic
173-
# (`isinstance` has no `foo` parameter)
172+
# error: [unknown-argument]
174173
if isinstance(x, int, foo="bar"):
175174
reveal_type(x) # revealed: Literal[1] | Literal["a"]
176175
```

crates/red_knot_python_semantic/resources/mdtest/narrow/issubclass.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ class A: ...
146146

147147
t = object()
148148

149-
# TODO: we should emit a diagnostic here
149+
# error: [invalid-argument-type]
150150
if issubclass(t, A):
151151
reveal_type(t) # revealed: type[A]
152152
```
@@ -160,7 +160,7 @@ branch:
160160
```py
161161
t = 1
162162

163-
# TODO: we should emit a diagnostic here
163+
# error: [invalid-argument-type]
164164
if issubclass(t, int):
165165
reveal_type(t) # revealed: Never
166166
```
@@ -234,8 +234,7 @@ def flag() -> bool: ...
234234

235235
t = int if flag() else str
236236

237-
# TODO: this should cause us to emit a diagnostic
238-
# (`issubclass` has no `foo` parameter)
237+
# error: [unknown-argument]
239238
if issubclass(t, int, foo="bar"):
240239
reveal_type(t) # revealed: Literal[int, str]
241240
```

0 commit comments

Comments
 (0)