diff --git a/crates/ty_python_semantic/resources/mdtest/pep695_type_aliases.md b/crates/ty_python_semantic/resources/mdtest/pep695_type_aliases.md index ee5bffcb19..904f08099a 100644 --- a/crates/ty_python_semantic/resources/mdtest/pep695_type_aliases.md +++ b/crates/ty_python_semantic/resources/mdtest/pep695_type_aliases.md @@ -64,6 +64,17 @@ x: MyIntOrStr = 1 y: MyIntOrStr = None ``` +## Unpacking from a type alias + +```py +type T = tuple[int, str] + +def f(x: T): + a, b = x + reveal_type(a) # revealed: int + reveal_type(b) # revealed: str +``` + ## Generic type aliases ```py diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index ac5124a4bc..30e01fdc97 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -4866,7 +4866,39 @@ impl<'db> Type<'db> { // diagnostic in unreachable code. return Ok(Cow::Owned(TupleSpec::homogeneous(Type::unknown()))); } - _ => {} + Type::TypeAlias(alias) => { + return alias.value_type(db).try_iterate_with_mode(db, mode); + } + Type::Dynamic(_) + | Type::FunctionLiteral(_) + | Type::GenericAlias(_) + | Type::BoundMethod(_) + | Type::MethodWrapper(_) + | Type::WrapperDescriptor(_) + | Type::DataclassDecorator(_) + | Type::DataclassTransformer(_) + | Type::Callable(_) + | Type::ModuleLiteral(_) + | Type::ClassLiteral(_) + | Type::SubclassOf(_) + | Type::ProtocolInstance(_) + | Type::SpecialForm(_) + | Type::KnownInstance(_) + | Type::PropertyInstance(_) + | Type::Union(_) + | Type::Intersection(_) + | Type::AlwaysTruthy + | Type::AlwaysFalsy + | Type::IntLiteral(_) + | Type::BooleanLiteral(_) + | Type::EnumLiteral(_) + | Type::LiteralString + | Type::BytesLiteral(_) + | Type::TypeVar(_) + | Type::NonInferableTypeVar(_) + | Type::BoundSuper(_) + | Type::TypeIs(_) + | Type::TypedDict(_) => {} } let try_call_dunder_getitem = || {