Skip to content

Commit d4c005d

Browse files
committed
add GenericContext mdtest class
1 parent 0e09549 commit d4c005d

File tree

13 files changed

+190
-76
lines changed

13 files changed

+190
-76
lines changed

crates/ty_python_semantic/resources/mdtest/annotations/self.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -503,9 +503,11 @@ class C[T]():
503503
def f(self: Self):
504504
def b(x: Self):
505505
reveal_type(x) # revealed: Self@f
506-
reveal_type(generic_context(b)) # revealed: None
506+
# revealed: None
507+
reveal_type(generic_context(b))
507508

508-
reveal_type(generic_context(C.f)) # revealed: tuple[Self@f]
509+
# revealed: ty_extensions.GenericContext[Self@f]
510+
reveal_type(generic_context(C.f))
509511
```
510512

511513
Even if the `Self` annotation appears first in the nested function, it is the method that binds
@@ -519,9 +521,11 @@ class C:
519521
def f(self: "C"):
520522
def b(x: Self):
521523
reveal_type(x) # revealed: Self@f
522-
reveal_type(generic_context(b)) # revealed: None
524+
# revealed: None
525+
reveal_type(generic_context(b))
523526

524-
reveal_type(generic_context(C.f)) # revealed: None
527+
# revealed: None
528+
reveal_type(generic_context(C.f))
525529
```
526530

527531
## Non-positional first parameters

crates/ty_python_semantic/resources/mdtest/generics/legacy/classes.md

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ class TypeVarAndParamSpec(Generic[P, T]): ...
2121
class SingleTypeVarTuple(Generic[Unpack[Ts]]): ...
2222
class TypeVarAndTypeVarTuple(Generic[T, Unpack[Ts]]): ...
2323

24-
# revealed: tuple[T@SingleTypevar]
24+
# revealed: ty_extensions.GenericContext[T@SingleTypevar]
2525
reveal_type(generic_context(SingleTypevar))
26-
# revealed: tuple[T@MultipleTypevars, S@MultipleTypevars]
26+
# revealed: ty_extensions.GenericContext[T@MultipleTypevars, S@MultipleTypevars]
2727
reveal_type(generic_context(MultipleTypevars))
2828

29-
# revealed: tuple[P@SingleParamSpec]
29+
# revealed: ty_extensions.GenericContext[P@SingleParamSpec]
3030
reveal_type(generic_context(SingleParamSpec))
31-
# revealed: tuple[P@TypeVarAndParamSpec, T@TypeVarAndParamSpec]
31+
# revealed: ty_extensions.GenericContext[P@TypeVarAndParamSpec, T@TypeVarAndParamSpec]
3232
reveal_type(generic_context(TypeVarAndParamSpec))
3333

3434
# TODO: support `TypeVarTuple` properly (these should not reveal `None`)
@@ -66,9 +66,9 @@ class InheritedGeneric(MultipleTypevars[T, S]): ...
6666
class InheritedGenericPartiallySpecialized(MultipleTypevars[T, int]): ...
6767
class InheritedGenericFullySpecialized(MultipleTypevars[str, int]): ...
6868

69-
# revealed: tuple[T@InheritedGeneric, S@InheritedGeneric]
69+
# revealed: ty_extensions.GenericContext[T@InheritedGeneric, S@InheritedGeneric]
7070
reveal_type(generic_context(InheritedGeneric))
71-
# revealed: tuple[T@InheritedGenericPartiallySpecialized]
71+
# revealed: ty_extensions.GenericContext[T@InheritedGenericPartiallySpecialized]
7272
reveal_type(generic_context(InheritedGenericPartiallySpecialized))
7373
# revealed: None
7474
reveal_type(generic_context(InheritedGenericFullySpecialized))
@@ -90,7 +90,7 @@ class OuterClass(Generic[T]):
9090
# revealed: None
9191
reveal_type(generic_context(InnerClassInMethod))
9292

93-
# revealed: tuple[T@OuterClass]
93+
# revealed: ty_extensions.GenericContext[T@OuterClass]
9494
reveal_type(generic_context(OuterClass))
9595
```
9696

@@ -118,11 +118,11 @@ class ExplicitInheritedGenericPartiallySpecializedExtraTypevar(MultipleTypevars[
118118
# error: [invalid-generic-class] "`Generic` base class must include all type variables used in other base classes"
119119
class ExplicitInheritedGenericPartiallySpecializedMissingTypevar(MultipleTypevars[T, int], Generic[S]): ...
120120

121-
# revealed: tuple[T@ExplicitInheritedGeneric, S@ExplicitInheritedGeneric]
121+
# revealed: ty_extensions.GenericContext[T@ExplicitInheritedGeneric, S@ExplicitInheritedGeneric]
122122
reveal_type(generic_context(ExplicitInheritedGeneric))
123-
# revealed: tuple[T@ExplicitInheritedGenericPartiallySpecialized]
123+
# revealed: ty_extensions.GenericContext[T@ExplicitInheritedGenericPartiallySpecialized]
124124
reveal_type(generic_context(ExplicitInheritedGenericPartiallySpecialized))
125-
# revealed: tuple[T@ExplicitInheritedGenericPartiallySpecializedExtraTypevar, S@ExplicitInheritedGenericPartiallySpecializedExtraTypevar]
125+
# revealed: ty_extensions.GenericContext[T@ExplicitInheritedGenericPartiallySpecializedExtraTypevar, S@ExplicitInheritedGenericPartiallySpecializedExtraTypevar]
126126
reveal_type(generic_context(ExplicitInheritedGenericPartiallySpecializedExtraTypevar))
127127
```
128128

@@ -594,18 +594,27 @@ class C(Generic[T]):
594594
def generic_method(self, t: T, u: U) -> U:
595595
return u
596596

597-
reveal_type(generic_context(C)) # revealed: tuple[T@C]
598-
reveal_type(generic_context(C.method)) # revealed: tuple[Self@method]
599-
reveal_type(generic_context(C.generic_method)) # revealed: tuple[Self@generic_method, U@generic_method]
600-
reveal_type(generic_context(C[int])) # revealed: None
601-
reveal_type(generic_context(C[int].method)) # revealed: tuple[Self@method]
602-
reveal_type(generic_context(C[int].generic_method)) # revealed: tuple[Self@generic_method, U@generic_method]
597+
# revealed: ty_extensions.GenericContext[T@C]
598+
reveal_type(generic_context(C))
599+
# revealed: ty_extensions.GenericContext[Self@method]
600+
reveal_type(generic_context(C.method))
601+
# revealed: ty_extensions.GenericContext[Self@generic_method, U@generic_method]
602+
reveal_type(generic_context(C.generic_method))
603+
# revealed: None
604+
reveal_type(generic_context(C[int]))
605+
# revealed: ty_extensions.GenericContext[Self@method]
606+
reveal_type(generic_context(C[int].method))
607+
# revealed: ty_extensions.GenericContext[Self@generic_method, U@generic_method]
608+
reveal_type(generic_context(C[int].generic_method))
603609

604610
c: C[int] = C[int]()
605611
reveal_type(c.generic_method(1, "string")) # revealed: Literal["string"]
606-
reveal_type(generic_context(c)) # revealed: None
607-
reveal_type(generic_context(c.method)) # revealed: tuple[Self@method]
608-
reveal_type(generic_context(c.generic_method)) # revealed: tuple[Self@generic_method, U@generic_method]
612+
# revealed: None
613+
reveal_type(generic_context(c))
614+
# revealed: ty_extensions.GenericContext[Self@method]
615+
reveal_type(generic_context(c.method))
616+
# revealed: ty_extensions.GenericContext[Self@generic_method, U@generic_method]
617+
reveal_type(generic_context(c.generic_method))
609618
```
610619

611620
## Specializations propagate

crates/ty_python_semantic/resources/mdtest/generics/pep695/aliases.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,21 @@ type TypeVarAndParamSpec[T, **P] = ...
2020
type SingleTypeVarTuple[*Ts] = ...
2121
type TypeVarAndTypeVarTuple[T, *Ts] = ...
2222

23-
# revealed: tuple[T@SingleTypevar]
23+
# revealed: ty_extensions.GenericContext[T@SingleTypevar]
2424
reveal_type(generic_context(SingleTypevar))
25-
# revealed: tuple[T@MultipleTypevars, S@MultipleTypevars]
25+
# revealed: ty_extensions.GenericContext[T@MultipleTypevars, S@MultipleTypevars]
2626
reveal_type(generic_context(MultipleTypevars))
2727

2828
# TODO: support `ParamSpec`/`TypeVarTuple` properly
2929
# (these should include the `ParamSpec`s and `TypeVarTuple`s in their generic contexts)
30-
reveal_type(generic_context(SingleParamSpec)) # revealed: tuple[()]
31-
reveal_type(generic_context(TypeVarAndParamSpec)) # revealed: tuple[T@TypeVarAndParamSpec]
32-
reveal_type(generic_context(SingleTypeVarTuple)) # revealed: tuple[()]
33-
reveal_type(generic_context(TypeVarAndTypeVarTuple)) # revealed: tuple[T@TypeVarAndTypeVarTuple]
30+
# revealed: ty_extensions.GenericContext[]
31+
reveal_type(generic_context(SingleParamSpec))
32+
# revealed: ty_extensions.GenericContext[T@TypeVarAndParamSpec]
33+
reveal_type(generic_context(TypeVarAndParamSpec))
34+
# revealed: ty_extensions.GenericContext[]
35+
reveal_type(generic_context(SingleTypeVarTuple))
36+
# revealed: ty_extensions.GenericContext[T@TypeVarAndTypeVarTuple]
37+
reveal_type(generic_context(TypeVarAndTypeVarTuple))
3438
```
3539

3640
You cannot use the same typevar more than once.

crates/ty_python_semantic/resources/mdtest/generics/pep695/classes.md

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,21 @@ class TypeVarAndParamSpec[T, **P]: ...
2020
class SingleTypeVarTuple[*Ts]: ...
2121
class TypeVarAndTypeVarTuple[T, *Ts]: ...
2222

23-
# revealed: tuple[T@SingleTypevar]
23+
# revealed: ty_extensions.GenericContext[T@SingleTypevar]
2424
reveal_type(generic_context(SingleTypevar))
25-
# revealed: tuple[T@MultipleTypevars, S@MultipleTypevars]
25+
# revealed: ty_extensions.GenericContext[T@MultipleTypevars, S@MultipleTypevars]
2626
reveal_type(generic_context(MultipleTypevars))
2727

2828
# TODO: support `ParamSpec`/`TypeVarTuple` properly
2929
# (these should include the `ParamSpec`s and `TypeVarTuple`s in their generic contexts)
30-
reveal_type(generic_context(SingleParamSpec)) # revealed: tuple[()]
31-
reveal_type(generic_context(TypeVarAndParamSpec)) # revealed: tuple[T@TypeVarAndParamSpec]
32-
reveal_type(generic_context(SingleTypeVarTuple)) # revealed: tuple[()]
33-
reveal_type(generic_context(TypeVarAndTypeVarTuple)) # revealed: tuple[T@TypeVarAndTypeVarTuple]
30+
# revealed: ty_extensions.GenericContext[]
31+
reveal_type(generic_context(SingleParamSpec))
32+
# revealed: ty_extensions.GenericContext[T@TypeVarAndParamSpec]
33+
reveal_type(generic_context(TypeVarAndParamSpec))
34+
# revealed: ty_extensions.GenericContext[]
35+
reveal_type(generic_context(SingleTypeVarTuple))
36+
# revealed: ty_extensions.GenericContext[T@TypeVarAndTypeVarTuple]
37+
reveal_type(generic_context(TypeVarAndTypeVarTuple))
3438
```
3539

3640
You cannot use the same typevar more than once.
@@ -49,9 +53,9 @@ class InheritedGeneric[U, V](MultipleTypevars[U, V]): ...
4953
class InheritedGenericPartiallySpecialized[U](MultipleTypevars[U, int]): ...
5054
class InheritedGenericFullySpecialized(MultipleTypevars[str, int]): ...
5155

52-
# revealed: tuple[U@InheritedGeneric, V@InheritedGeneric]
56+
# revealed: ty_extensions.GenericContext[U@InheritedGeneric, V@InheritedGeneric]
5357
reveal_type(generic_context(InheritedGeneric))
54-
# revealed: tuple[U@InheritedGenericPartiallySpecialized]
58+
# revealed: ty_extensions.GenericContext[U@InheritedGenericPartiallySpecialized]
5559
reveal_type(generic_context(InheritedGenericPartiallySpecialized))
5660
# revealed: None
5761
reveal_type(generic_context(InheritedGenericFullySpecialized))
@@ -64,7 +68,8 @@ the inheriting class generic.
6468
```py
6569
class InheritedGenericDefaultSpecialization(MultipleTypevars): ...
6670

67-
reveal_type(generic_context(InheritedGenericDefaultSpecialization)) # revealed: None
71+
# revealed: None
72+
reveal_type(generic_context(InheritedGenericDefaultSpecialization))
6873
```
6974

7075
You cannot use PEP-695 syntax and the legacy syntax in the same class definition.
@@ -512,18 +517,27 @@ class C[T]:
512517
# TODO: error
513518
def cannot_shadow_class_typevar[T](self, t: T): ...
514519

515-
reveal_type(generic_context(C)) # revealed: tuple[T@C]
516-
reveal_type(generic_context(C.method)) # revealed: tuple[Self@method]
517-
reveal_type(generic_context(C.generic_method)) # revealed: tuple[Self@generic_method, U@generic_method]
518-
reveal_type(generic_context(C[int])) # revealed: None
519-
reveal_type(generic_context(C[int].method)) # revealed: tuple[Self@method]
520-
reveal_type(generic_context(C[int].generic_method)) # revealed: tuple[Self@generic_method, U@generic_method]
520+
# revealed: ty_extensions.GenericContext[T@C]
521+
reveal_type(generic_context(C))
522+
# revealed: ty_extensions.GenericContext[Self@method]
523+
reveal_type(generic_context(C.method))
524+
# revealed: ty_extensions.GenericContext[Self@generic_method, U@generic_method]
525+
reveal_type(generic_context(C.generic_method))
526+
# revealed: None
527+
reveal_type(generic_context(C[int]))
528+
# revealed: ty_extensions.GenericContext[Self@method]
529+
reveal_type(generic_context(C[int].method))
530+
# revealed: ty_extensions.GenericContext[Self@generic_method, U@generic_method]
531+
reveal_type(generic_context(C[int].generic_method))
521532

522533
c: C[int] = C[int]()
523534
reveal_type(c.generic_method(1, "string")) # revealed: Literal["string"]
524-
reveal_type(generic_context(c)) # revealed: None
525-
reveal_type(generic_context(c.method)) # revealed: tuple[Self@method]
526-
reveal_type(generic_context(c.generic_method)) # revealed: tuple[Self@generic_method, U@generic_method]
535+
# revealed: None
536+
reveal_type(generic_context(c))
537+
# revealed: ty_extensions.GenericContext[Self@method]
538+
reveal_type(generic_context(c.method))
539+
# revealed: ty_extensions.GenericContext[Self@generic_method, U@generic_method]
540+
reveal_type(generic_context(c.generic_method))
527541
```
528542

529543
## Specializations propagate

crates/ty_python_semantic/resources/mdtest/generics/scoping.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,10 @@ from ty_extensions import generic_context
154154

155155
legacy.m("string", None) # error: [invalid-argument-type]
156156
reveal_type(legacy.m) # revealed: bound method Legacy[int].m[S](x: int, y: S@m) -> S@m
157-
reveal_type(generic_context(Legacy)) # revealed: tuple[T@Legacy]
158-
reveal_type(generic_context(legacy.m)) # revealed: tuple[Self@m, S@m]
157+
# revealed: ty_extensions.GenericContext[T@Legacy]
158+
reveal_type(generic_context(Legacy))
159+
# revealed: ty_extensions.GenericContext[Self@m, S@m]
160+
reveal_type(generic_context(legacy.m))
159161
```
160162

161163
With PEP 695 syntax, it is clearer that the method uses a separate typevar:

crates/ty_python_semantic/src/types.rs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6595,6 +6595,10 @@ impl<'db> Type<'db> {
65956595
invalid_expressions: smallvec::smallvec![InvalidTypeExpression::ConstraintSet],
65966596
fallback_type: Type::unknown(),
65976597
}),
6598+
KnownInstanceType::GenericContext(__call__) => Err(InvalidTypeExpressionError {
6599+
invalid_expressions: smallvec::smallvec![InvalidTypeExpression::GenericContext],
6600+
fallback_type: Type::unknown(),
6601+
}),
65986602
KnownInstanceType::SubscriptedProtocol(_) => Err(InvalidTypeExpressionError {
65996603
invalid_expressions: smallvec::smallvec_inline![
66006604
InvalidTypeExpression::Protocol
@@ -7852,6 +7856,10 @@ pub enum KnownInstanceType<'db> {
78527856
/// `ty_extensions.ConstraintSet`.
78537857
ConstraintSet(TrackedConstraintSet<'db>),
78547858

7859+
/// A generic context, which is exposed in mdtests as an instance of
7860+
/// `ty_extensions.GenericContext`.
7861+
GenericContext(GenericContext<'db>),
7862+
78557863
/// A single instance of `types.UnionType`, which stores the left- and
78567864
/// right-hand sides of a PEP 604 union.
78577865
UnionType(InternedTypes<'db>),
@@ -7883,7 +7891,9 @@ fn walk_known_instance_type<'db, V: visitor::TypeVisitor<'db> + ?Sized>(
78837891
KnownInstanceType::TypeAliasType(type_alias) => {
78847892
visitor.visit_type_alias_type(db, type_alias);
78857893
}
7886-
KnownInstanceType::Deprecated(_) | KnownInstanceType::ConstraintSet(_) => {
7894+
KnownInstanceType::Deprecated(_)
7895+
| KnownInstanceType::ConstraintSet(_)
7896+
| KnownInstanceType::GenericContext(_) => {
78877897
// Nothing to visit
78887898
}
78897899
KnownInstanceType::Field(field) => {
@@ -7931,22 +7941,18 @@ impl<'db> KnownInstanceType<'db> {
79317941
Self::TypeAliasType(type_alias) => {
79327942
Self::TypeAliasType(type_alias.normalized_impl(db, visitor))
79337943
}
7934-
Self::Deprecated(deprecated) => {
7935-
// Nothing to normalize
7936-
Self::Deprecated(deprecated)
7937-
}
79387944
Self::Field(field) => Self::Field(field.normalized_impl(db, visitor)),
7939-
Self::ConstraintSet(set) => {
7940-
// Nothing to normalize
7941-
Self::ConstraintSet(set)
7942-
}
79437945
Self::UnionType(list) => Self::UnionType(list.normalized_impl(db, visitor)),
79447946
Self::Literal(ty) => Self::Literal(ty.normalized_impl(db, visitor)),
79457947
Self::Annotated(ty) => Self::Annotated(ty.normalized_impl(db, visitor)),
79467948
Self::NewType(newtype) => Self::NewType(
79477949
newtype
79487950
.map_base_class_type(db, |class_type| class_type.normalized_impl(db, visitor)),
79497951
),
7952+
Self::Deprecated(_) | Self::ConstraintSet(_) | Self::GenericContext(_) => {
7953+
// Nothing to normalize
7954+
self
7955+
}
79507956
}
79517957
}
79527958

@@ -7964,6 +7970,7 @@ impl<'db> KnownInstanceType<'db> {
79647970
Self::Deprecated(_) => KnownClass::Deprecated,
79657971
Self::Field(_) => KnownClass::Field,
79667972
Self::ConstraintSet(_) => KnownClass::ConstraintSet,
7973+
Self::GenericContext(_) => KnownClass::GenericContext,
79677974
Self::UnionType(_) => KnownClass::UnionType,
79687975
Self::Literal(_) => KnownClass::GenericAlias,
79697976
Self::Annotated(_) => KnownClass::GenericAlias,
@@ -8047,6 +8054,13 @@ impl<'db> KnownInstanceType<'db> {
80478054
constraints.display(self.db)
80488055
)
80498056
}
8057+
KnownInstanceType::GenericContext(generic_context) => {
8058+
write!(
8059+
f,
8060+
"ty_extensions.GenericContext{}",
8061+
generic_context.display_full(self.db)
8062+
)
8063+
}
80508064
KnownInstanceType::UnionType(_) => f.write_str("types.UnionType"),
80518065
KnownInstanceType::Literal(_) => f.write_str("<typing.Literal special form>"),
80528066
KnownInstanceType::Annotated(_) => {
@@ -8290,6 +8304,8 @@ enum InvalidTypeExpression<'db> {
82908304
Field,
82918305
/// Same for `ty_extensions.ConstraintSet`
82928306
ConstraintSet,
8307+
/// Same for `ty_extensions.GenericContext`
8308+
GenericContext,
82938309
/// Same for `typing.TypedDict`
82948310
TypedDict,
82958311
/// Type qualifiers are always invalid in *type expressions*,
@@ -8342,6 +8358,9 @@ impl<'db> InvalidTypeExpression<'db> {
83428358
InvalidTypeExpression::ConstraintSet => {
83438359
f.write_str("`ty_extensions.ConstraintSet` is not allowed in type expressions")
83448360
}
8361+
InvalidTypeExpression::GenericContext => {
8362+
f.write_str("`ty_extensions.GenericContext` is not allowed in type expressions")
8363+
}
83458364
InvalidTypeExpression::TypedDict => {
83468365
f.write_str(
83478366
"The special form `typing.TypedDict` is not allowed in type expressions. \

crates/ty_python_semantic/src/types/call/bind.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,12 @@ impl<'db> Bindings<'db> {
757757

758758
Some(KnownFunction::GenericContext) => {
759759
if let [Some(ty)] = overload.parameter_types() {
760+
let wrap_generic_context = |generic_context| {
761+
Type::KnownInstance(KnownInstanceType::GenericContext(
762+
generic_context,
763+
))
764+
};
765+
760766
let function_generic_context = |function: FunctionType<'db>| {
761767
let union = UnionType::from_elements(
762768
db,
@@ -765,7 +771,7 @@ impl<'db> Bindings<'db> {
765771
.overloads
766772
.iter()
767773
.filter_map(|signature| signature.generic_context)
768-
.map(|generic_context| generic_context.as_tuple(db)),
774+
.map(wrap_generic_context),
769775
);
770776
if union.is_never() {
771777
Type::none(db)
@@ -779,7 +785,7 @@ impl<'db> Bindings<'db> {
779785
overload.set_return_type(match ty {
780786
Type::ClassLiteral(class) => class
781787
.generic_context(db)
782-
.map(|generic_context| generic_context.as_tuple(db))
788+
.map(wrap_generic_context)
783789
.unwrap_or_else(|| Type::none(db)),
784790

785791
Type::FunctionLiteral(function) => {
@@ -794,7 +800,7 @@ impl<'db> Bindings<'db> {
794800
TypeAliasType::PEP695(alias),
795801
)) => alias
796802
.generic_context(db)
797-
.map(|generic_context| generic_context.as_tuple(db))
803+
.map(wrap_generic_context)
798804
.unwrap_or_else(|| Type::none(db)),
799805

800806
_ => Type::none(db),

0 commit comments

Comments
 (0)