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 7f0cab333f..97bce36638 100644 --- a/crates/ty_python_semantic/resources/mdtest/implicit_type_aliases.md +++ b/crates/ty_python_semantic/resources/mdtest/implicit_type_aliases.md @@ -558,6 +558,23 @@ def _( reveal_type(list_of_ints2) # revealed: list[int] ``` +### In stringified annotations + +Generic implicit type aliases can be specialized in stringified annotations: + +```py +from typing_extensions import TypeVar + +T = TypeVar("T") + +MyList = list[T] + +def _( + list_of_ints: "MyList[int]", +): + reveal_type(list_of_ints) # revealed: @Todo(Specialization of generic type alias in stringified annotation) +``` + ### Error cases A generic alias that is already fully specialized cannot be specialized again: diff --git a/crates/ty_python_semantic/src/types/infer/builder/type_expression.rs b/crates/ty_python_semantic/src/types/infer/builder/type_expression.rs index bee6e3146c..9000badb19 100644 --- a/crates/ty_python_semantic/src/types/infer/builder/type_expression.rs +++ b/crates/ty_python_semantic/src/types/infer/builder/type_expression.rs @@ -759,6 +759,14 @@ impl<'db> TypeInferenceBuilder<'db, '_> { ) -> Type<'db> { let db = self.db(); + if self + .index + .try_expression_scope_id(&ast::ExprRef::from(subscript)) + .is_none() + { + return todo_type!("Specialization of generic type alias in stringified annotation"); + } + let definitions = match &*subscript.value { ast::Expr::Name(id) => { // TODO: This is an expensive call to an API that was never meant to be called from