mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 10:23:11 +00:00
[red-knot] Add support for calling type[…]
(#16597)
## Summary This fixes the non-diagnostics part of #15948. ## Test Plan New Markdown tests. Negative diff on the ecosystem checks: ```diff zipp (https://github.com/jaraco/zipp) - error: lint:call-non-callable - --> /tmp/mypy_primer/projects/zipp/zipp/__init__.py:393:16 - | - 392 | def _next(self, at): - 393 | return self.__class__(self.root, at) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Object of type `type[Unknown]` is not callable - 394 | - 395 | def is_dir(self): - | - - Found 9 diagnostics + Found 8 diagnostics arrow (https://github.com/arrow-py/arrow) + | + | + warning: lint:unused-ignore-comment + --> /tmp/mypy_primer/projects/arrow/arrow/arrow.py:576:66 + 574 | values.append(1) + 575 | + 576 | floor = self.__class__(*values, tzinfo=self.tzinfo) # type: ignore[misc] + | -------------------- Unused blanket `type: ignore` directive + 577 | + 578 | if frame_absolute == "week": - error: lint:call-non-callable - --> /tmp/mypy_primer/projects/arrow/arrow/arrow.py:1080:16 - | - 1078 | dt = self._datetime.astimezone(tz) - 1079 | - 1080 | return self.__class__( - | ________________^ - 1081 | | dt.year, - 1082 | | dt.month, - 1083 | | dt.day, - 1084 | | dt.hour, - 1085 | | dt.minute, - 1086 | | dt.second, - 1087 | | dt.microsecond, - 1088 | | dt.tzinfo, - 1089 | | fold=getattr(dt, "fold", 0), - 1090 | | ) - | |_________^ Object of type `type[Unknown]` is not callable - 1091 | - 1092 | # string output and formatting - | black (https://github.com/psf/black) - - | - | - error: lint:call-non-callable - --> /tmp/mypy_primer/projects/black/src/blib2to3/pgen2/grammar.py:135:15 - 133 | Copy the grammar. - 134 | """ - 135 | new = self.__class__() - | ^^^^^^^^^^^^^^^^ Object of type `type[@Todo]` is not callable - 136 | for dict_attr in ( - 137 | "symbol2number", - Found 328 diagnostics + Found 327 diagnostics ```
This commit is contained in:
parent
f19cb86c5d
commit
c60e8a037a
2 changed files with 57 additions and 0 deletions
|
@ -0,0 +1,50 @@
|
|||
# Call `type[...]`
|
||||
|
||||
## Single class
|
||||
|
||||
### Trivial constructor
|
||||
|
||||
```py
|
||||
class C: ...
|
||||
|
||||
def _(subclass_of_c: type[C]):
|
||||
reveal_type(subclass_of_c()) # revealed: C
|
||||
```
|
||||
|
||||
### Non-trivial constructor
|
||||
|
||||
```py
|
||||
class C:
|
||||
def __init__(self, x: int): ...
|
||||
|
||||
def _(subclass_of_c: type[C]):
|
||||
reveal_type(subclass_of_c(1)) # revealed: C
|
||||
|
||||
# TODO: Those should all be errors
|
||||
reveal_type(subclass_of_c("a")) # revealed: C
|
||||
reveal_type(subclass_of_c()) # revealed: C
|
||||
reveal_type(subclass_of_c(1, 2)) # revealed: C
|
||||
```
|
||||
|
||||
## Dynamic base
|
||||
|
||||
```py
|
||||
from typing import Any
|
||||
from knot_extensions import Unknown
|
||||
|
||||
def _(subclass_of_any: type[Any], subclass_of_unknown: type[Unknown]):
|
||||
reveal_type(subclass_of_any()) # revealed: Any
|
||||
reveal_type(subclass_of_any("any", "args", 1, 2)) # revealed: Any
|
||||
reveal_type(subclass_of_unknown()) # revealed: Unknown
|
||||
reveal_type(subclass_of_unknown("any", "args", 1, 2)) # revealed: Unknown
|
||||
```
|
||||
|
||||
## Unions of classes
|
||||
|
||||
```py
|
||||
class A: ...
|
||||
class B: ...
|
||||
|
||||
def _(subclass_of_ab: type[A | B]):
|
||||
reveal_type(subclass_of_ab()) # revealed: A | B
|
||||
```
|
|
@ -2678,6 +2678,13 @@ impl<'db> Type<'db> {
|
|||
)))
|
||||
}
|
||||
|
||||
Type::SubclassOf(subclass_of_type) => match subclass_of_type.subclass_of() {
|
||||
ClassBase::Dynamic(dynamic_type) => Ok(CallOutcome::Single(
|
||||
CallBinding::from_return_type(Type::Dynamic(dynamic_type)),
|
||||
)),
|
||||
ClassBase::Class(class) => Type::class_literal(class).try_call(db, arguments),
|
||||
},
|
||||
|
||||
instance_ty @ Type::Instance(_) => {
|
||||
instance_ty
|
||||
.try_call_dunder(db, "__call__", arguments)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue