From 6aaa9d784ab7d8f70a4cd34de994ec7d468b0d78 Mon Sep 17 00:00:00 2001 From: David Peter Date: Tue, 25 Nov 2025 11:13:22 +0100 Subject: [PATCH] Fix problem with np.array related to type[T] --- .../resources/mdtest/implicit_type_aliases.md | 24 +++++++++++++++++++ crates/ty_python_semantic/src/types.rs | 10 ++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/crates/ty_python_semantic/resources/mdtest/implicit_type_aliases.md b/crates/ty_python_semantic/resources/mdtest/implicit_type_aliases.md index 93cdcf515f..c975b14db2 100644 --- a/crates/ty_python_semantic/resources/mdtest/implicit_type_aliases.md +++ b/crates/ty_python_semantic/resources/mdtest/implicit_type_aliases.md @@ -500,14 +500,27 @@ def _( A generic implicit type alias can also be used in another generic implicit type alias: ```py +from typing_extensions import Any + +B = TypeVar("B", bound=int) + MyOtherList = MyList[T] +MyOtherType = MyType[T] +TypeOrList = MyType[B] | MyList[B] reveal_type(MyOtherList) # revealed: +reveal_type(MyOtherType) # revealed: GenericAlias +reveal_type(TypeOrList) # revealed: types.UnionType def _( list_of_ints: MyOtherList[int], + subclass_of_int: MyOtherType[int], + type_or_list: TypeOrList[Any], ): reveal_type(list_of_ints) # revealed: list[int] + reveal_type(subclass_of_int) # revealed: type[int] + # TODO: Should be `type[Any] | list[Any]` + reveal_type(type_or_list) # revealed: @Todo(type[T] for typevar T) | list[Any] ``` If a generic implicit type alias is used unspecialized in a type expression, we treat it as an @@ -1456,3 +1469,14 @@ def _( reveal_type(recursive_dict3) # revealed: dict[Divergent, int] reveal_type(recursive_dict4) # revealed: dict[Divergent, int] ``` + +### Self-referential generic implicit type aliases + + + +```py +from typing import TypeVar + +T = TypeVar("T") +NestedDict = dict[str, "NestedDict[T] | T"] +``` diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index 367ea11be5..fe4afa5356 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -6799,7 +6799,7 @@ impl<'db> Type<'db> { } KnownInstanceType::Literal(ty) => Ok(ty.inner(db)), KnownInstanceType::Annotated(ty) => Ok(ty.inner(db)), - KnownInstanceType::TypeGenericAlias(ty) => { + KnownInstanceType::TypeGenericAlias(instance) => { // When `type[…]` appears in a value position (e.g. in an implicit type alias), // we infer its argument as a type expression. This ensures that we can emit // diagnostics for invalid type expressions, and more importantly, that we can @@ -6808,7 +6808,13 @@ impl<'db> Type<'db> { // (`int` -> instance of `int` -> subclass of `int`) can be lossy, but it is // okay for all valid arguments to `type[…]`. - Ok(ty.inner(db).to_meta_type(db)) + let ty = instance.inner(db); + + if ty.is_type_var() { + Ok(todo_type!("type[T] for typevar T")) + } else { + Ok(ty.to_meta_type(db)) + } } KnownInstanceType::Callable(instance) => { Ok(Type::Callable(instance.callable_type(db)))