mirror of https://github.com/astral-sh/ruff
improvements
This commit is contained in:
parent
7d7a3a883c
commit
263877718f
|
|
@ -42,14 +42,11 @@ reveal_type(len(())) # revealed: Literal[0]
|
||||||
reveal_type(len((1,))) # revealed: Literal[1]
|
reveal_type(len((1,))) # revealed: Literal[1]
|
||||||
reveal_type(len((1, 2))) # revealed: Literal[2]
|
reveal_type(len((1, 2))) # revealed: Literal[2]
|
||||||
reveal_type(len(tuple())) # revealed: Literal[0]
|
reveal_type(len(tuple())) # revealed: Literal[0]
|
||||||
|
reveal_type(len((*[],))) # revealed: Literal[0]
|
||||||
# could also be `Literal[0]`, but `int` is accurate
|
|
||||||
reveal_type(len((*[],))) # revealed: int
|
|
||||||
|
|
||||||
# fmt: off
|
# fmt: off
|
||||||
|
|
||||||
# could also be `Literal[1]`, but `int` is accurate
|
reveal_type(len( # revealed: Literal[1]
|
||||||
reveal_type(len( # revealed: int
|
|
||||||
(
|
(
|
||||||
*[],
|
*[],
|
||||||
1,
|
1,
|
||||||
|
|
@ -58,11 +55,8 @@ reveal_type(len( # revealed: int
|
||||||
|
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
# Could also be `Literal[2]`, but `int` is accurate
|
reveal_type(len((*[], 1, 2))) # revealed: Literal[2]
|
||||||
reveal_type(len((*[], 1, 2))) # revealed: int
|
reveal_type(len((*[], *{}))) # revealed: Literal[0]
|
||||||
|
|
||||||
# Could also be `Literal[0]`, but `int` is accurate
|
|
||||||
reveal_type(len((*[], *{}))) # revealed: int
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Tuple subclasses:
|
Tuple subclasses:
|
||||||
|
|
|
||||||
|
|
@ -534,6 +534,8 @@ reveal_type(x) # revealed: list[Literal[1, 2, 3]]
|
||||||
## Tuples with starred elements
|
## Tuples with starred elements
|
||||||
|
|
||||||
```py
|
```py
|
||||||
|
from typing import Literal, Sequence
|
||||||
|
|
||||||
x = (1, *range(3), 3)
|
x = (1, *range(3), 3)
|
||||||
reveal_type(x) # revealed: tuple[Literal[1], *tuple[int, ...], Literal[3]]
|
reveal_type(x) # revealed: tuple[Literal[1], *tuple[int, ...], Literal[3]]
|
||||||
|
|
||||||
|
|
@ -542,7 +544,21 @@ y = 1, 2
|
||||||
reveal_type(("foo", *y)) # revealed: tuple[Literal["foo"], Literal[1], Literal[2]]
|
reveal_type(("foo", *y)) # revealed: tuple[Literal["foo"], Literal[1], Literal[2]]
|
||||||
|
|
||||||
aa: tuple[list[int], ...] = ([42], *{[56], [78]}, [100])
|
aa: tuple[list[int], ...] = ([42], *{[56], [78]}, [100])
|
||||||
reveal_type(aa) # revealed: tuple[list[int], *tuple[list[int], ...], list[int]]
|
reveal_type(aa) # revealed: tuple[list[int], list[int], list[int], list[int]]
|
||||||
|
|
||||||
|
bb: tuple[list[Literal[42, 56]], ...] = ([42], *{[56, 42], [42]}, [42, 42, 56])
|
||||||
|
reveal_type(bb) # revealed: tuple[list[Literal[42, 56]], list[Literal[42, 56]], list[Literal[42, 56]], list[Literal[42, 56]]]
|
||||||
|
|
||||||
|
reveal_type((*[],)) # revealed: tuple[()]
|
||||||
|
reveal_type((42, *[], 56, *[])) # revealed: tuple[Literal[42], Literal[56]]
|
||||||
|
|
||||||
|
tup: Sequence[str] = (*{"foo": 42, "bar": 56},)
|
||||||
|
|
||||||
|
# TODO: `tuple[str, str]` would be better, given the type annotation
|
||||||
|
reveal_type(tup) # revealed: tuple[Unknown | str, Unknown | str]
|
||||||
|
|
||||||
|
def f(x: list[int]):
|
||||||
|
reveal_type((42, 56, *x, 97)) # revealed: tuple[Literal[42], Literal[56], *tuple[int, ...], Literal[97]]
|
||||||
```
|
```
|
||||||
|
|
||||||
[not a singleton type]: https://discuss.python.org/t/should-we-specify-in-the-language-reference-that-the-empty-tuple-is-a-singleton/67957
|
[not a singleton type]: https://discuss.python.org/t/should-we-specify-in-the-language-reference-that-the-empty-tuple-is-a-singleton/67957
|
||||||
|
|
|
||||||
|
|
@ -7334,12 +7334,33 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
let mut builder = TupleSpecBuilder::with_capacity(elts.len());
|
let mut builder = TupleSpecBuilder::with_capacity(elts.len());
|
||||||
|
|
||||||
for element in elts {
|
for element in elts {
|
||||||
if element.is_starred_expr() {
|
if let ast::Expr::Starred(starred) = element {
|
||||||
let element_type = infer_element(element);
|
let element_type = infer_element(element);
|
||||||
// Fine to use `iterate` rather than `try_iterate` here:
|
// Fine to use `iterate` rather than `try_iterate` here:
|
||||||
// errors from iterating over something not iterable will have been
|
// errors from iterating over something not iterable will have been
|
||||||
// emitted in the `infer_element` call above.
|
// emitted in the `infer_element` call above.
|
||||||
builder = builder.concat(db, &element_type.iterate(db));
|
let mut spec = element_type.iterate(db).into_owned();
|
||||||
|
|
||||||
|
let known_length = match &*starred.value {
|
||||||
|
ast::Expr::List(ast::ExprList { elts, .. })
|
||||||
|
| ast::Expr::Set(ast::ExprSet { elts, .. }) => elts
|
||||||
|
.iter()
|
||||||
|
.all(|elt| !elt.is_starred_expr())
|
||||||
|
.then_some(elts.len()),
|
||||||
|
ast::Expr::Dict(ast::ExprDict { items, .. }) => items
|
||||||
|
.iter()
|
||||||
|
.all(|item| item.key.is_some())
|
||||||
|
.then_some(items.len()),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(known_length) = known_length {
|
||||||
|
spec = spec
|
||||||
|
.resize(db, TupleLength::Fixed(known_length))
|
||||||
|
.unwrap_or(spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder = builder.concat(db, &spec);
|
||||||
} else {
|
} else {
|
||||||
builder.push(infer_element(element));
|
builder.push(infer_element(element));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue