Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
8d7a211
Add CallBinding::into_outcome
dcreager Mar 7, 2025
5221ffd
Add separate bindings for each overload
dcreager Mar 8, 2025
4329cac
Report diagnostics for all overloads
dcreager Mar 8, 2025
184154f
Add overloads of signatures
dcreager Mar 8, 2025
f85734d
Use overloads for decorator method special cases
dcreager Mar 8, 2025
257b506
Include overload number in diagnostics
dcreager Mar 8, 2025
1fb02d5
Use bind_call for intersection types TODO
dcreager Mar 8, 2025
9cbcdd3
Use bind_call for bool()
dcreager Mar 8, 2025
cb2f10c
Use bind_call for str()
dcreager Mar 8, 2025
7b129d8
Use bind_call for type()
dcreager Mar 8, 2025
61df852
Use bind_call for all class instantiations
dcreager Mar 8, 2025
2a8f8a8
clippy
dcreager Mar 8, 2025
48b2b56
Add todo comment about short-circuiting binding
dcreager Mar 8, 2025
99644d6
Merge branch 'main' into dcreager/overloads
dcreager Mar 8, 2025
0e28bd9
Fix merge conflicts
dcreager Mar 8, 2025
8f67fda
Use bind_call for dynamic callables
dcreager Mar 8, 2025
42188cd
Clean up this match
dcreager Mar 8, 2025
3aaf910
Merge branch 'main' into dcreager/overloads
dcreager Mar 10, 2025
045ff63
Fix merge conflicts
dcreager Mar 10, 2025
7ebda2b
Use Name::new_static
dcreager Mar 10, 2025
eaa8832
Document Overloads::from_overloads precondition
dcreager Mar 10, 2025
d0d5029
Add snapshot test for overload call binding errors
dcreager Mar 10, 2025
cebd1ee
Single diagnostic for calls to overloaded function
dcreager Mar 10, 2025
1447cb3
Update lint schema
dcreager Mar 10, 2025
b63286e
typo
dcreager Mar 10, 2025
ea088e4
Move overload diagnostic check into separate file
dcreager Mar 11, 2025
5cd1eba
Add TODOs about real overload algorithm
dcreager Mar 11, 2025
a75c724
Simpler `has_binding_errors`
dcreager Mar 11, 2025
0315a04
Return Type::Unknown for invalid overload call return type
dcreager Mar 11, 2025
d7fa0d1
Remove extra parameter accessors
dcreager Mar 11, 2025
0b3caa2
Use nullary salsa queries as LazyLock alternative
dcreager Mar 11, 2025
5937f24
Add TODO about merging decorator cases
dcreager Mar 11, 2025
fdc67f9
Rename `Overloads` and `Signature`
dcreager Mar 11, 2025
dd17521
Merge branch 'main' into dcreager/overloads
dcreager Mar 11, 2025
e04f15c
Fix merge conflicts
dcreager Mar 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
class NotBool:
__bool__ = None

# TODO: We should emit an `invalid-argument` error here for `2` because `bool` only takes one argument.
# error: [too-many-positional-arguments] "Too many positional arguments to class `bool`: expected 1, got 2"
bool(1, 2)

# TODO: We should emit an `unsupported-bool-conversion` error here because the argument doesn't implement `__bool__` correctly.
Expand All @@ -29,9 +29,12 @@ But a three-argument call to type creates a dynamic instance of the `type` class
reveal_type(type("Foo", (), {})) # revealed: type
```

Other numbers of arguments are invalid (TODO -- these should emit a diagnostic)
Other numbers of arguments are invalid

```py
# error: [no-matching-overload] "No overload of class `type` matches arguments"
type("Foo", ())

# error: [no-matching-overload] "No overload of class `type` matches arguments"
type("Foo", (), {}, weird_other_arg=42)
```
10 changes: 5 additions & 5 deletions crates/red_knot_python_semantic/resources/mdtest/call/methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,23 +235,23 @@ method_wrapper(C(), None)
method_wrapper(None, C)

# Passing `None` without an `owner` argument is an
# error: [missing-argument] "No argument provided for required parameter `owner`"
# error: [no-matching-overload] "No overload of method wrapper `__get__` of function `f` matches arguments"
method_wrapper(None)

# Passing something that is not assignable to `type` as the `owner` argument is an
# error: [invalid-argument-type] "Object of type `Literal[1]` cannot be assigned to parameter 2 (`owner`) of method wrapper `__get__` of function `f`; expected type `type`"
# error: [no-matching-overload] "No overload of method wrapper `__get__` of function `f` matches arguments"
method_wrapper(None, 1)

# Passing `None` as the `owner` argument when `instance` is `None` is an
# error: [invalid-argument-type] "Object of type `None` cannot be assigned to parameter 2 (`owner`) of method wrapper `__get__` of function `f`; expected type `type`"
# error: [no-matching-overload] "No overload of method wrapper `__get__` of function `f` matches arguments"
method_wrapper(None, None)

# Calling `__get__` without any arguments is an
# error: [missing-argument] "No argument provided for required parameter `instance`"
# error: [no-matching-overload] "No overload of method wrapper `__get__` of function `f` matches arguments"
method_wrapper()

# Calling `__get__` with too many positional arguments is an
# error: [too-many-positional-arguments] "Too many positional arguments to method wrapper `__get__` of function `f`: expected 2, got 3"
# error: [no-matching-overload] "No overload of method wrapper `__get__` of function `f` matches arguments"
method_wrapper(C(), C, "one too many")
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -710,30 +710,30 @@ Finally, we test some error cases for the call to the wrapper descriptor:

```py
# Calling the wrapper descriptor without any arguments is an
# error: [missing-argument] "No arguments provided for required parameters `self`, `instance`"
# error: [no-matching-overload] "No overload of wrapper descriptor `FunctionType.__get__` matches arguments"
wrapper_descriptor()

# Calling it without the `instance` argument is an also an
# error: [missing-argument] "No argument provided for required parameter `instance`"
# error: [no-matching-overload] "No overload of wrapper descriptor `FunctionType.__get__` matches arguments"
wrapper_descriptor(f)

# Calling it without the `owner` argument if `instance` is not `None` is an
# error: [missing-argument] "No argument provided for required parameter `owner`"
# error: [no-matching-overload] "No overload of wrapper descriptor `FunctionType.__get__` matches arguments"
wrapper_descriptor(f, None)

# But calling it with an instance is fine (in this case, the `owner` argument is optional):
wrapper_descriptor(f, C())

# Calling it with something that is not a `FunctionType` as the first argument is an
# error: [invalid-argument-type] "Object of type `Literal[1]` cannot be assigned to parameter 1 (`self`) of wrapper descriptor `FunctionType.__get__`; expected type `FunctionType`"
# error: [no-matching-overload] "No overload of wrapper descriptor `FunctionType.__get__` matches arguments"
wrapper_descriptor(1, None, type(f))

# Calling it with something that is not a `type` as the `owner` argument is an
# error: [invalid-argument-type] "Object of type `Literal[f]` cannot be assigned to parameter 3 (`owner`) of wrapper descriptor `FunctionType.__get__`; expected type `type`"
# error: [no-matching-overload] "No overload of wrapper descriptor `FunctionType.__get__` matches arguments"
wrapper_descriptor(f, None, f)

# Calling it with too many positional arguments is an
# error: [too-many-positional-arguments] "Too many positional arguments to wrapper descriptor `FunctionType.__get__`: expected 3, got 4"
# error: [no-matching-overload] "No overload of wrapper descriptor `FunctionType.__get__` matches arguments"
wrapper_descriptor(f, None, type(f), "one too many")
```

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# No matching overload diagnostics

<!-- snapshot-diagnostics -->

## Calls to overloaded functions

TODO: Note that we do not yet support the `@overload` decorator to define overloaded functions in
real Python code. We are instead testing a special-cased function where we create an overloaded
signature internally. Update this to an `@overload` function in the Python snippet itself once we
can.

```py
type("Foo", ()) # error: [no-matching-overload]
```
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ def _(flag: bool):

# invalid invocation, too many positional args
reveal_type(x) # revealed: Literal[1] | None
if bool(x is not None, 5): # TODO diagnostic
# error: [too-many-positional-arguments] "Too many positional arguments to class `bool`: expected 1, got 2"
if bool(x is not None, 5):
reveal_type(x) # revealed: Literal[1] | None

# invalid invocation, too many kwargs
reveal_type(x) # revealed: Literal[1] | None
if bool(x is not None, y=5): # TODO diagnostic
# error: [unknown-argument] "Argument `y` does not match any known parameter of class `bool`"
if bool(x is not None, y=5):
reveal_type(x) # revealed: Literal[1] | None
```
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def _(x: str | int):

```py
def _(x: str | int):
# TODO: we could issue a diagnostic here
# error: [no-matching-overload] "No overload of class `type` matches arguments"
if type(object=x) is str:
reveal_type(x) # revealed: str | int
```
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
source: crates/red_knot_test/src/lib.rs
expression: snapshot
---
---
mdtest name: no_matching_overload.md - No matching overload diagnostics - Calls to overloaded functions
mdtest path: crates/red_knot_python_semantic/resources/mdtest/diagnostics/no_matching_overload.md
---

# Python source files

## mdtest_snippet.py

```
1 | type("Foo", ()) # error: [no-matching-overload]
```

# Diagnostics

```
error: lint:no-matching-overload
--> /src/mdtest_snippet.py:1:1
|
1 | type("Foo", ()) # error: [no-matching-overload]
| ^^^^^^^^^^^^^^^ No overload of class `type` matches arguments
|

```
Loading
Loading