diff --git a/crates/ty_python_semantic/resources/mdtest/annotations/annotated.md b/crates/ty_python_semantic/resources/mdtest/annotations/annotated.md index 7c0ba50f1a..1bc97ad4c4 100644 --- a/crates/ty_python_semantic/resources/mdtest/annotations/annotated.md +++ b/crates/ty_python_semantic/resources/mdtest/annotations/annotated.md @@ -76,7 +76,18 @@ from ty_extensions import reveal_mro class C(Annotated[int, "foo"]): ... -reveal_mro(C) # revealed: (, , ) +# revealed: (, , ) +reveal_mro(C) + +class D(Annotated[list[str], "foo"]): ... + +# revealed: (, , , , , , , , typing.Protocol, typing.Generic, ) +reveal_mro(D) + +class E(Annotated[list["E"], "metadata"]): ... + +# error: [revealed-type] "Revealed MRO: (, , , , , , , , typing.Protocol, typing.Generic, )" +reveal_mro(E) ``` ### Not parameterized 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 a06b3c65f0..2c52e46a4c 100644 --- a/crates/ty_python_semantic/resources/mdtest/implicit_type_aliases.md +++ b/crates/ty_python_semantic/resources/mdtest/implicit_type_aliases.md @@ -974,13 +974,14 @@ We *do* support stringified annotations if they appear in a position where a typ syntactically expected: ```py -from typing import Union, List, Dict +from typing import Union, List, Dict, Annotated ListOfInts1 = list["int"] ListOfInts2 = List["int"] StrOrStyle = Union[str, "Style"] SubclassOfStyle = type["Style"] DictStrToStyle = Dict[str, "Style"] +AnnotatedStyle = Annotated["Style", "metadata"] class Style: ... @@ -990,12 +991,14 @@ def _( str_or_style: StrOrStyle, subclass_of_style: SubclassOfStyle, dict_str_to_style: DictStrToStyle, + annotated_style: AnnotatedStyle, ): reveal_type(list_of_ints1) # revealed: list[int] reveal_type(list_of_ints2) # revealed: list[int] reveal_type(str_or_style) # revealed: str | Style reveal_type(subclass_of_style) # revealed: type[Style] reveal_type(dict_str_to_style) # revealed: dict[str, Style] + reveal_type(annotated_style) # revealed: Style ``` ## Recursive diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index 952609b3cd..e913a445ae 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -6599,11 +6599,7 @@ impl<'db> Type<'db> { Ok(builder.build()) } KnownInstanceType::Literal(ty) => Ok(ty.inner(db)), - KnownInstanceType::Annotated(ty) => { - Ok(ty - .inner(db) - .in_type_expression(db, scope_id, typevar_binding_context)?) - } + KnownInstanceType::Annotated(ty) => Ok(ty.inner(db)), KnownInstanceType::TypeGenericAlias(ty) => { // 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 diff --git a/crates/ty_python_semantic/src/types/class_base.rs b/crates/ty_python_semantic/src/types/class_base.rs index 83f7cf423c..8015dfcf00 100644 --- a/crates/ty_python_semantic/src/types/class_base.rs +++ b/crates/ty_python_semantic/src/types/class_base.rs @@ -183,7 +183,16 @@ impl<'db> ClassBase<'db> { KnownInstanceType::TypeGenericAlias(_) => { Self::try_from_type(db, KnownClass::Type.to_class_literal(db), subclass) } - KnownInstanceType::Annotated(ty) => Self::try_from_type(db, ty.inner(db), subclass), + KnownInstanceType::Annotated(ty) => { + // Unions are not supported in this position, so we only need to support + // something like `class C(Annotated[Base, "metadata"]): ...`, which we + // can do by turning the instance type (`Base` in this example) back into + // a class. + let annotated_ty = ty.inner(db); + let instance_ty = annotated_ty.as_nominal_instance()?; + + Some(Self::Class(instance_ty.class(db))) + } }, Type::SpecialForm(special_form) => match special_form { diff --git a/crates/ty_python_semantic/src/types/infer/builder.rs b/crates/ty_python_semantic/src/types/infer/builder.rs index 3d573fa27a..ddd6a33edb 100644 --- a/crates/ty_python_semantic/src/types/infer/builder.rs +++ b/crates/ty_python_semantic/src/types/infer/builder.rs @@ -10726,7 +10726,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { self.infer_expression(element, TypeContext::default()); } - let ty = self.infer_expression(type_expr, TypeContext::default()); + let ty = self.infer_type_expression(type_expr); return Type::KnownInstance(KnownInstanceType::Annotated(InternedType::new( self.db(),