mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 10:22:24 +00:00
[red-knot] Three-argument type-calls take 'str' as the first argument (#17168)
## Summary Similar to #17163, a minor fix in the signature of `type(…)`. ## Test Plan New MD tests
This commit is contained in:
parent
d401a5440e
commit
3f00010a7a
4 changed files with 41 additions and 4 deletions
|
@ -26,7 +26,11 @@ reveal_type(type(1)) # revealed: Literal[int]
|
|||
But a three-argument call to type creates a dynamic instance of the `type` class:
|
||||
|
||||
```py
|
||||
class Base: ...
|
||||
|
||||
reveal_type(type("Foo", (), {})) # revealed: type
|
||||
|
||||
reveal_type(type("Foo", (Base,), {"attr": 1})) # revealed: type
|
||||
```
|
||||
|
||||
Other numbers of arguments are invalid
|
||||
|
@ -39,6 +43,24 @@ type("Foo", ())
|
|||
type("Foo", (), {}, weird_other_arg=42)
|
||||
```
|
||||
|
||||
The following calls are also invalid, due to incorrect argument types:
|
||||
|
||||
```py
|
||||
class Base: ...
|
||||
|
||||
# error: [no-matching-overload] "No overload of class `type` matches arguments"
|
||||
type(b"Foo", (), {})
|
||||
|
||||
# error: [no-matching-overload] "No overload of class `type` matches arguments"
|
||||
type("Foo", Base, {})
|
||||
|
||||
# TODO: this should be an error
|
||||
type("Foo", (1, 2), {})
|
||||
|
||||
# TODO: this should be an error
|
||||
type("Foo", (Base,), {b"attr": 1})
|
||||
```
|
||||
|
||||
## Calls to `str()`
|
||||
|
||||
### Valid calls
|
||||
|
|
|
@ -76,6 +76,9 @@ No narrowing should occur if `type` is used to dynamically create a class:
|
|||
|
||||
```py
|
||||
def _(x: str | int):
|
||||
# The following diagnostic is valid, since the three-argument form of `type`
|
||||
# can only be called with `str` as the first argument.
|
||||
# error: [no-matching-overload] "No overload of class `type` matches arguments"
|
||||
if type(x, (), {}) is str:
|
||||
reveal_type(x) # revealed: str | int
|
||||
else:
|
||||
|
|
|
@ -194,6 +194,9 @@ static_assert(is_assignable_to(tuple[int, str], tuple[int, str]))
|
|||
static_assert(is_assignable_to(tuple[Literal[1], Literal[2]], tuple[int, int]))
|
||||
static_assert(is_assignable_to(tuple[Any, Literal[2]], tuple[int, int]))
|
||||
static_assert(is_assignable_to(tuple[Literal[1], Any], tuple[int, int]))
|
||||
static_assert(is_assignable_to(tuple[()], tuple))
|
||||
static_assert(is_assignable_to(tuple[int, str], tuple))
|
||||
static_assert(is_assignable_to(tuple[Any], tuple))
|
||||
|
||||
static_assert(not is_assignable_to(tuple[()], tuple[int]))
|
||||
static_assert(not is_assignable_to(tuple[int], tuple[str]))
|
||||
|
|
|
@ -950,6 +950,13 @@ impl<'db> Type<'db> {
|
|||
)
|
||||
}
|
||||
|
||||
// This special case is required because the left-hand side tuple might be a
|
||||
// gradual type, so we can not rely on subtyping. This allows us to assign e.g.
|
||||
// `tuple[Any, int]` to `tuple`.
|
||||
(Type::Tuple(_), _) => KnownClass::Tuple
|
||||
.to_instance(db)
|
||||
.is_assignable_to(db, target),
|
||||
|
||||
// `type[Any]` is assignable to any `type[...]` type, because `type[Any]` can
|
||||
// materialize to any `type[...]` type.
|
||||
(Type::SubclassOf(subclass_of_ty), Type::SubclassOf(_))
|
||||
|
@ -2903,12 +2910,14 @@ impl<'db> Type<'db> {
|
|||
),
|
||||
Signature::new(
|
||||
Parameters::new([
|
||||
Parameter::positional_only(Some(Name::new_static("o")))
|
||||
.with_annotated_type(Type::any()),
|
||||
Parameter::positional_only(Some(Name::new_static("name")))
|
||||
.with_annotated_type(KnownClass::Str.to_instance(db)),
|
||||
Parameter::positional_only(Some(Name::new_static("bases")))
|
||||
.with_annotated_type(Type::any()),
|
||||
// TODO: Should be tuple[type, ...] once we have support for homogenous tuples
|
||||
.with_annotated_type(KnownClass::Tuple.to_instance(db)),
|
||||
Parameter::positional_only(Some(Name::new_static("dict")))
|
||||
.with_annotated_type(Type::any()),
|
||||
// TODO: Should be `dict[str, Any]` once we have support for generics
|
||||
.with_annotated_type(KnownClass::Dict.to_instance(db)),
|
||||
]),
|
||||
Some(KnownClass::Type.to_instance(db)),
|
||||
),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue