Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/ty_python_semantic/resources/mdtest/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ class C:

c_instance = C()
reveal_type(c_instance.a) # revealed: Unknown | Literal[1]
reveal_type(c_instance.b) # revealed: Unknown
reveal_type(c_instance.b) # revealed: Unknown | list[Literal[2, 3]]
```

#### Attributes defined in for-loop (unpacking)
Expand Down
40 changes: 14 additions & 26 deletions crates/ty_python_semantic/resources/mdtest/unpacking.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,7 @@ reveal_type(d) # revealed: Literal[5]
# error: [invalid-assignment] "Not enough values to unpack: Expected 3 or more"
[a, *b, c, d] = (1, 2)
reveal_type(a) # revealed: Unknown
# TODO: Should be list[Any] once support for assigning to starred expression is added
reveal_type(b) # revealed: Unknown
reveal_type(b) # revealed: list[Unknown]
reveal_type(c) # revealed: Unknown
reveal_type(d) # revealed: Unknown
```
Expand All @@ -120,8 +119,7 @@ reveal_type(d) # revealed: Unknown
```py
[a, *b, c] = (1, 2)
reveal_type(a) # revealed: Literal[1]
# TODO: Should be list[Any] once support for assigning to starred expression is added
reveal_type(b) # revealed: @Todo(starred unpacking)
reveal_type(b) # revealed: list[Unknown]
reveal_type(c) # revealed: Literal[2]
```

Expand All @@ -130,8 +128,7 @@ reveal_type(c) # revealed: Literal[2]
```py
[a, *b, c] = (1, 2, 3)
reveal_type(a) # revealed: Literal[1]
# TODO: Should be list[int] once support for assigning to starred expression is added
reveal_type(b) # revealed: @Todo(starred unpacking)
reveal_type(b) # revealed: list[Literal[2]]
reveal_type(c) # revealed: Literal[3]
```

Expand All @@ -140,8 +137,7 @@ reveal_type(c) # revealed: Literal[3]
```py
[a, *b, c, d] = (1, 2, 3, 4, 5, 6)
reveal_type(a) # revealed: Literal[1]
# TODO: Should be list[int] once support for assigning to starred expression is added
reveal_type(b) # revealed: @Todo(starred unpacking)
reveal_type(b) # revealed: list[Literal[2, 3, 4]]
reveal_type(c) # revealed: Literal[5]
reveal_type(d) # revealed: Literal[6]
```
Expand All @@ -152,8 +148,7 @@ reveal_type(d) # revealed: Literal[6]
[a, b, *c] = (1, 2, 3, 4)
reveal_type(a) # revealed: Literal[1]
reveal_type(b) # revealed: Literal[2]
# TODO: Should be list[int] once support for assigning to starred expression is added
reveal_type(c) # revealed: @Todo(starred unpacking)
reveal_type(c) # revealed: list[Literal[3, 4]]
```

### Starred expression (6)
Expand All @@ -164,7 +159,7 @@ reveal_type(c) # revealed: @Todo(starred unpacking)
reveal_type(a) # revealed: Unknown
reveal_type(b) # revealed: Unknown
reveal_type(c) # revealed: Unknown
reveal_type(d) # revealed: Unknown
reveal_type(d) # revealed: list[Unknown]
reveal_type(e) # revealed: Unknown
reveal_type(f) # revealed: Unknown
```
Expand Down Expand Up @@ -247,8 +242,7 @@ reveal_type(b) # revealed: Unknown
# error: [invalid-assignment] "Not enough values to unpack: Expected 3 or more"
(a, *b, c, d) = "ab"
reveal_type(a) # revealed: Unknown
# TODO: Should be list[LiteralString] once support for assigning to starred expression is added
reveal_type(b) # revealed: Unknown
reveal_type(b) # revealed: list[Unknown]
reveal_type(c) # revealed: Unknown
reveal_type(d) # revealed: Unknown
```
Expand All @@ -258,7 +252,7 @@ reveal_type(d) # revealed: Unknown
(a, b, *c, d) = "a"
reveal_type(a) # revealed: Unknown
reveal_type(b) # revealed: Unknown
reveal_type(c) # revealed: Unknown
reveal_type(c) # revealed: list[Unknown]
reveal_type(d) # revealed: Unknown
```

Expand All @@ -267,8 +261,7 @@ reveal_type(d) # revealed: Unknown
```py
(a, *b, c) = "ab"
reveal_type(a) # revealed: LiteralString
# TODO: Should be list[Any] once support for assigning to starred expression is added
reveal_type(b) # revealed: @Todo(starred unpacking)
reveal_type(b) # revealed: list[Unknown]
reveal_type(c) # revealed: LiteralString
```

Expand All @@ -277,8 +270,7 @@ reveal_type(c) # revealed: LiteralString
```py
(a, *b, c) = "abc"
reveal_type(a) # revealed: LiteralString
# TODO: Should be list[LiteralString] once support for assigning to starred expression is added
reveal_type(b) # revealed: @Todo(starred unpacking)
reveal_type(b) # revealed: list[LiteralString]
reveal_type(c) # revealed: LiteralString
```

Expand All @@ -287,8 +279,7 @@ reveal_type(c) # revealed: LiteralString
```py
(a, *b, c, d) = "abcdef"
reveal_type(a) # revealed: LiteralString
# TODO: Should be list[LiteralString] once support for assigning to starred expression is added
reveal_type(b) # revealed: @Todo(starred unpacking)
reveal_type(b) # revealed: list[LiteralString]
reveal_type(c) # revealed: LiteralString
reveal_type(d) # revealed: LiteralString
```
Expand All @@ -299,8 +290,7 @@ reveal_type(d) # revealed: LiteralString
(a, b, *c) = "abcd"
reveal_type(a) # revealed: LiteralString
reveal_type(b) # revealed: LiteralString
# TODO: Should be list[int] once support for assigning to starred expression is added
reveal_type(c) # revealed: @Todo(starred unpacking)
reveal_type(c) # revealed: list[LiteralString]
```

### Unicode
Expand Down Expand Up @@ -411,8 +401,7 @@ def _(arg: tuple[int, tuple[str, bytes]] | tuple[tuple[int, bytes], Literal["ab"
def _(arg: tuple[int, bytes, int] | tuple[int, int, str, int, bytes]):
a, *b, c = arg
reveal_type(a) # revealed: int
# TODO: Should be `list[bytes | int | str]`
reveal_type(b) # revealed: @Todo(starred unpacking)
reveal_type(b) # revealed: list[bytes] | list[int | str]
reveal_type(c) # revealed: int | bytes
```

Expand Down Expand Up @@ -676,8 +665,7 @@ class ContextManager:

with ContextManager() as (a, *b):
reveal_type(a) # revealed: int
# TODO: Should be list[int] once support for assigning to starred expression is added
reveal_type(b) # revealed: @Todo(starred unpacking)
reveal_type(b) # revealed: list[int]
```

### Unbound context manager expression
Expand Down
32 changes: 24 additions & 8 deletions crates/ty_python_semantic/src/types/unpacker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ use ruff_python_ast::{self as ast, AnyNodeRef};
use crate::Db;
use crate::semantic_index::ast_ids::{HasScopedExpressionId, ScopedExpressionId};
use crate::semantic_index::symbol::ScopeId;
use crate::types::{Type, TypeCheckDiagnostics, infer_expression_types, todo_type};
use crate::types::{Type, TypeCheckDiagnostics, infer_expression_types};
use crate::unpack::{UnpackKind, UnpackValue};

use super::context::InferContext;
use super::diagnostic::INVALID_ASSIGNMENT;
use super::{TupleType, UnionType};
use super::{KnownClass, TupleType, UnionType};

/// Unpacks the value expression type to their respective targets.
pub(crate) struct Unpacker<'db> {
Expand Down Expand Up @@ -253,12 +253,17 @@ impl<'db> Unpacker<'db> {
let starred_end_index = tuple_ty.len(self.db()) - remaining;

// SAFETY: Safe because of the length check above.
let _starred_element_types =
let starred_element_types =
&tuple_ty.elements(self.db())[starred_index..starred_end_index];
// TODO: Combine the types into a list type. If the
// starred_element_types is empty, then it should be `List[Any]`.
// combine_types(starred_element_types);
element_types.push(todo_type!("starred unpacking"));

element_types.push(KnownClass::List.to_specialized_instance(
self.db(),
[if starred_element_types.is_empty() {
Type::unknown()
} else {
UnionType::from_elements(self.db(), starred_element_types)
}],
));

// Insert the types remaining that aren't consumed by the starred expression.
element_types.extend_from_slice(
Expand All @@ -278,7 +283,18 @@ impl<'db> Unpacker<'db> {
);
}

Cow::Owned(vec![Type::unknown(); targets.len()])
Cow::Owned(
targets
.iter()
.map(|target| {
if target.is_starred_expr() {
KnownClass::List.to_specialized_instance(self.db(), [Type::unknown()])
} else {
Type::unknown()
}
})
.collect(),
)
}
}

Expand Down
Loading