move `Type::is_definition_generic` to `types.rs`

This commit is contained in:
Shunsuke Shibayama 2025-12-10 19:27:31 +09:00
parent 41e30cc86d
commit 51af2786bc
2 changed files with 42 additions and 38 deletions

View File

@ -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(_))
}

View File

@ -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<NominalInstanceType<'db>> {
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.
///