[red-knot] Add tests for classes that have incompatible __new__ and __init__ methods (#17747)

Closes #17737
This commit is contained in:
Victor Hugo Gomes 2025-04-30 17:40:16 -03:00 committed by GitHub
parent 650cbdd296
commit d33a503686
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -343,6 +343,64 @@ reveal_type(Foo(1)) # revealed: Foo
reveal_type(Foo(1, 2)) # revealed: Foo
```
### Incompatible signatures
```py
import abc
class Foo:
def __new__(cls) -> "Foo":
return object.__new__(cls)
def __init__(self, x):
self.x = 42
# error: [missing-argument] "No argument provided for required parameter `x` of bound method `__init__`"
reveal_type(Foo()) # revealed: Foo
# error: [too-many-positional-arguments] "Too many positional arguments to function `__new__`: expected 0, got 1"
reveal_type(Foo(42)) # revealed: Foo
class Foo2:
def __new__(cls, x) -> "Foo2":
return object.__new__(cls)
def __init__(self):
pass
# error: [missing-argument] "No argument provided for required parameter `x` of function `__new__`"
reveal_type(Foo2()) # revealed: Foo2
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 0, got 1"
reveal_type(Foo2(42)) # revealed: Foo2
class Foo3(metaclass=abc.ABCMeta):
def __new__(cls) -> "Foo3":
return object.__new__(cls)
def __init__(self, x):
self.x = 42
# error: [missing-argument] "No argument provided for required parameter `x` of bound method `__init__`"
reveal_type(Foo3()) # revealed: Foo3
# error: [too-many-positional-arguments] "Too many positional arguments to function `__new__`: expected 0, got 1"
reveal_type(Foo3(42)) # revealed: Foo3
class Foo4(metaclass=abc.ABCMeta):
def __new__(cls, x) -> "Foo4":
return object.__new__(cls)
def __init__(self):
pass
# error: [missing-argument] "No argument provided for required parameter `x` of function `__new__`"
reveal_type(Foo4()) # revealed: Foo4
# error: [too-many-positional-arguments] "Too many positional arguments to bound method `__init__`: expected 0, got 1"
reveal_type(Foo4(42)) # revealed: Foo4
```
### Lookup of `__new__`
The `__new__` method is always invoked on the class itself, never on the metaclass. This is