add GenericContext mdtest class

This commit is contained in:
Douglas Creager 2025-11-12 17:58:07 -05:00
parent 25631f0f63
commit 2d16039709
13 changed files with 190 additions and 76 deletions

View file

@ -503,9 +503,11 @@ class C[T]():
def f(self: Self):
def b(x: Self):
reveal_type(x) # revealed: Self@f
reveal_type(generic_context(b)) # revealed: None
# revealed: None
reveal_type(generic_context(b))
reveal_type(generic_context(C.f)) # revealed: tuple[Self@f]
# revealed: ty_extensions.GenericContext[Self@f]
reveal_type(generic_context(C.f))
```
Even if the `Self` annotation appears first in the nested function, it is the method that binds
@ -519,9 +521,11 @@ class C:
def f(self: "C"):
def b(x: Self):
reveal_type(x) # revealed: Self@f
reveal_type(generic_context(b)) # revealed: None
# revealed: None
reveal_type(generic_context(b))
reveal_type(generic_context(C.f)) # revealed: None
# revealed: None
reveal_type(generic_context(C.f))
```
## Non-positional first parameters

View file

@ -21,14 +21,14 @@ class TypeVarAndParamSpec(Generic[P, T]): ...
class SingleTypeVarTuple(Generic[Unpack[Ts]]): ...
class TypeVarAndTypeVarTuple(Generic[T, Unpack[Ts]]): ...
# revealed: tuple[T@SingleTypevar]
# revealed: ty_extensions.GenericContext[T@SingleTypevar]
reveal_type(generic_context(SingleTypevar))
# revealed: tuple[T@MultipleTypevars, S@MultipleTypevars]
# revealed: ty_extensions.GenericContext[T@MultipleTypevars, S@MultipleTypevars]
reveal_type(generic_context(MultipleTypevars))
# revealed: tuple[P@SingleParamSpec]
# revealed: ty_extensions.GenericContext[P@SingleParamSpec]
reveal_type(generic_context(SingleParamSpec))
# revealed: tuple[P@TypeVarAndParamSpec, T@TypeVarAndParamSpec]
# revealed: ty_extensions.GenericContext[P@TypeVarAndParamSpec, T@TypeVarAndParamSpec]
reveal_type(generic_context(TypeVarAndParamSpec))
# TODO: support `TypeVarTuple` properly (these should not reveal `None`)
@ -66,9 +66,9 @@ class InheritedGeneric(MultipleTypevars[T, S]): ...
class InheritedGenericPartiallySpecialized(MultipleTypevars[T, int]): ...
class InheritedGenericFullySpecialized(MultipleTypevars[str, int]): ...
# revealed: tuple[T@InheritedGeneric, S@InheritedGeneric]
# revealed: ty_extensions.GenericContext[T@InheritedGeneric, S@InheritedGeneric]
reveal_type(generic_context(InheritedGeneric))
# revealed: tuple[T@InheritedGenericPartiallySpecialized]
# revealed: ty_extensions.GenericContext[T@InheritedGenericPartiallySpecialized]
reveal_type(generic_context(InheritedGenericPartiallySpecialized))
# revealed: None
reveal_type(generic_context(InheritedGenericFullySpecialized))
@ -90,7 +90,7 @@ class OuterClass(Generic[T]):
# revealed: None
reveal_type(generic_context(InnerClassInMethod))
# revealed: tuple[T@OuterClass]
# revealed: ty_extensions.GenericContext[T@OuterClass]
reveal_type(generic_context(OuterClass))
```
@ -118,11 +118,11 @@ class ExplicitInheritedGenericPartiallySpecializedExtraTypevar(MultipleTypevars[
# error: [invalid-generic-class] "`Generic` base class must include all type variables used in other base classes"
class ExplicitInheritedGenericPartiallySpecializedMissingTypevar(MultipleTypevars[T, int], Generic[S]): ...
# revealed: tuple[T@ExplicitInheritedGeneric, S@ExplicitInheritedGeneric]
# revealed: ty_extensions.GenericContext[T@ExplicitInheritedGeneric, S@ExplicitInheritedGeneric]
reveal_type(generic_context(ExplicitInheritedGeneric))
# revealed: tuple[T@ExplicitInheritedGenericPartiallySpecialized]
# revealed: ty_extensions.GenericContext[T@ExplicitInheritedGenericPartiallySpecialized]
reveal_type(generic_context(ExplicitInheritedGenericPartiallySpecialized))
# revealed: tuple[T@ExplicitInheritedGenericPartiallySpecializedExtraTypevar, S@ExplicitInheritedGenericPartiallySpecializedExtraTypevar]
# revealed: ty_extensions.GenericContext[T@ExplicitInheritedGenericPartiallySpecializedExtraTypevar, S@ExplicitInheritedGenericPartiallySpecializedExtraTypevar]
reveal_type(generic_context(ExplicitInheritedGenericPartiallySpecializedExtraTypevar))
```
@ -594,18 +594,27 @@ class C(Generic[T]):
def generic_method(self, t: T, u: U) -> U:
return u
reveal_type(generic_context(C)) # revealed: tuple[T@C]
reveal_type(generic_context(C.method)) # revealed: tuple[Self@method]
reveal_type(generic_context(C.generic_method)) # revealed: tuple[Self@generic_method, U@generic_method]
reveal_type(generic_context(C[int])) # revealed: None
reveal_type(generic_context(C[int].method)) # revealed: tuple[Self@method]
reveal_type(generic_context(C[int].generic_method)) # revealed: tuple[Self@generic_method, U@generic_method]
# revealed: ty_extensions.GenericContext[T@C]
reveal_type(generic_context(C))
# revealed: ty_extensions.GenericContext[Self@method]
reveal_type(generic_context(C.method))
# revealed: ty_extensions.GenericContext[Self@generic_method, U@generic_method]
reveal_type(generic_context(C.generic_method))
# revealed: None
reveal_type(generic_context(C[int]))
# revealed: ty_extensions.GenericContext[Self@method]
reveal_type(generic_context(C[int].method))
# revealed: ty_extensions.GenericContext[Self@generic_method, U@generic_method]
reveal_type(generic_context(C[int].generic_method))
c: C[int] = C[int]()
reveal_type(c.generic_method(1, "string")) # revealed: Literal["string"]
reveal_type(generic_context(c)) # revealed: None
reveal_type(generic_context(c.method)) # revealed: tuple[Self@method]
reveal_type(generic_context(c.generic_method)) # revealed: tuple[Self@generic_method, U@generic_method]
# revealed: None
reveal_type(generic_context(c))
# revealed: ty_extensions.GenericContext[Self@method]
reveal_type(generic_context(c.method))
# revealed: ty_extensions.GenericContext[Self@generic_method, U@generic_method]
reveal_type(generic_context(c.generic_method))
```
## Specializations propagate

View file

@ -20,17 +20,21 @@ type TypeVarAndParamSpec[T, **P] = ...
type SingleTypeVarTuple[*Ts] = ...
type TypeVarAndTypeVarTuple[T, *Ts] = ...
# revealed: tuple[T@SingleTypevar]
# revealed: ty_extensions.GenericContext[T@SingleTypevar]
reveal_type(generic_context(SingleTypevar))
# revealed: tuple[T@MultipleTypevars, S@MultipleTypevars]
# revealed: ty_extensions.GenericContext[T@MultipleTypevars, S@MultipleTypevars]
reveal_type(generic_context(MultipleTypevars))
# TODO: support `ParamSpec`/`TypeVarTuple` properly
# (these should include the `ParamSpec`s and `TypeVarTuple`s in their generic contexts)
reveal_type(generic_context(SingleParamSpec)) # revealed: tuple[()]
reveal_type(generic_context(TypeVarAndParamSpec)) # revealed: tuple[T@TypeVarAndParamSpec]
reveal_type(generic_context(SingleTypeVarTuple)) # revealed: tuple[()]
reveal_type(generic_context(TypeVarAndTypeVarTuple)) # revealed: tuple[T@TypeVarAndTypeVarTuple]
# revealed: ty_extensions.GenericContext[]
reveal_type(generic_context(SingleParamSpec))
# revealed: ty_extensions.GenericContext[T@TypeVarAndParamSpec]
reveal_type(generic_context(TypeVarAndParamSpec))
# revealed: ty_extensions.GenericContext[]
reveal_type(generic_context(SingleTypeVarTuple))
# revealed: ty_extensions.GenericContext[T@TypeVarAndTypeVarTuple]
reveal_type(generic_context(TypeVarAndTypeVarTuple))
```
You cannot use the same typevar more than once.

View file

@ -20,17 +20,21 @@ class TypeVarAndParamSpec[T, **P]: ...
class SingleTypeVarTuple[*Ts]: ...
class TypeVarAndTypeVarTuple[T, *Ts]: ...
# revealed: tuple[T@SingleTypevar]
# revealed: ty_extensions.GenericContext[T@SingleTypevar]
reveal_type(generic_context(SingleTypevar))
# revealed: tuple[T@MultipleTypevars, S@MultipleTypevars]
# revealed: ty_extensions.GenericContext[T@MultipleTypevars, S@MultipleTypevars]
reveal_type(generic_context(MultipleTypevars))
# TODO: support `ParamSpec`/`TypeVarTuple` properly
# (these should include the `ParamSpec`s and `TypeVarTuple`s in their generic contexts)
reveal_type(generic_context(SingleParamSpec)) # revealed: tuple[()]
reveal_type(generic_context(TypeVarAndParamSpec)) # revealed: tuple[T@TypeVarAndParamSpec]
reveal_type(generic_context(SingleTypeVarTuple)) # revealed: tuple[()]
reveal_type(generic_context(TypeVarAndTypeVarTuple)) # revealed: tuple[T@TypeVarAndTypeVarTuple]
# revealed: ty_extensions.GenericContext[]
reveal_type(generic_context(SingleParamSpec))
# revealed: ty_extensions.GenericContext[T@TypeVarAndParamSpec]
reveal_type(generic_context(TypeVarAndParamSpec))
# revealed: ty_extensions.GenericContext[]
reveal_type(generic_context(SingleTypeVarTuple))
# revealed: ty_extensions.GenericContext[T@TypeVarAndTypeVarTuple]
reveal_type(generic_context(TypeVarAndTypeVarTuple))
```
You cannot use the same typevar more than once.
@ -49,9 +53,9 @@ class InheritedGeneric[U, V](MultipleTypevars[U, V]): ...
class InheritedGenericPartiallySpecialized[U](MultipleTypevars[U, int]): ...
class InheritedGenericFullySpecialized(MultipleTypevars[str, int]): ...
# revealed: tuple[U@InheritedGeneric, V@InheritedGeneric]
# revealed: ty_extensions.GenericContext[U@InheritedGeneric, V@InheritedGeneric]
reveal_type(generic_context(InheritedGeneric))
# revealed: tuple[U@InheritedGenericPartiallySpecialized]
# revealed: ty_extensions.GenericContext[U@InheritedGenericPartiallySpecialized]
reveal_type(generic_context(InheritedGenericPartiallySpecialized))
# revealed: None
reveal_type(generic_context(InheritedGenericFullySpecialized))
@ -64,7 +68,8 @@ the inheriting class generic.
```py
class InheritedGenericDefaultSpecialization(MultipleTypevars): ...
reveal_type(generic_context(InheritedGenericDefaultSpecialization)) # revealed: None
# revealed: None
reveal_type(generic_context(InheritedGenericDefaultSpecialization))
```
You cannot use PEP-695 syntax and the legacy syntax in the same class definition.
@ -512,18 +517,27 @@ class C[T]:
# TODO: error
def cannot_shadow_class_typevar[T](self, t: T): ...
reveal_type(generic_context(C)) # revealed: tuple[T@C]
reveal_type(generic_context(C.method)) # revealed: tuple[Self@method]
reveal_type(generic_context(C.generic_method)) # revealed: tuple[Self@generic_method, U@generic_method]
reveal_type(generic_context(C[int])) # revealed: None
reveal_type(generic_context(C[int].method)) # revealed: tuple[Self@method]
reveal_type(generic_context(C[int].generic_method)) # revealed: tuple[Self@generic_method, U@generic_method]
# revealed: ty_extensions.GenericContext[T@C]
reveal_type(generic_context(C))
# revealed: ty_extensions.GenericContext[Self@method]
reveal_type(generic_context(C.method))
# revealed: ty_extensions.GenericContext[Self@generic_method, U@generic_method]
reveal_type(generic_context(C.generic_method))
# revealed: None
reveal_type(generic_context(C[int]))
# revealed: ty_extensions.GenericContext[Self@method]
reveal_type(generic_context(C[int].method))
# revealed: ty_extensions.GenericContext[Self@generic_method, U@generic_method]
reveal_type(generic_context(C[int].generic_method))
c: C[int] = C[int]()
reveal_type(c.generic_method(1, "string")) # revealed: Literal["string"]
reveal_type(generic_context(c)) # revealed: None
reveal_type(generic_context(c.method)) # revealed: tuple[Self@method]
reveal_type(generic_context(c.generic_method)) # revealed: tuple[Self@generic_method, U@generic_method]
# revealed: None
reveal_type(generic_context(c))
# revealed: ty_extensions.GenericContext[Self@method]
reveal_type(generic_context(c.method))
# revealed: ty_extensions.GenericContext[Self@generic_method, U@generic_method]
reveal_type(generic_context(c.generic_method))
```
## Specializations propagate

View file

@ -154,8 +154,10 @@ from ty_extensions import generic_context
legacy.m("string", None) # error: [invalid-argument-type]
reveal_type(legacy.m) # revealed: bound method Legacy[int].m[S](x: int, y: S@m) -> S@m
reveal_type(generic_context(Legacy)) # revealed: tuple[T@Legacy]
reveal_type(generic_context(legacy.m)) # revealed: tuple[Self@m, S@m]
# revealed: ty_extensions.GenericContext[T@Legacy]
reveal_type(generic_context(Legacy))
# revealed: ty_extensions.GenericContext[Self@m, S@m]
reveal_type(generic_context(legacy.m))
```
With PEP 695 syntax, it is clearer that the method uses a separate typevar: