diff --git a/crates/ty_python_semantic/resources/mdtest/generics/pep695/variables.md b/crates/ty_python_semantic/resources/mdtest/generics/pep695/variables.md index ecee87ec86..8d64ed34a7 100644 --- a/crates/ty_python_semantic/resources/mdtest/generics/pep695/variables.md +++ b/crates/ty_python_semantic/resources/mdtest/generics/pep695/variables.md @@ -766,4 +766,23 @@ def constrained[T: (Callable[[], int], Callable[[], str])](f: T): reveal_type(f()) # revealed: int | str ``` +## Meta-type + +The meta-type of a typevar is the same as the meta-type of the upper bound, or the union of the +meta-types of the constraints: + +```py +def normal[T](x: T): + reveal_type(type(x)) # revealed: type + +def bound_object[T: object](x: T): + reveal_type(type(x)) # revealed: type + +def bound_int[T: int](x: T): + reveal_type(type(x)) # revealed: type[int] + +def constrained[T: (int, str)](x: T): + reveal_type(type(x)) # revealed: type[int] | type[str] +``` + [pep 695]: https://peps.python.org/pep-0695/ diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index f58bd2412b..dc5450245f 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -5243,7 +5243,7 @@ impl<'db> Type<'db> { Type::Tuple(_) => KnownClass::Tuple.to_class_literal(db), Type::TypeVar(typevar) => match typevar.bound_or_constraints(db) { - None => KnownClass::Object.to_class_literal(db), + None => KnownClass::Type.to_instance(db), Some(TypeVarBoundOrConstraints::UpperBound(bound)) => bound.to_meta_type(db), Some(TypeVarBoundOrConstraints::Constraints(constraints)) => { // TODO: If we add a proper `OneOf` connector, we should use that here instead