From e609da0c729bedbf7c45a163749e7869c8aa7650 Mon Sep 17 00:00:00 2001 From: David Peter Date: Wed, 26 Nov 2025 14:55:59 +0100 Subject: [PATCH] Remove it from ClassType --- crates/ty_python_semantic/src/types.rs | 69 +++++++++++-------- crates/ty_python_semantic/src/types/class.rs | 22 ++---- .../src/types/class_base.rs | 4 +- .../ty_python_semantic/src/types/display.rs | 4 +- .../ty_python_semantic/src/types/function.rs | 6 +- .../src/types/infer/builder.rs | 4 +- .../types/infer/builder/type_expression.rs | 4 +- .../src/types/subclass_of.rs | 2 +- 8 files changed, 58 insertions(+), 57 deletions(-) diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index 17b7e101be..fb7e235819 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -1160,7 +1160,7 @@ impl<'db> Type<'db> { pub(crate) fn to_class_type(self, db: &'db dyn Db) -> Option> { match self { 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, } } @@ -1284,8 +1284,8 @@ impl<'db> Type<'db> { Self::BytesLiteral(BytesLiteralType::new(db, bytes)) } - pub(crate) fn typed_dict(defining_class: impl Into>) -> Self { - Self::TypedDict(TypedDictType::new(defining_class.into())) + pub(crate) fn typed_dict(defining_class: ClassType<'db>) -> Self { + Self::TypedDict(TypedDictType::new(defining_class)) } #[must_use] @@ -1570,7 +1570,9 @@ impl<'db> Type<'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::instance(db, newtype.base_class_type(db)).try_upcast_to_callable(db) @@ -2417,20 +2419,22 @@ impl<'db> Type<'db> { ) }) .unwrap_or_else(|| ConstraintSet::from(relation.is_assignability())), - (Type::GenericAlias(alias), Type::SubclassOf(target_subclass_ty)) => target_subclass_ty - .subclass_of() - .into_class() - .map(|subclass_of_class| { - ClassType::Generic(alias).has_relation_to_impl( - db, - subclass_of_class, - inferable, - relation, - relation_visitor, - disjointness_visitor, - ) - }) - .unwrap_or_else(|| ConstraintSet::from(relation.is_assignability())), + (Type::GenericAlias(instance), Type::SubclassOf(target_subclass_ty)) => { + target_subclass_ty + .subclass_of() + .into_class() + .map(|subclass_of_class| { + ClassType::Generic(instance.alias(db)).has_relation_to_impl( + db, + subclass_of_class, + inferable, + relation, + relation_visitor, + disjointness_visitor, + ) + }) + .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]`? (Type::SubclassOf(self_subclass_ty), Type::SubclassOf(target_subclass_ty)) => { @@ -2457,7 +2461,7 @@ impl<'db> Type<'db> { disjointness_visitor, ) } - (Type::GenericAlias(alias), _) => ClassType::from(alias) + (Type::GenericAlias(instance), _) => ClassType::Generic(instance.alias(db)) .metaclass_instance_type(db) .has_relation_to_impl( db, @@ -3181,7 +3185,7 @@ impl<'db> Type<'db> { | (Type::GenericAlias(alias_b), Type::SubclassOf(subclass_of_ty)) => { match subclass_of_ty.subclass_of() { 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) .negate(db), } @@ -3296,9 +3300,9 @@ impl<'db> Type<'db> { .metaclass_instance_type(db) .when_subtype_of(db, instance, inferable) .negate(db), - (Type::GenericAlias(alias), instance @ Type::NominalInstance(_)) - | (instance @ Type::NominalInstance(_), Type::GenericAlias(alias)) => { - ClassType::from(alias) + (Type::GenericAlias(generic), instance @ Type::NominalInstance(_)) + | (instance @ Type::NominalInstance(_), Type::GenericAlias(generic)) => { + ClassType::Generic(generic.alias(db)) .metaclass_instance_type(db) .has_relation_to_impl( db, @@ -3831,7 +3835,8 @@ impl<'db> Type<'db> { ), 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 .alias(db) .specialization(db) @@ -5040,7 +5045,7 @@ impl<'db> Type<'db> { .metaclass_instance_type(db) .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) .try_bool_impl(db, allow_short_circuit, visitor)?, @@ -6642,7 +6647,9 @@ impl<'db> Type<'db> { match self { Type::Dynamic(_) | Type::Never => Some(self), 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::KnownInstance(KnownInstanceType::NewType(newtype)) => { Some(Type::NewTypeInstance(newtype)) @@ -6725,9 +6732,11 @@ impl<'db> Type<'db> { Ok(ty) } 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::BooleanLiteral(_) @@ -7085,7 +7094,7 @@ impl<'db> Type<'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() { SubclassOfInner::Dynamic(_) => self, SubclassOfInner::Class(class) => SubclassOfType::from( @@ -8271,7 +8280,7 @@ fn walk_known_instance_type<'db, V: visitor::TypeVisitor<'db> + ?Sized>( } KnownInstanceType::NewType(newtype) => { 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); } } } diff --git a/crates/ty_python_semantic/src/types/class.rs b/crates/ty_python_semantic/src/types/class.rs index 2504a4757a..910f598546 100644 --- a/crates/ty_python_semantic/src/types/class.rs +++ b/crates/ty_python_semantic/src/types/class.rs @@ -419,7 +419,7 @@ pub enum ClassType<'db> { // should use `ClassLiteral::default_specialization` instead of assuming // `ClassType::NonGeneric`. NonGeneric(ClassLiteral<'db>), - Generic(GenericAliasInstance<'db>), + Generic(GenericAlias<'db>), } #[salsa::tracked] @@ -439,14 +439,16 @@ impl<'db> ClassType<'db> { pub(super) fn into_generic_alias(self, db: &'db dyn Db) -> Option> { match self { 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> { match self { 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)) } -impl<'db> From> for ClassType<'db> { - fn from(generic: GenericAliasInstance<'db>) -> ClassType<'db> { - ClassType::Generic(generic) - } -} - impl<'db> VarianceInferable<'db> for ClassType<'db> { fn variance_of(self, db: &'db dyn Db, typevar: BoundTypeVarInstance<'db>) -> TypeVarVariance { match self { 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( - db, - GenericAlias::new(db, self, specialization), - binding_context, - )) + ClassType::Generic(GenericAlias::new(db, self, specialization)) } } } diff --git a/crates/ty_python_semantic/src/types/class_base.rs b/crates/ty_python_semantic/src/types/class_base.rs index dd55212c39..e05be12e79 100644 --- a/crates/ty_python_semantic/src/types/class_base.rs +++ b/crates/ty_python_semantic/src/types/class_base.rs @@ -79,7 +79,9 @@ impl<'db> ClassBase<'db> { match ty { Type::Dynamic(dynamic) => Some(Self::Dynamic(dynamic)), 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) if instance.has_known_class(db, KnownClass::GenericAlias) => { diff --git a/crates/ty_python_semantic/src/types/display.rs b/crates/ty_python_semantic/src/types/display.rs index d4ddda7601..4ad0c4317a 100644 --- a/crates/ty_python_semantic/src/types/display.rs +++ b/crates/ty_python_semantic/src/types/display.rs @@ -599,7 +599,7 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> { (ClassType::NonGeneric(class), _) => { 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 { @@ -608,7 +608,6 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> { .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), }, @@ -674,7 +673,6 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> { .write_str("type")?; f.write_char('[')?; instance - .alias(self.db) .display_with(self.db, self.settings.clone()) .fmt_detailed(f)?; f.write_char(']') diff --git a/crates/ty_python_semantic/src/types/function.rs b/crates/ty_python_semantic/src/types/function.rs index 80e0d802d9..d29330419b 100644 --- a/crates/ty_python_semantic/src/types/function.rs +++ b/crates/ty_python_semantic/src/types/function.rs @@ -1578,7 +1578,7 @@ impl KnownFunction { let mut good_argument = true; let classes = match param_type { 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) => { let elements = union.elements(db); let mut classes = Vec::with_capacity(elements.len()); @@ -1587,8 +1587,8 @@ impl KnownFunction { Type::ClassLiteral(class) => { classes.push(ClassType::NonGeneric(*class)); } - Type::GenericAlias(generic_alias) => { - classes.push(ClassType::Generic(*generic_alias)); + Type::GenericAlias(generic) => { + classes.push(ClassType::Generic(generic.alias(db))); } _ => { good_argument = false; diff --git a/crates/ty_python_semantic/src/types/infer/builder.rs b/crates/ty_python_semantic/src/types/infer/builder.rs index da28ad4ef5..3ac8ae0dd7 100644 --- a/crates/ty_python_semantic/src/types/infer/builder.rs +++ b/crates/ty_python_semantic/src/types/infer/builder.rs @@ -686,7 +686,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { continue; } Type::ClassLiteral(class) => ClassType::NonGeneric(*class), - Type::GenericAlias(class) => ClassType::Generic(*class), + Type::GenericAlias(generic) => ClassType::Generic(generic.alias(self.db())), _ => continue, }; @@ -8085,7 +8085,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { let class = match callable_type { 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(), _ => None, }; 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 b279e64f53..6ec78b03f7 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 @@ -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, value_ty, - alias.binding_context(self.db()), + instance.binding_context(self.db()), true, ), Type::StringLiteral(_) => { diff --git a/crates/ty_python_semantic/src/types/subclass_of.rs b/crates/ty_python_semantic/src/types/subclass_of.rs index a59675b740..3e86777951 100644 --- a/crates/ty_python_semantic/src/types/subclass_of.rs +++ b/crates/ty_python_semantic/src/types/subclass_of.rs @@ -273,7 +273,7 @@ impl<'db> SubclassOfInner<'db> { match ty { Type::Dynamic(dynamic) => Some(Self::Dynamic(dynamic)), 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)), _ => None, }