Remove it from ClassType

This commit is contained in:
David Peter 2025-11-26 14:55:59 +01:00
parent 7818186fcc
commit e609da0c72
8 changed files with 58 additions and 57 deletions

View File

@ -1160,7 +1160,7 @@ impl<'db> Type<'db> {
pub(crate) fn to_class_type(self, db: &'db dyn Db) -> Option<ClassType<'db>> { pub(crate) fn to_class_type(self, db: &'db dyn Db) -> Option<ClassType<'db>> {
match self { match self {
Type::ClassLiteral(class_literal) => Some(class_literal.default_specialization(db)), Type::ClassLiteral(class_literal) => Some(class_literal.default_specialization(db)),
Type::GenericAlias(alias) => Some(ClassType::Generic(alias)), Type::GenericAlias(instance) => Some(ClassType::Generic(instance.alias(db))),
_ => None, _ => None,
} }
} }
@ -1284,8 +1284,8 @@ impl<'db> Type<'db> {
Self::BytesLiteral(BytesLiteralType::new(db, bytes)) Self::BytesLiteral(BytesLiteralType::new(db, bytes))
} }
pub(crate) fn typed_dict(defining_class: impl Into<ClassType<'db>>) -> Self { pub(crate) fn typed_dict(defining_class: ClassType<'db>) -> Self {
Self::TypedDict(TypedDictType::new(defining_class.into())) Self::TypedDict(TypedDictType::new(defining_class))
} }
#[must_use] #[must_use]
@ -1570,7 +1570,9 @@ impl<'db> Type<'db> {
Some(class_literal.default_specialization(db).into_callable(db)) Some(class_literal.default_specialization(db).into_callable(db))
} }
Type::GenericAlias(alias) => Some(ClassType::Generic(alias).into_callable(db)), Type::GenericAlias(instance) => {
Some(ClassType::Generic(instance.alias(db)).into_callable(db))
}
Type::NewTypeInstance(newtype) => { Type::NewTypeInstance(newtype) => {
Type::instance(db, newtype.base_class_type(db)).try_upcast_to_callable(db) Type::instance(db, newtype.base_class_type(db)).try_upcast_to_callable(db)
@ -2417,11 +2419,12 @@ impl<'db> Type<'db> {
) )
}) })
.unwrap_or_else(|| ConstraintSet::from(relation.is_assignability())), .unwrap_or_else(|| ConstraintSet::from(relation.is_assignability())),
(Type::GenericAlias(alias), Type::SubclassOf(target_subclass_ty)) => target_subclass_ty (Type::GenericAlias(instance), Type::SubclassOf(target_subclass_ty)) => {
target_subclass_ty
.subclass_of() .subclass_of()
.into_class() .into_class()
.map(|subclass_of_class| { .map(|subclass_of_class| {
ClassType::Generic(alias).has_relation_to_impl( ClassType::Generic(instance.alias(db)).has_relation_to_impl(
db, db,
subclass_of_class, subclass_of_class,
inferable, inferable,
@ -2430,7 +2433,8 @@ impl<'db> Type<'db> {
disjointness_visitor, disjointness_visitor,
) )
}) })
.unwrap_or_else(|| ConstraintSet::from(relation.is_assignability())), .unwrap_or_else(|| ConstraintSet::from(relation.is_assignability()))
}
// This branch asks: given two types `type[T]` and `type[S]`, is `type[T]` a subtype of `type[S]`? // This branch asks: given two types `type[T]` and `type[S]`, is `type[T]` a subtype of `type[S]`?
(Type::SubclassOf(self_subclass_ty), Type::SubclassOf(target_subclass_ty)) => { (Type::SubclassOf(self_subclass_ty), Type::SubclassOf(target_subclass_ty)) => {
@ -2457,7 +2461,7 @@ impl<'db> Type<'db> {
disjointness_visitor, disjointness_visitor,
) )
} }
(Type::GenericAlias(alias), _) => ClassType::from(alias) (Type::GenericAlias(instance), _) => ClassType::Generic(instance.alias(db))
.metaclass_instance_type(db) .metaclass_instance_type(db)
.has_relation_to_impl( .has_relation_to_impl(
db, db,
@ -3181,7 +3185,7 @@ impl<'db> Type<'db> {
| (Type::GenericAlias(alias_b), Type::SubclassOf(subclass_of_ty)) => { | (Type::GenericAlias(alias_b), Type::SubclassOf(subclass_of_ty)) => {
match subclass_of_ty.subclass_of() { match subclass_of_ty.subclass_of() {
SubclassOfInner::Dynamic(_) => ConstraintSet::from(false), SubclassOfInner::Dynamic(_) => ConstraintSet::from(false),
SubclassOfInner::Class(class_a) => ClassType::from(alias_b) SubclassOfInner::Class(class_a) => ClassType::Generic(alias_b.alias(db))
.when_subclass_of(db, class_a, inferable) .when_subclass_of(db, class_a, inferable)
.negate(db), .negate(db),
} }
@ -3296,9 +3300,9 @@ impl<'db> Type<'db> {
.metaclass_instance_type(db) .metaclass_instance_type(db)
.when_subtype_of(db, instance, inferable) .when_subtype_of(db, instance, inferable)
.negate(db), .negate(db),
(Type::GenericAlias(alias), instance @ Type::NominalInstance(_)) (Type::GenericAlias(generic), instance @ Type::NominalInstance(_))
| (instance @ Type::NominalInstance(_), Type::GenericAlias(alias)) => { | (instance @ Type::NominalInstance(_), Type::GenericAlias(generic)) => {
ClassType::from(alias) ClassType::Generic(generic.alias(db))
.metaclass_instance_type(db) .metaclass_instance_type(db)
.has_relation_to_impl( .has_relation_to_impl(
db, db,
@ -3831,7 +3835,8 @@ impl<'db> Type<'db> {
), ),
Type::GenericAlias(instance) => { Type::GenericAlias(instance) => {
let attr = Some(ClassType::from(*instance).class_member(db, name, policy)); let attr =
Some(ClassType::Generic(instance.alias(db)).class_member(db, name, policy));
match instance match instance
.alias(db) .alias(db)
.specialization(db) .specialization(db)
@ -5040,7 +5045,7 @@ impl<'db> Type<'db> {
.metaclass_instance_type(db) .metaclass_instance_type(db)
.try_bool_impl(db, allow_short_circuit, visitor)? .try_bool_impl(db, allow_short_circuit, visitor)?
} }
Type::GenericAlias(alias) => ClassType::from(*alias) Type::GenericAlias(generic) => ClassType::Generic(generic.alias(db))
.metaclass_instance_type(db) .metaclass_instance_type(db)
.try_bool_impl(db, allow_short_circuit, visitor)?, .try_bool_impl(db, allow_short_circuit, visitor)?,
@ -6642,7 +6647,9 @@ impl<'db> Type<'db> {
match self { match self {
Type::Dynamic(_) | Type::Never => Some(self), Type::Dynamic(_) | Type::Never => Some(self),
Type::ClassLiteral(class) => Some(Type::instance(db, class.default_specialization(db))), Type::ClassLiteral(class) => Some(Type::instance(db, class.default_specialization(db))),
Type::GenericAlias(alias) => Some(Type::instance(db, ClassType::from(alias))), Type::GenericAlias(instance) => {
Some(Type::instance(db, ClassType::Generic(instance.alias(db))))
}
Type::SubclassOf(subclass_of_ty) => Some(subclass_of_ty.to_instance(db)), Type::SubclassOf(subclass_of_ty) => Some(subclass_of_ty.to_instance(db)),
Type::KnownInstance(KnownInstanceType::NewType(newtype)) => { Type::KnownInstance(KnownInstanceType::NewType(newtype)) => {
Some(Type::NewTypeInstance(newtype)) Some(Type::NewTypeInstance(newtype))
@ -6725,9 +6732,11 @@ impl<'db> Type<'db> {
Ok(ty) Ok(ty)
} }
Type::GenericAlias(instance) if instance.alias(db).is_typed_dict(db) => { Type::GenericAlias(instance) if instance.alias(db).is_typed_dict(db) => {
Ok(Type::typed_dict(*instance)) Ok(Type::typed_dict(ClassType::Generic(instance.alias(db))))
}
Type::GenericAlias(instance) => {
Ok(Type::instance(db, ClassType::Generic(instance.alias(db))))
} }
Type::GenericAlias(instance) => Ok(Type::instance(db, ClassType::from(*instance))),
Type::SubclassOf(_) Type::SubclassOf(_)
| Type::BooleanLiteral(_) | Type::BooleanLiteral(_)
@ -7085,7 +7094,7 @@ impl<'db> Type<'db> {
} }
Type::ClassLiteral(class) => class.metaclass(db), Type::ClassLiteral(class) => class.metaclass(db),
Type::GenericAlias(alias) => ClassType::from(alias).metaclass(db), Type::GenericAlias(instance) => ClassType::Generic(instance.alias(db)).metaclass(db),
Type::SubclassOf(subclass_of_ty) => match subclass_of_ty.subclass_of() { Type::SubclassOf(subclass_of_ty) => match subclass_of_ty.subclass_of() {
SubclassOfInner::Dynamic(_) => self, SubclassOfInner::Dynamic(_) => self,
SubclassOfInner::Class(class) => SubclassOfType::from( SubclassOfInner::Class(class) => SubclassOfType::from(
@ -8271,7 +8280,7 @@ fn walk_known_instance_type<'db, V: visitor::TypeVisitor<'db> + ?Sized>(
} }
KnownInstanceType::NewType(newtype) => { KnownInstanceType::NewType(newtype) => {
if let ClassType::Generic(generic_alias) = newtype.base_class_type(db) { if let ClassType::Generic(generic_alias) = newtype.base_class_type(db) {
visitor.visit_generic_alias_type(db, generic_alias.alias(db)); visitor.visit_generic_alias_type(db, generic_alias);
} }
} }
} }

View File

@ -419,7 +419,7 @@ pub enum ClassType<'db> {
// should use `ClassLiteral::default_specialization` instead of assuming // should use `ClassLiteral::default_specialization` instead of assuming
// `ClassType::NonGeneric`. // `ClassType::NonGeneric`.
NonGeneric(ClassLiteral<'db>), NonGeneric(ClassLiteral<'db>),
Generic(GenericAliasInstance<'db>), Generic(GenericAlias<'db>),
} }
#[salsa::tracked] #[salsa::tracked]
@ -439,14 +439,16 @@ impl<'db> ClassType<'db> {
pub(super) fn into_generic_alias(self, db: &'db dyn Db) -> Option<GenericAlias<'db>> { pub(super) fn into_generic_alias(self, db: &'db dyn Db) -> Option<GenericAlias<'db>> {
match self { match self {
Self::NonGeneric(_) => None, Self::NonGeneric(_) => None,
Self::Generic(instance) => Some(instance.alias(db)), Self::Generic(alias) => Some(alias),
} }
} }
pub(super) fn into_type(self, db: &'db dyn Db) -> Type<'db> { pub(super) fn into_type(self, db: &'db dyn Db) -> Type<'db> {
match self { match self {
Self::NonGeneric(class) => class.into(), Self::NonGeneric(class) => class.into(),
Self::Generic(generic) => Type::GenericAlias(generic), Self::Generic(instance) => {
Type::GenericAlias(GenericAliasInstance::new(db, instance, None))
}
} }
} }
@ -1280,17 +1282,11 @@ fn into_callable_cycle_initial<'db>(
CallableTypes::one(CallableType::bottom(db)) CallableTypes::one(CallableType::bottom(db))
} }
impl<'db> From<GenericAliasInstance<'db>> for ClassType<'db> {
fn from(generic: GenericAliasInstance<'db>) -> ClassType<'db> {
ClassType::Generic(generic)
}
}
impl<'db> VarianceInferable<'db> for ClassType<'db> { impl<'db> VarianceInferable<'db> for ClassType<'db> {
fn variance_of(self, db: &'db dyn Db, typevar: BoundTypeVarInstance<'db>) -> TypeVarVariance { fn variance_of(self, db: &'db dyn Db, typevar: BoundTypeVarInstance<'db>) -> TypeVarVariance {
match self { match self {
Self::NonGeneric(class) => class.variance_of(db, typevar), Self::NonGeneric(class) => class.variance_of(db, typevar),
Self::Generic(generic) => generic.alias(db).variance_of(db, typevar), Self::Generic(alias) => alias.variance_of(db, typevar),
} }
} }
} }
@ -1595,11 +1591,7 @@ impl<'db> ClassLiteral<'db> {
} }
} }
ClassType::Generic(GenericAliasInstance::new( ClassType::Generic(GenericAlias::new(db, self, specialization))
db,
GenericAlias::new(db, self, specialization),
binding_context,
))
} }
} }
} }

View File

@ -79,7 +79,9 @@ impl<'db> ClassBase<'db> {
match ty { match ty {
Type::Dynamic(dynamic) => Some(Self::Dynamic(dynamic)), Type::Dynamic(dynamic) => Some(Self::Dynamic(dynamic)),
Type::ClassLiteral(literal) => Some(Self::Class(literal.default_specialization(db))), Type::ClassLiteral(literal) => Some(Self::Class(literal.default_specialization(db))),
Type::GenericAlias(generic) => Some(Self::Class(ClassType::Generic(generic))), Type::GenericAlias(instance) => {
Some(Self::Class(ClassType::Generic(instance.alias(db))))
}
Type::NominalInstance(instance) Type::NominalInstance(instance)
if instance.has_known_class(db, KnownClass::GenericAlias) => if instance.has_known_class(db, KnownClass::GenericAlias) =>
{ {

View File

@ -599,7 +599,7 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
(ClassType::NonGeneric(class), _) => { (ClassType::NonGeneric(class), _) => {
class.display_with(self.db, self.settings.clone()).fmt_detailed(f) class.display_with(self.db, self.settings.clone()).fmt_detailed(f)
}, },
(ClassType::Generic(instance), _) => instance.alias(self.db).display_with(self.db, self.settings.clone()).fmt_detailed(f), (ClassType::Generic(instance), _) => instance.display_with(self.db, self.settings.clone()).fmt_detailed(f),
} }
} }
Type::ProtocolInstance(protocol) => match protocol.inner { Type::ProtocolInstance(protocol) => match protocol.inner {
@ -608,7 +608,6 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
.display_with(self.db, self.settings.clone()) .display_with(self.db, self.settings.clone())
.fmt_detailed(f), .fmt_detailed(f),
ClassType::Generic(instance) => instance ClassType::Generic(instance) => instance
.alias(self.db)
.display_with(self.db, self.settings.clone()) .display_with(self.db, self.settings.clone())
.fmt_detailed(f), .fmt_detailed(f),
}, },
@ -674,7 +673,6 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
.write_str("type")?; .write_str("type")?;
f.write_char('[')?; f.write_char('[')?;
instance instance
.alias(self.db)
.display_with(self.db, self.settings.clone()) .display_with(self.db, self.settings.clone())
.fmt_detailed(f)?; .fmt_detailed(f)?;
f.write_char(']') f.write_char(']')

View File

@ -1578,7 +1578,7 @@ impl KnownFunction {
let mut good_argument = true; let mut good_argument = true;
let classes = match param_type { let classes = match param_type {
Type::ClassLiteral(class) => vec![ClassType::NonGeneric(*class)], Type::ClassLiteral(class) => vec![ClassType::NonGeneric(*class)],
Type::GenericAlias(generic_alias) => vec![ClassType::Generic(*generic_alias)], Type::GenericAlias(generic) => vec![ClassType::Generic(generic.alias(db))],
Type::Union(union) => { Type::Union(union) => {
let elements = union.elements(db); let elements = union.elements(db);
let mut classes = Vec::with_capacity(elements.len()); let mut classes = Vec::with_capacity(elements.len());
@ -1587,8 +1587,8 @@ impl KnownFunction {
Type::ClassLiteral(class) => { Type::ClassLiteral(class) => {
classes.push(ClassType::NonGeneric(*class)); classes.push(ClassType::NonGeneric(*class));
} }
Type::GenericAlias(generic_alias) => { Type::GenericAlias(generic) => {
classes.push(ClassType::Generic(*generic_alias)); classes.push(ClassType::Generic(generic.alias(db)));
} }
_ => { _ => {
good_argument = false; good_argument = false;

View File

@ -686,7 +686,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
continue; continue;
} }
Type::ClassLiteral(class) => ClassType::NonGeneric(*class), Type::ClassLiteral(class) => ClassType::NonGeneric(*class),
Type::GenericAlias(class) => ClassType::Generic(*class), Type::GenericAlias(generic) => ClassType::Generic(generic.alias(self.db())),
_ => continue, _ => continue,
}; };
@ -8085,7 +8085,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
let class = match callable_type { let class = match callable_type {
Type::ClassLiteral(class) => Some(ClassType::NonGeneric(class)), Type::ClassLiteral(class) => Some(ClassType::NonGeneric(class)),
Type::GenericAlias(generic) => Some(ClassType::Generic(generic)), Type::GenericAlias(generic) => Some(ClassType::Generic(generic.alias(self.db()))),
Type::SubclassOf(subclass) => subclass.subclass_of().into_class(), Type::SubclassOf(subclass) => subclass.subclass_of().into_class(),
_ => None, _ => None,
}; };

View File

@ -1049,10 +1049,10 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
} }
} }
} }
Type::GenericAlias(alias) => self.infer_explicitly_specialized_type_alias( Type::GenericAlias(instance) => self.infer_explicitly_specialized_type_alias(
subscript, subscript,
value_ty, value_ty,
alias.binding_context(self.db()), instance.binding_context(self.db()),
true, true,
), ),
Type::StringLiteral(_) => { Type::StringLiteral(_) => {

View File

@ -273,7 +273,7 @@ impl<'db> SubclassOfInner<'db> {
match ty { match ty {
Type::Dynamic(dynamic) => Some(Self::Dynamic(dynamic)), Type::Dynamic(dynamic) => Some(Self::Dynamic(dynamic)),
Type::ClassLiteral(literal) => Some(Self::Class(literal.default_specialization(db))), Type::ClassLiteral(literal) => Some(Self::Class(literal.default_specialization(db))),
Type::GenericAlias(generic) => Some(Self::Class(ClassType::Generic(generic))), Type::GenericAlias(generic) => Some(Self::Class(ClassType::Generic(generic.alias(db)))),
Type::SpecialForm(SpecialFormType::Any) => Some(Self::Dynamic(DynamicType::Any)), Type::SpecialForm(SpecialFormType::Any) => Some(Self::Dynamic(DynamicType::Any)),
_ => None, _ => None,
} }