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:

View file

@ -6712,6 +6712,10 @@ impl<'db> Type<'db> {
invalid_expressions: smallvec::smallvec![InvalidTypeExpression::ConstraintSet],
fallback_type: Type::unknown(),
}),
KnownInstanceType::GenericContext(__call__) => Err(InvalidTypeExpressionError {
invalid_expressions: smallvec::smallvec![InvalidTypeExpression::GenericContext],
fallback_type: Type::unknown(),
}),
KnownInstanceType::SubscriptedProtocol(_) => Err(InvalidTypeExpressionError {
invalid_expressions: smallvec::smallvec_inline![
InvalidTypeExpression::Protocol
@ -7977,6 +7981,10 @@ pub enum KnownInstanceType<'db> {
/// `ty_extensions.ConstraintSet`.
ConstraintSet(TrackedConstraintSet<'db>),
/// A generic context, which is exposed in mdtests as an instance of
/// `ty_extensions.GenericContext`.
GenericContext(GenericContext<'db>),
/// A single instance of `types.UnionType`, which stores the left- and
/// right-hand sides of a PEP 604 union.
UnionType(InternedTypes<'db>),
@ -8011,7 +8019,9 @@ fn walk_known_instance_type<'db, V: visitor::TypeVisitor<'db> + ?Sized>(
KnownInstanceType::TypeAliasType(type_alias) => {
visitor.visit_type_alias_type(db, type_alias);
}
KnownInstanceType::Deprecated(_) | KnownInstanceType::ConstraintSet(_) => {
KnownInstanceType::Deprecated(_)
| KnownInstanceType::ConstraintSet(_)
| KnownInstanceType::GenericContext(_) => {
// Nothing to visit
}
KnownInstanceType::Field(field) => {
@ -8061,15 +8071,7 @@ impl<'db> KnownInstanceType<'db> {
Self::TypeAliasType(type_alias) => {
Self::TypeAliasType(type_alias.normalized_impl(db, visitor))
}
Self::Deprecated(deprecated) => {
// Nothing to normalize
Self::Deprecated(deprecated)
}
Self::Field(field) => Self::Field(field.normalized_impl(db, visitor)),
Self::ConstraintSet(set) => {
// Nothing to normalize
Self::ConstraintSet(set)
}
Self::UnionType(list) => Self::UnionType(list.normalized_impl(db, visitor)),
Self::Literal(ty) => Self::Literal(ty.normalized_impl(db, visitor)),
Self::Annotated(ty) => Self::Annotated(ty.normalized_impl(db, visitor)),
@ -8078,6 +8080,10 @@ impl<'db> KnownInstanceType<'db> {
newtype
.map_base_class_type(db, |class_type| class_type.normalized_impl(db, visitor)),
),
Self::Deprecated(_) | Self::ConstraintSet(_) | Self::GenericContext(_) => {
// Nothing to normalize
self
}
}
}
@ -8095,6 +8101,7 @@ impl<'db> KnownInstanceType<'db> {
Self::Deprecated(_) => KnownClass::Deprecated,
Self::Field(_) => KnownClass::Field,
Self::ConstraintSet(_) => KnownClass::ConstraintSet,
Self::GenericContext(_) => KnownClass::GenericContext,
Self::UnionType(_) => KnownClass::UnionType,
Self::Literal(_) | Self::Annotated(_) | Self::TypeGenericAlias(_) => {
KnownClass::GenericAlias
@ -8179,6 +8186,13 @@ impl<'db> KnownInstanceType<'db> {
constraints.display(self.db)
)
}
KnownInstanceType::GenericContext(generic_context) => {
write!(
f,
"ty_extensions.GenericContext{}",
generic_context.display_full(self.db)
)
}
KnownInstanceType::UnionType(_) => f.write_str("types.UnionType"),
KnownInstanceType::Literal(_) => f.write_str("<typing.Literal special form>"),
KnownInstanceType::Annotated(_) => {
@ -8423,6 +8437,8 @@ enum InvalidTypeExpression<'db> {
Field,
/// Same for `ty_extensions.ConstraintSet`
ConstraintSet,
/// Same for `ty_extensions.GenericContext`
GenericContext,
/// Same for `typing.TypedDict`
TypedDict,
/// Type qualifiers are always invalid in *type expressions*,
@ -8475,6 +8491,9 @@ impl<'db> InvalidTypeExpression<'db> {
InvalidTypeExpression::ConstraintSet => {
f.write_str("`ty_extensions.ConstraintSet` is not allowed in type expressions")
}
InvalidTypeExpression::GenericContext => {
f.write_str("`ty_extensions.GenericContext` is not allowed in type expressions")
}
InvalidTypeExpression::TypedDict => {
f.write_str(
"The special form `typing.TypedDict` is not allowed in type expressions. \

View file

@ -782,6 +782,12 @@ impl<'db> Bindings<'db> {
Some(KnownFunction::GenericContext) => {
if let [Some(ty)] = overload.parameter_types() {
let wrap_generic_context = |generic_context| {
Type::KnownInstance(KnownInstanceType::GenericContext(
generic_context,
))
};
let function_generic_context = |function: FunctionType<'db>| {
let union = UnionType::from_elements(
db,
@ -790,7 +796,7 @@ impl<'db> Bindings<'db> {
.overloads
.iter()
.filter_map(|signature| signature.generic_context)
.map(|generic_context| generic_context.as_tuple(db)),
.map(wrap_generic_context),
);
if union.is_never() {
Type::none(db)
@ -804,7 +810,7 @@ impl<'db> Bindings<'db> {
overload.set_return_type(match ty {
Type::ClassLiteral(class) => class
.generic_context(db)
.map(|generic_context| generic_context.as_tuple(db))
.map(wrap_generic_context)
.unwrap_or_else(|| Type::none(db)),
Type::FunctionLiteral(function) => {
@ -819,7 +825,7 @@ impl<'db> Bindings<'db> {
TypeAliasType::PEP695(alias),
)) => alias
.generic_context(db)
.map(|generic_context| generic_context.as_tuple(db))
.map(wrap_generic_context)
.unwrap_or_else(|| Type::none(db)),
_ => Type::none(db),

View file

@ -3956,6 +3956,7 @@ pub enum KnownClass {
Path,
// ty_extensions
ConstraintSet,
GenericContext,
}
impl KnownClass {
@ -4059,6 +4060,7 @@ impl KnownClass {
| Self::NamedTupleFallback
| Self::NamedTupleLike
| Self::ConstraintSet
| Self::GenericContext
| Self::ProtocolMeta
| Self::TypedDictFallback => Some(Truthiness::Ambiguous),
@ -4142,6 +4144,7 @@ impl KnownClass {
| KnownClass::NamedTupleFallback
| KnownClass::NamedTupleLike
| KnownClass::ConstraintSet
| KnownClass::GenericContext
| KnownClass::TypedDictFallback
| KnownClass::BuiltinFunctionType
| KnownClass::ProtocolMeta
@ -4225,6 +4228,7 @@ impl KnownClass {
| KnownClass::NamedTupleFallback
| KnownClass::NamedTupleLike
| KnownClass::ConstraintSet
| KnownClass::GenericContext
| KnownClass::TypedDictFallback
| KnownClass::BuiltinFunctionType
| KnownClass::ProtocolMeta
@ -4308,6 +4312,7 @@ impl KnownClass {
| KnownClass::NamedTupleLike
| KnownClass::NamedTupleFallback
| KnownClass::ConstraintSet
| KnownClass::GenericContext
| KnownClass::BuiltinFunctionType
| KnownClass::ProtocolMeta
| KnownClass::Template
@ -4402,6 +4407,7 @@ impl KnownClass {
| Self::InitVar
| Self::NamedTupleFallback
| Self::ConstraintSet
| Self::GenericContext
| Self::TypedDictFallback
| Self::BuiltinFunctionType
| Self::ProtocolMeta
@ -4491,6 +4497,7 @@ impl KnownClass {
| KnownClass::Template
| KnownClass::Path
| KnownClass::ConstraintSet
| KnownClass::GenericContext
| KnownClass::InitVar => false,
KnownClass::NamedTupleFallback | KnownClass::TypedDictFallback => true,
}
@ -4599,6 +4606,7 @@ impl KnownClass {
Self::NamedTupleFallback => "NamedTupleFallback",
Self::NamedTupleLike => "NamedTupleLike",
Self::ConstraintSet => "ConstraintSet",
Self::GenericContext => "GenericContext",
Self::TypedDictFallback => "TypedDictFallback",
Self::Template => "Template",
Self::Path => "Path",
@ -4910,7 +4918,9 @@ impl KnownClass {
| Self::OrderedDict => KnownModule::Collections,
Self::Field | Self::KwOnly | Self::InitVar => KnownModule::Dataclasses,
Self::NamedTupleFallback | Self::TypedDictFallback => KnownModule::TypeCheckerInternals,
Self::NamedTupleLike | Self::ConstraintSet => KnownModule::TyExtensions,
Self::NamedTupleLike | Self::ConstraintSet | Self::GenericContext => {
KnownModule::TyExtensions
}
Self::Template => KnownModule::Templatelib,
Self::Path => KnownModule::Pathlib,
}
@ -4993,6 +5003,7 @@ impl KnownClass {
| Self::NamedTupleFallback
| Self::NamedTupleLike
| Self::ConstraintSet
| Self::GenericContext
| Self::TypedDictFallback
| Self::BuiltinFunctionType
| Self::ProtocolMeta
@ -5081,6 +5092,7 @@ impl KnownClass {
| Self::NamedTupleFallback
| Self::NamedTupleLike
| Self::ConstraintSet
| Self::GenericContext
| Self::TypedDictFallback
| Self::BuiltinFunctionType
| Self::ProtocolMeta
@ -5184,6 +5196,7 @@ impl KnownClass {
"NamedTupleFallback" => &[Self::NamedTupleFallback],
"NamedTupleLike" => &[Self::NamedTupleLike],
"ConstraintSet" => &[Self::ConstraintSet],
"GenericContext" => &[Self::GenericContext],
"TypedDictFallback" => &[Self::TypedDictFallback],
"Template" => &[Self::Template],
"Path" => &[Self::Path],
@ -5261,6 +5274,7 @@ impl KnownClass {
| Self::ExtensionsTypeVar
| Self::NamedTupleLike
| Self::ConstraintSet
| Self::GenericContext
| Self::Awaitable
| Self::Generator
| Self::Template

View file

@ -174,6 +174,7 @@ impl<'db> ClassBase<'db> {
| KnownInstanceType::Deprecated(_)
| KnownInstanceType::Field(_)
| KnownInstanceType::ConstraintSet(_)
| KnownInstanceType::GenericContext(_)
| KnownInstanceType::UnionType(_)
| KnownInstanceType::Literal(_)
// A class inheriting from a newtype would make intuitive sense, but newtype

View file

@ -892,6 +892,16 @@ impl<'db> GenericContext<'db> {
pub fn display(&'db self, db: &'db dyn Db) -> DisplayGenericContext<'db> {
Self::display_with(self, db, DisplaySettings::default())
}
pub fn display_full(&'db self, db: &'db dyn Db) -> DisplayGenericContext<'db> {
DisplayGenericContext {
generic_context: self,
db,
settings: DisplaySettings::default(),
full: true,
}
}
pub fn display_with(
&'db self,
db: &'db dyn Db,
@ -901,6 +911,7 @@ impl<'db> GenericContext<'db> {
generic_context: self,
db,
settings,
full: false,
}
}
}
@ -914,12 +925,9 @@ struct DisplayOptionalGenericContext<'db> {
impl Display for DisplayOptionalGenericContext<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if let Some(generic_context) = self.generic_context {
DisplayGenericContext {
generic_context,
db: self.db,
settings: self.settings.clone(),
}
.fmt(f)
generic_context
.display_with(self.db, self.settings.clone())
.fmt(f)
} else {
Ok(())
}
@ -931,10 +939,11 @@ pub struct DisplayGenericContext<'db> {
db: &'db dyn Db,
#[expect(dead_code)]
settings: DisplaySettings<'db>,
full: bool,
}
impl Display for DisplayGenericContext<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
impl DisplayGenericContext<'_> {
fn fmt_normal(&self, f: &mut Formatter<'_>) -> fmt::Result {
let variables = self.generic_context.variables(self.db);
let non_implicit_variables: Vec<_> = variables
@ -954,6 +963,28 @@ impl Display for DisplayGenericContext<'_> {
}
f.write_char(']')
}
fn fmt_full(&self, f: &mut Formatter<'_>) -> fmt::Result {
let variables = self.generic_context.variables(self.db);
f.write_char('[')?;
for (idx, bound_typevar) in variables.enumerate() {
if idx > 0 {
f.write_str(", ")?;
}
bound_typevar.identity(self.db).display(self.db).fmt(f)?;
}
f.write_char(']')
}
}
impl Display for DisplayGenericContext<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if self.full {
self.fmt_full(f)
} else {
self.fmt_normal(f)
}
}
}
impl<'db> Specialization<'db> {

View file

@ -474,11 +474,6 @@ impl<'db> GenericContext<'db> {
self.specialize(db, types.into())
}
/// Returns a tuple type of the typevars introduced by this generic context.
pub(crate) fn as_tuple(self, db: &'db dyn Db) -> Type<'db> {
Type::heterogeneous_tuple(db, self.variables(db).map(Type::TypeVar))
}
pub(crate) fn is_subset_of(self, db: &'db dyn Db, other: GenericContext<'db>) -> bool {
let other_variables = other.variables_inner(db);
self.variables(db)

View file

@ -783,6 +783,15 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
}
Type::unknown()
}
KnownInstanceType::GenericContext(_) => {
self.infer_type_expression(slice);
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
builder.into_diagnostic(format_args!(
"`ty_extensions.GenericContext` is not allowed in type expressions",
));
}
Type::unknown()
}
KnownInstanceType::TypeVar(_) => {
self.infer_type_expression(slice);
todo_type!("TypeVar annotations")