Skip to content

Commit 630a684

Browse files
committed
[ty] support type[tuple[...]]
1 parent 9cb60b3 commit 630a684

File tree

2 files changed

+19
-3
lines changed

2 files changed

+19
-3
lines changed

crates/ty_python_semantic/resources/mdtest/subscript/tuple.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,16 @@ reveal_type(tuple[int, str]) # revealed: <class 'tuple[int, str]'>
329329
reveal_type(tuple[int, ...]) # revealed: <class 'tuple[int, ...]'>
330330
```
331331

332+
```py
333+
from typing import Any
334+
335+
def _(a: type[tuple], b: type[tuple[int]], c: type[tuple[int, ...]], d: type[tuple[Any, ...]]) -> None:
336+
reveal_type(a) # revealed: type[tuple[Unknown, ...]]
337+
reveal_type(b) # revealed: type[tuple[int]]
338+
reveal_type(c) # revealed: type[tuple[int, ...]]
339+
reveal_type(d) # revealed: type[tuple[Any, ...]]
340+
```
341+
332342
## Inheritance
333343

334344
```toml
@@ -392,7 +402,7 @@ class C(Tuple): ...
392402
reveal_mro(C)
393403
```
394404

395-
### Union subscript access
405+
## Union subscript access
396406

397407
```py
398408
def test(val: tuple[str] | tuple[int]):
@@ -402,15 +412,15 @@ def test2(val: tuple[str, None] | list[int | float]):
402412
reveal_type(val[0]) # revealed: str | int | float
403413
```
404414

405-
### Union subscript access with non-indexable type
415+
## Union subscript access with non-indexable type
406416

407417
```py
408418
def test3(val: tuple[str] | tuple[int] | int):
409419
# error: [non-subscriptable] "Cannot subscript object of type `int` with no `__getitem__` method"
410420
reveal_type(val[0]) # revealed: str | int | Unknown
411421
```
412422

413-
### Intersection subscript access
423+
## Intersection subscript access
414424

415425
```py
416426
from ty_extensions import Intersection

crates/ty_python_semantic/src/types/infer/builder/type_expression.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,12 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
709709
self.db(),
710710
todo_type!("type[T] for protocols").expect_dynamic(),
711711
)
712+
} else if class_literal.is_tuple(self.db()) {
713+
let class_type = self
714+
.infer_tuple_type_expression(parameters)
715+
.map(|tuple_type| tuple_type.to_class_type(self.db()))
716+
.unwrap_or_else(|| class_literal.default_specialization(self.db()));
717+
SubclassOfType::from(self.db(), class_type)
712718
} else {
713719
match class_literal.generic_context(self.db()) {
714720
Some(generic_context) => {

0 commit comments

Comments
 (0)