From 96e7ebb58830cddf5e12ec1130b7e233008c3e40 Mon Sep 17 00:00:00 2001 From: David Peter Date: Wed, 26 Nov 2025 13:24:21 +0100 Subject: [PATCH] New KnownInstanceType --- crates/ty_python_semantic/src/types.rs | 43 +++++++--- crates/ty_python_semantic/src/types/class.rs | 85 +++++++------------ .../src/types/class_base.rs | 5 +- .../src/types/infer/builder.rs | 83 +++++++++++------- .../types/infer/builder/type_expression.rs | 48 +++++------ .../ty_python_semantic/src/types/instance.rs | 4 +- crates/ty_python_semantic/src/types/mro.rs | 19 +++-- crates/ty_python_semantic/src/types/tuple.rs | 45 ++++------ 8 files changed, 163 insertions(+), 169 deletions(-) diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index e3812035fe..9f58f0e9b3 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -906,12 +906,12 @@ impl<'db> Type<'db> { matches!(self, Type::GenericAlias(_)) } - pub(crate) fn as_generic_alias(&self) -> Option> { - match self { - Type::GenericAlias(alias) => Some(*alias), - _ => None, - } - } + // pub(crate) fn as_generic_alias(&self) -> Option> { + // match self { + // Type::GenericAlias(alias) => Some(*alias), + // _ => None, + // } + // } const fn is_dynamic(&self) -> bool { matches!(self, Type::Dynamic(_)) @@ -6599,7 +6599,7 @@ impl<'db> Type<'db> { .map(|specialization| { Type::instance( db, - generic_origin.apply_specialization(db, |_| specialization, None), + generic_origin.apply_specialization(db, |_| specialization), ) }) .unwrap_or(instance_ty); @@ -6824,6 +6824,7 @@ impl<'db> Type<'db> { Ok(ty.to_meta_type(db)) } } + KnownInstanceType::GenericAlias(instance) => Ok(instance.inner(db)), KnownInstanceType::Callable(instance) => { Ok(Type::Callable(instance.callable_type(db))) } @@ -7111,11 +7112,7 @@ impl<'db> Type<'db> { pub(crate) fn dunder_class(self, db: &'db dyn Db) -> Type<'db> { if self.is_typed_dict() { return KnownClass::Dict - .to_specialized_class_type( - db, - [KnownClass::Str.to_instance(db), Type::object()], - None, - ) + .to_specialized_class_type(db, [KnownClass::Str.to_instance(db), Type::object()]) .map(Type::from) // Guard against user-customized typesheds with a broken `dict` class .unwrap_or_else(Type::unknown); @@ -7272,6 +7269,15 @@ impl<'db> Type<'db> { ) )) }, + KnownInstanceType::GenericAlias(instance) => { + Type::KnownInstance(KnownInstanceType::GenericAlias( + TypeInContext::new( + db, + instance.inner(db).apply_type_mapping_impl(db, type_mapping, tcx, visitor), + instance.binding_context(db), + ) + )) + }, KnownInstanceType::Callable(instance) => { Type::KnownInstance(KnownInstanceType::Callable(CallableTypeInstance::new( db, @@ -7617,6 +7623,10 @@ impl<'db> Type<'db> { ty.inner(db) .find_legacy_typevars_impl(db, binding_context, typevars, visitor); } + KnownInstanceType::GenericAlias(ty) => { + ty.inner(db) + .find_legacy_typevars_impl(db, binding_context, typevars, visitor); + } KnownInstanceType::SubscriptedProtocol(_) | KnownInstanceType::SubscriptedGeneric(_) | KnownInstanceType::TypeVar(_) @@ -8205,6 +8215,8 @@ pub enum KnownInstanceType<'db> { /// An instance of `typing.GenericAlias` representing a `type[...]` expression. TypeGenericAlias(TypeInContext<'db>), + GenericAlias(TypeInContext<'db>), + /// An instance of `typing.GenericAlias` representing a `Callable[...]` expression. Callable(CallableTypeInstance<'db>), @@ -8248,7 +8260,9 @@ fn walk_known_instance_type<'db, V: visitor::TypeVisitor<'db> + ?Sized>( visitor.visit_type(db, *union_type); } } - KnownInstanceType::Annotated(instance) | KnownInstanceType::TypeGenericAlias(instance) => { + KnownInstanceType::Annotated(instance) + | KnownInstanceType::TypeGenericAlias(instance) + | KnownInstanceType::GenericAlias(instance) => { visitor.visit_type(db, instance.inner(db)); } KnownInstanceType::Literal(ty) | KnownInstanceType::LiteralStringAlias(ty) => { @@ -8294,6 +8308,7 @@ impl<'db> KnownInstanceType<'db> { Self::Literal(ty) => Self::Literal(ty.normalized_impl(db, visitor)), Self::Annotated(ty) => Self::Annotated(ty.normalized_impl(db, visitor)), Self::TypeGenericAlias(ty) => Self::TypeGenericAlias(ty.normalized_impl(db, visitor)), + Self::GenericAlias(ty) => Self::GenericAlias(ty.normalized_impl(db, visitor)), Self::Callable(callable) => Self::Callable(callable.normalized_impl(db, visitor)), Self::LiteralStringAlias(ty) => { Self::LiteralStringAlias(ty.normalized_impl(db, visitor)) @@ -8332,6 +8347,7 @@ impl<'db> KnownInstanceType<'db> { Self::Literal(_) | Self::Annotated(_) | Self::TypeGenericAlias(_) + | Self::GenericAlias(_) | Self::Callable(_) => KnownClass::GenericAlias, Self::LiteralStringAlias(_) => KnownClass::Str, Self::NewType(_) => KnownClass::NewType, @@ -8437,6 +8453,7 @@ impl<'db> KnownInstanceType<'db> { KnownInstanceType::TypeGenericAlias(_) | KnownInstanceType::Callable(_) => { f.write_str("GenericAlias") } + KnownInstanceType::GenericAlias(_) => f.write_str("GenericAlias(…)"), //TODO KnownInstanceType::LiteralStringAlias(_) => f.write_str("str"), KnownInstanceType::NewType(declaration) => { write!(f, "", declaration.name(self.db)) diff --git a/crates/ty_python_semantic/src/types/class.rs b/crates/ty_python_semantic/src/types/class.rs index 7f7a87caa0..151d329d47 100644 --- a/crates/ty_python_semantic/src/types/class.rs +++ b/crates/ty_python_semantic/src/types/class.rs @@ -103,7 +103,7 @@ fn try_mro_cycle_initial<'db>( ) -> Result, MroError<'db>> { Err(MroError::cycle( db, - self_.apply_optional_specialization(db, specialization, None), + self_.apply_optional_specialization(db, specialization), )) } @@ -233,8 +233,6 @@ impl<'db> CodeGeneratorKind<'db> { pub struct GenericAlias<'db> { pub(crate) origin: ClassLiteral<'db>, pub(crate) specialization: Specialization<'db>, - - pub(crate) binding_context: Option>, } pub(super) fn walk_generic_alias<'db, V: super::visitor::TypeVisitor<'db> + ?Sized>( @@ -254,7 +252,6 @@ impl<'db> GenericAlias<'db> { db, self.origin(db), self.specialization(db).normalized_impl(db, visitor), - self.binding_context(db), ) } @@ -280,7 +277,6 @@ impl<'db> GenericAlias<'db> { self.origin(db), self.specialization(db) .apply_type_mapping_impl(db, type_mapping, tcx, visitor), - self.binding_context(db), ) } @@ -1533,7 +1529,6 @@ impl<'db> ClassLiteral<'db> { self, db: &'db dyn Db, f: impl FnOnce(GenericContext<'db>) -> Specialization<'db>, - binding_context: Option>, ) -> ClassType<'db> { match self.generic_context(db) { None => ClassType::NonGeneric(self), @@ -1550,7 +1545,7 @@ impl<'db> ClassLiteral<'db> { } } - ClassType::Generic(GenericAlias::new(db, self, specialization, binding_context)) + ClassType::Generic(GenericAlias::new(db, self, specialization)) } } } @@ -1559,63 +1554,48 @@ impl<'db> ClassLiteral<'db> { self, db: &'db dyn Db, specialization: Option>, - binding_context: Option>, ) -> ClassType<'db> { - self.apply_specialization( - db, - |generic_context| { - specialization - .unwrap_or_else(|| generic_context.default_specialization(db, self.known(db))) - }, - binding_context, - ) + self.apply_specialization(db, |generic_context| { + specialization + .unwrap_or_else(|| generic_context.default_specialization(db, self.known(db))) + }) } pub(crate) fn top_materialization(self, db: &'db dyn Db) -> ClassType<'db> { - self.apply_specialization( - db, - |generic_context| { - generic_context - .default_specialization(db, self.known(db)) - .materialize_impl( - db, - MaterializationKind::Top, - &ApplyTypeMappingVisitor::default(), - ) - }, - None, - ) + self.apply_specialization(db, |generic_context| { + generic_context + .default_specialization(db, self.known(db)) + .materialize_impl( + db, + MaterializationKind::Top, + &ApplyTypeMappingVisitor::default(), + ) + }) } /// Returns the default specialization of this class. For non-generic classes, the class is /// returned unchanged. For a non-specialized generic class, we return a generic alias that /// applies the default specialization to the class's typevars. pub(crate) fn default_specialization(self, db: &'db dyn Db) -> ClassType<'db> { - self.apply_specialization( - db, - |generic_context| generic_context.default_specialization(db, self.known(db)), - None, - ) + self.apply_specialization(db, |generic_context| { + generic_context.default_specialization(db, self.known(db)) + }) } /// Returns the unknown specialization of this class. For non-generic classes, the class is /// returned unchanged. For a non-specialized generic class, we return a generic alias that /// maps each of the class's typevars to `Unknown`. pub(crate) fn unknown_specialization(self, db: &'db dyn Db) -> ClassType<'db> { - self.apply_specialization( - db, - |generic_context| generic_context.unknown_specialization(db), - None, - ) + self.apply_specialization(db, |generic_context| { + generic_context.unknown_specialization(db) + }) } /// Returns a specialization of this class where each typevar is mapped to itself. pub(crate) fn identity_specialization(self, db: &'db dyn Db) -> ClassType<'db> { - self.apply_specialization( - db, - |generic_context| generic_context.identity_specialization(db), - None, - ) + self.apply_specialization(db, |generic_context| { + generic_context.identity_specialization(db) + }) } /// Return an iterator over the inferred types of this class's *explicit* bases. @@ -1646,7 +1626,7 @@ impl<'db> ClassLiteral<'db> { Box::new([ definition_expression_type(db, class_definition, &class_stmt.bases()[0]), - Type::from(tuple_type.to_class_type(db, None)), + Type::from(tuple_type.to_class_type(db)), ]) } else { class_stmt @@ -2291,10 +2271,8 @@ impl<'db> ClassLiteral<'db> { || transformer_params.is_some_and(|params| params.flags(db).contains(param)) }; - let instance_ty = Type::instance( - db, - self.apply_optional_specialization(db, specialization, None), - ); + let instance_ty = + Type::instance(db, self.apply_optional_specialization(db, specialization)); let signature_from_fields = |mut parameters: Vec<_>, return_ty: Option>| { for (field_name, field) in self.fields(db, specialization, field_policy) { @@ -4809,7 +4787,6 @@ impl KnownClass { self, db: &'db dyn Db, specialization: impl IntoIterator>, - binding_context: Option>, ) -> Option> { let Type::ClassLiteral(class_literal) = self.to_class_literal(db) else { return None; @@ -4831,11 +4808,7 @@ impl KnownClass { return Some(class_literal.default_specialization(db)); } - Some(class_literal.apply_specialization( - db, - |_| generic_context.specialize(db, types), - binding_context, - )) + Some(class_literal.apply_specialization(db, |_| generic_context.specialize(db, types))) } /// Lookup a [`KnownClass`] in typeshed and return a [`Type`] @@ -4854,7 +4827,7 @@ impl KnownClass { KnownClass::Tuple, "Use `Type::heterogeneous_tuple` or `Type::homogeneous_tuple` to create `tuple` instances" ); - self.to_specialized_class_type(db, specialization, None) + self.to_specialized_class_type(db, specialization) .and_then(|class_type| Type::from(class_type).to_instance(db)) .unwrap_or_else(Type::unknown) } diff --git a/crates/ty_python_semantic/src/types/class_base.rs b/crates/ty_python_semantic/src/types/class_base.rs index e392df287f..831809e081 100644 --- a/crates/ty_python_semantic/src/types/class_base.rs +++ b/crates/ty_python_semantic/src/types/class_base.rs @@ -185,6 +185,9 @@ impl<'db> ClassBase<'db> { KnownInstanceType::TypeGenericAlias(_) => { Self::try_from_type(db, KnownClass::Type.to_class_literal(db), subclass) } + KnownInstanceType::GenericAlias(instance) => { + Self::try_from_type(db, instance.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 @@ -239,7 +242,7 @@ impl<'db> ClassBase<'db> { db, fields.values().map(|field| field.declared_ty), )? - .to_class_type(db, None) + .to_class_type(db) .into(), subclass, ) diff --git a/crates/ty_python_semantic/src/types/infer/builder.rs b/crates/ty_python_semantic/src/types/infer/builder.rs index c36a797ae8..9b64bf0a29 100644 --- a/crates/ty_python_semantic/src/types/infer/builder.rs +++ b/crates/ty_python_semantic/src/types/infer/builder.rs @@ -7500,7 +7500,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { } let class_type = - class_literal.apply_specialization(self.db(), |_| builder.build(generic_context), None); + class_literal.apply_specialization(self.db(), |_| builder.build(generic_context)); Type::from(class_type).to_instance(self.db()) } @@ -10813,18 +10813,48 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { // If we have an implicit type alias like `MyList = list[T]`, and if `MyList` is being // used in another implicit type alias like `Numbers = MyList[int]`, then we infer the // right hand side as a value expression, and need to handle the specialization here. - if let Some(alias) = value_ty.as_generic_alias() { - let return_ty = self.infer_explicitly_specialized_type_alias( - subscript, - value_ty, - alias.binding_context(self.db()), - false, - ); - - return return_ty; + if let Type::KnownInstance(KnownInstanceType::GenericAlias(alias)) = value_ty { + return Type::KnownInstance(KnownInstanceType::GenericAlias(TypeInContext::new( + self.db(), + self.infer_explicitly_specialized_type_alias( + subscript, + value_ty, + alias.binding_context(self.db()), + false, + ), + self.typevar_binding_context, + ))); } - self.infer_subscript_load_impl(value_ty, subscript) + // if let Type::GenericAlias(alias) = value_ty { + // return Type::KnownInstance(KnownInstanceType::GenericAlias(TypeInContext::new( + // self.db(), + // self.infer_explicitly_specialized_type_alias( + // subscript, + // value_ty, + // Some(alias.definition(self.db())), + // false, + // ), + // self.typevar_binding_context, + // ))); + // } + + let result_ty = self.infer_subscript_load_impl(value_ty, subscript); + + // let result_ty = if result_ty.is_generic_alias() { + // Type::KnownInstance(KnownInstanceType::GenericAlias(TypeInContext::new( + // self.db(), + // result_ty, + // self.typevar_binding_context, + // ))) + // } else { + // result_ty + // }; + + // eprintln!("Subscripting type: {}", value_ty.display(self.db())); + // eprintln!("Inferred subscript type: {}", result_ty.display(self.db())); + + result_ty } fn infer_subscript_load_impl( @@ -10860,11 +10890,9 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { } } - let db = self.db(); - let typevar_binding_context = self.typevar_binding_context; - let tuple_generic_alias = |tuple: Option>| { + let tuple_generic_alias = |db: &'db dyn Db, tuple: Option>| { let tuple = tuple.unwrap_or_else(|| TupleType::homogeneous(db, Type::unknown())); - Type::from(tuple.to_class_type(db, typevar_binding_context)) + Type::from(tuple.to_class_type(db)) }; match value_ty { @@ -10876,7 +10904,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { // updating all of the subscript logic below to use custom callables for all of the _other_ // special cases, too. if class.is_tuple(self.db()) { - return tuple_generic_alias(self.infer_tuple_type_expression(slice)); + return tuple_generic_alias(self.db(), self.infer_tuple_type_expression(slice)); } else if class.is_known(self.db(), KnownClass::Type) { let argument_ty = self.infer_type_expression(slice); return Type::KnownInstance(KnownInstanceType::TypeGenericAlias( @@ -10904,7 +10932,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { } } Type::SpecialForm(SpecialFormType::Tuple) => { - return tuple_generic_alias(self.infer_tuple_type_expression(slice)); + return tuple_generic_alias(self.db(), self.infer_tuple_type_expression(slice)); } Type::SpecialForm(SpecialFormType::Literal) => { match self.infer_literal_parameter_type(slice) { @@ -11070,11 +11098,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { .expect("A known stdlib class is available"); return class - .to_specialized_class_type( - self.db(), - [element_ty], - self.typevar_binding_context, - ) + .to_specialized_class_type(self.db(), [element_ty]) .map(Type::from) .unwrap_or_else(Type::unknown); } @@ -11132,11 +11156,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { .expect("Stdlib class available"); return class - .to_specialized_class_type( - self.db(), - [first_ty, second_ty], - self.typevar_binding_context, - ) + .to_specialized_class_type(self.db(), [first_ty, second_ty]) .map(Type::from) .unwrap_or_else(Type::unknown); } @@ -11183,13 +11203,10 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { generic_context: GenericContext<'db>, ) -> Type<'db> { let db = self.db(); - let typevar_binding_context = self.typevar_binding_context; let specialize = |types: &[Option>]| { - Type::from(generic_class.apply_specialization( - db, - |_| generic_context.specialize_partial(db, types.iter().copied()), - typevar_binding_context, - )) + Type::from(generic_class.apply_specialization(db, |_| { + generic_context.specialize_partial(db, types.iter().copied()) + })) }; self.infer_explicit_callable_specialization( diff --git a/crates/ty_python_semantic/src/types/infer/builder/type_expression.rs b/crates/ty_python_semantic/src/types/infer/builder/type_expression.rs index 8801217759..e56c375fc6 100644 --- a/crates/ty_python_semantic/src/types/infer/builder/type_expression.rs +++ b/crates/ty_python_semantic/src/types/infer/builder/type_expression.rs @@ -13,10 +13,10 @@ use crate::types::string_annotation::parse_string_annotation; use crate::types::tuple::{TupleSpecBuilder, TupleType}; use crate::types::visitor::any_over_type; use crate::types::{ - BindingContext, CallableType, DynamicType, GenericAlias, GenericContext, IntersectionBuilder, - KnownClass, KnownInstanceType, LintDiagnosticGuard, Parameter, Parameters, SpecialFormType, - SubclassOfType, Type, TypeAliasType, TypeContext, TypeInContext, TypeIsType, TypeMapping, - UnionBuilder, UnionType, todo_type, + BindingContext, CallableType, DynamicType, GenericContext, IntersectionBuilder, KnownClass, + KnownInstanceType, LintDiagnosticGuard, Parameter, Parameters, SpecialFormType, SubclassOfType, + Type, TypeAliasType, TypeContext, TypeInContext, TypeIsType, TypeMapping, UnionBuilder, + UnionType, todo_type, }; /// Type expressions @@ -713,20 +713,13 @@ impl<'db> TypeInferenceBuilder<'db, '_> { match class_literal.generic_context(self.db()) { Some(generic_context) => { let db = self.db(); - let typevar_binding_context = self.typevar_binding_context; let specialize = |types: &[Option>]| { SubclassOfType::from( db, - class_literal.apply_specialization( - db, - |_| { - generic_context.specialize_partial( - db, - types.iter().copied(), - ) - }, - typevar_binding_context, - ), + class_literal.apply_specialization(db, |_| { + generic_context + .specialize_partial(db, types.iter().copied()) + }), ) }; self.infer_explicit_callable_specialization( @@ -810,12 +803,12 @@ impl<'db> TypeInferenceBuilder<'db, '_> { } else { // Update the binding context match specialized { - Type::GenericAlias(alias) => Type::GenericAlias(GenericAlias::new( - db, - alias.origin(db), - alias.specialization(db), - current_typevar_binding_context, - )), + // Type::GenericAlias(alias) => Type::GenericAlias(GenericAlias::new( + // db, + // alias.origin(db), + // alias.specialization(db), + // current_typevar_binding_context, + // )), Type::KnownInstance(KnownInstanceType::TypeGenericAlias(instance)) => { Type::KnownInstance(KnownInstanceType::TypeGenericAlias( TypeInContext::new( @@ -995,7 +988,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { true, ), KnownInstanceType::Annotated(instance) - | KnownInstanceType::TypeGenericAlias(instance) => self + | KnownInstanceType::TypeGenericAlias(instance) + | KnownInstanceType::GenericAlias(instance) => self .infer_explicitly_specialized_type_alias( subscript, value_ty, @@ -1049,12 +1043,9 @@ impl<'db> TypeInferenceBuilder<'db, '_> { } } } - Type::GenericAlias(alias) => self.infer_explicitly_specialized_type_alias( - subscript, - value_ty, - alias.binding_context(self.db()), - true, - ), + // Type::GenericAlias(alias) => { + // self.infer_explicitly_specialized_type_alias(subscript, value_ty, None, true) + // } Type::StringLiteral(_) => { self.infer_type_expression(slice); // For stringified TypeAlias; remove once properly supported @@ -1063,6 +1054,7 @@ impl<'db> TypeInferenceBuilder<'db, '_> { _ => { self.infer_type_expression(slice); if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) { + dbg!(&value_ty); builder.into_diagnostic(format_args!( "Invalid subscript of object of type `{}` in type expression", value_ty.display(self.db()) diff --git a/crates/ty_python_semantic/src/types/instance.rs b/crates/ty_python_semantic/src/types/instance.rs index a0218e4276..04a560be83 100644 --- a/crates/ty_python_semantic/src/types/instance.rs +++ b/crates/ty_python_semantic/src/types/instance.rs @@ -213,7 +213,7 @@ pub(super) fn walk_nominal_instance_type<'db, V: super::visitor::TypeVisitor<'db impl<'db> NominalInstanceType<'db> { pub(super) fn class(&self, db: &'db dyn Db) -> ClassType<'db> { match self.0 { - NominalInstanceInner::ExactTuple(tuple) => tuple.to_class_type(db, None), + NominalInstanceInner::ExactTuple(tuple) => tuple.to_class_type(db), NominalInstanceInner::NonTuple(class) => class, NominalInstanceInner::Object => KnownClass::Object .try_to_class_literal(db) @@ -224,7 +224,7 @@ impl<'db> NominalInstanceType<'db> { pub(super) fn class_literal(&self, db: &'db dyn Db) -> ClassLiteral<'db> { let class = match self.0 { - NominalInstanceInner::ExactTuple(tuple) => tuple.to_class_type(db, None), + NominalInstanceInner::ExactTuple(tuple) => tuple.to_class_type(db), NominalInstanceInner::NonTuple(class) => class, NominalInstanceInner::Object => { return KnownClass::Object diff --git a/crates/ty_python_semantic/src/types/mro.rs b/crates/ty_python_semantic/src/types/mro.rs index 34bd1a58d8..e2262ce925 100644 --- a/crates/ty_python_semantic/src/types/mro.rs +++ b/crates/ty_python_semantic/src/types/mro.rs @@ -51,7 +51,7 @@ impl<'db> Mro<'db> { class_literal: ClassLiteral<'db>, specialization: Option>, ) -> Result> { - let class = class_literal.apply_optional_specialization(db, specialization, None); + let class = class_literal.apply_optional_specialization(db, specialization); // Special-case `NotImplementedType`: typeshed says that it inherits from `Any`, // but this causes more problems than it fixes. if class_literal.is_known(db, KnownClass::NotImplementedType) { @@ -100,7 +100,13 @@ impl<'db> Mro<'db> { if original_bases.contains(&Type::SpecialForm(SpecialFormType::Protocol)) { return; } - if remaining_bases.iter().any(Type::is_generic_alias) { + if remaining_bases.iter().any(|ty| { + matches!( + ty, + Type::GenericAlias(..) + | Type::KnownInstance(KnownInstanceType::GenericAlias(_)) + ) + }) { return; } resolved_bases.push(ClassBase::Generic); @@ -412,11 +418,10 @@ impl<'db> Iterator for MroIterator<'db> { fn next(&mut self) -> Option { if !self.first_element_yielded { self.first_element_yielded = true; - return Some(ClassBase::Class(self.class.apply_optional_specialization( - self.db, - self.specialization, - None, - ))); + return Some(ClassBase::Class( + self.class + .apply_optional_specialization(self.db, self.specialization), + )); } self.full_mro_except_first_element().next() } diff --git a/crates/ty_python_semantic/src/types/tuple.rs b/crates/ty_python_semantic/src/types/tuple.rs index 4158ce629c..e773315d68 100644 --- a/crates/ty_python_semantic/src/types/tuple.rs +++ b/crates/ty_python_semantic/src/types/tuple.rs @@ -202,27 +202,19 @@ impl<'db> TupleType<'db> { // `static-frame` as part of a mypy_primer run! This is because it's called // from `NominalInstanceType::class()`, which is a very hot method. #[salsa::tracked(cycle_initial=to_class_type_cycle_initial, heap_size=ruff_memory_usage::heap_size)] - pub(crate) fn to_class_type( - self, - db: &'db dyn Db, - binding_context: Option>, - ) -> ClassType<'db> { + pub(crate) fn to_class_type(self, db: &'db dyn Db) -> ClassType<'db> { let tuple_class = KnownClass::Tuple .try_to_class_literal(db) .expect("Typeshed should always have a `tuple` class in `builtins.pyi`"); - tuple_class.apply_specialization( - db, - |generic_context| { - if generic_context.variables(db).len() == 1 { - let element_type = self.tuple(db).homogeneous_element_type(db); - generic_context.specialize_tuple(db, element_type, self) - } else { - generic_context.default_specialization(db, Some(KnownClass::Tuple)) - } - }, - binding_context, - ) + tuple_class.apply_specialization(db, |generic_context| { + if generic_context.variables(db).len() == 1 { + let element_type = self.tuple(db).homogeneous_element_type(db); + generic_context.specialize_tuple(db, element_type, self) + } else { + generic_context.default_specialization(db, Some(KnownClass::Tuple)) + } + }) } /// Return a normalized version of `self`. @@ -302,23 +294,18 @@ fn to_class_type_cycle_initial<'db>( db: &'db dyn Db, _id: salsa::Id, self_: TupleType<'db>, - binding_context: Option>, ) -> ClassType<'db> { let tuple_class = KnownClass::Tuple .try_to_class_literal(db) .expect("Typeshed should always have a `tuple` class in `builtins.pyi`"); - tuple_class.apply_specialization( - db, - |generic_context| { - if generic_context.variables(db).len() == 1 { - generic_context.specialize_tuple(db, Type::Never, self_) - } else { - generic_context.default_specialization(db, Some(KnownClass::Tuple)) - } - }, - binding_context, - ) + tuple_class.apply_specialization(db, |generic_context| { + if generic_context.variables(db).len() == 1 { + generic_context.specialize_tuple(db, Type::Never, self_) + } else { + generic_context.default_specialization(db, Some(KnownClass::Tuple)) + } + }) } /// A tuple spec describes the contents of a tuple type, which might be fixed- or variable-length.