From 51af2786bc229c16f470bacef239926901d18128 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Wed, 10 Dec 2025 19:27:31 +0900 Subject: [PATCH] move `Type::is_definition_generic` to `types.rs` --- crates/ty_python_semantic/src/types.rs | 33 +++++++++++++ .../ty_python_semantic/src/types/instance.rs | 47 ++++--------------- 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index 23f7a53f79..c93a6d2cc9 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -977,6 +977,39 @@ impl<'db> Type<'db> { matches!(self, Type::GenericAlias(_)) } + /// Returns whether the definition of this type is generic + /// (this is different from whether this type *is* a generic type; a type that is already fully specialized is not a generic type). + pub(crate) fn is_definition_generic(self, db: &'db dyn Db) -> bool { + match self { + Type::Union(union) => union + .elements(db) + .iter() + .any(|ty| ty.is_definition_generic(db)), + Type::Intersection(intersection) => { + intersection + .positive(db) + .iter() + .any(|ty| ty.is_definition_generic(db)) + || intersection + .negative(db) + .iter() + .any(|ty| ty.is_definition_generic(db)) + } + Type::NominalInstance(instance_type) => instance_type.is_definition_generic(), + Type::ProtocolInstance(protocol) => { + matches!(protocol.inner, Protocol::FromClass(class) if class.is_generic()) + } + Type::TypedDict(typed_dict) => typed_dict.defining_class().is_generic(), + Type::Dynamic(dynamic) => { + matches!(dynamic, DynamicType::UnknownGeneric(_)) + } + // Due to inheritance rules, enums cannot be generic. + Type::EnumLiteral(_) => false, + // Once generic NewType is officially specified, handle it. + _ => false, + } + } + const fn is_dynamic(&self) -> bool { matches!(self, Type::Dynamic(_)) } diff --git a/crates/ty_python_semantic/src/types/instance.rs b/crates/ty_python_semantic/src/types/instance.rs index a9d93f331b..9e674065b9 100644 --- a/crates/ty_python_semantic/src/types/instance.rs +++ b/crates/ty_python_semantic/src/types/instance.rs @@ -13,7 +13,7 @@ use crate::types::generics::{InferableTypeVars, walk_specialization}; use crate::types::protocol_class::{ProtocolClass, walk_protocol_interface}; use crate::types::tuple::{TupleSpec, TupleType, walk_tuple_type}; use crate::types::{ - ApplyTypeMappingVisitor, ClassBase, ClassLiteral, DynamicType, FindLegacyTypeVarsVisitor, + ApplyTypeMappingVisitor, ClassBase, ClassLiteral, FindLegacyTypeVarsVisitor, HasRelationToVisitor, IsDisjointVisitor, IsEquivalentVisitor, NormalizedVisitor, TypeContext, TypeMapping, TypeRelation, VarianceInferable, }; @@ -93,43 +93,6 @@ impl<'db> Type<'db> { matches!(self, Type::NominalInstance(_)) } - /// Returns whether the definition of this type is generic - /// (this is different from whether this type *is* a generic type; a type that is already fully specialized is not a generic type). - pub(crate) fn is_definition_generic(self, db: &'db dyn Db) -> bool { - match self { - Type::Union(union) => union - .elements(db) - .iter() - .any(|ty| ty.is_definition_generic(db)), - Type::Intersection(intersection) => { - intersection - .positive(db) - .iter() - .any(|ty| ty.is_definition_generic(db)) - || intersection - .negative(db) - .iter() - .any(|ty| ty.is_definition_generic(db)) - } - Type::NominalInstance(instance_type) => match instance_type.0 { - NominalInstanceInner::NonTuple(class) => class.is_generic(), - NominalInstanceInner::ExactTuple(_) => true, - NominalInstanceInner::Object => false, - }, - Type::ProtocolInstance(protocol) => { - matches!(protocol.inner, Protocol::FromClass(class) if class.is_generic()) - } - Type::TypedDict(typed_dict) => typed_dict.defining_class().is_generic(), - Type::Dynamic(dynamic) => { - matches!(dynamic, DynamicType::UnknownGeneric(_)) - } - // Due to inheritance rules, enums cannot be generic. - Type::EnumLiteral(_) => false, - // Once generic NewType is officially specified, handle it. - _ => false, - } - } - pub(crate) const fn as_nominal_instance(self) -> Option> { match self { Type::NominalInstance(instance_type) => Some(instance_type), @@ -341,6 +304,14 @@ impl<'db> NominalInstanceType<'db> { matches!(self.0, NominalInstanceInner::Object) } + pub(super) fn is_definition_generic(self) -> bool { + match self.0 { + NominalInstanceInner::NonTuple(class) => class.is_generic(), + NominalInstanceInner::ExactTuple(_) => true, + NominalInstanceInner::Object => false, + } + } + /// If this type is an *exact* tuple type (*not* a subclass of `tuple`), returns the /// tuple spec. ///