From 566bfc5ecbe37ecaaa11f18e1f129dc57d9df6bf Mon Sep 17 00:00:00 2001 From: Douglas Creager Date: Wed, 17 Dec 2025 19:23:56 -0500 Subject: [PATCH] partial spec is an enum --- .../ty_python_semantic/src/types/generics.rs | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/crates/ty_python_semantic/src/types/generics.rs b/crates/ty_python_semantic/src/types/generics.rs index ca6a700bd2..baa991e333 100644 --- a/crates/ty_python_semantic/src/types/generics.rs +++ b/crates/ty_python_semantic/src/types/generics.rs @@ -568,7 +568,7 @@ impl<'db> GenericContext<'db> { loop { let mut any_changed = false; for i in 0..len { - let partial = PartialSpecialization { + let partial = PartialSpecialization::FromGenericContext { generic_context: self, types: &types, // Don't recursively substitute type[i] in itself. Ideally, we could instead @@ -646,7 +646,7 @@ impl<'db> GenericContext<'db> { // Typevars are only allowed to refer to _earlier_ typevars in their defaults. (This is // statically enforced for PEP-695 contexts, and is explicitly called out as a // requirement for legacy contexts.) - let partial = PartialSpecialization { + let partial = PartialSpecialization::FromGenericContext { generic_context: self, types: &expanded[0..idx], skip: None, @@ -1452,12 +1452,14 @@ impl<'db> Specialization<'db> { /// You will usually use [`Specialization`] instead of this type. This type is used when we need to /// substitute types for type variables before we have fully constructed a [`Specialization`]. #[derive(Clone, Debug, Eq, Hash, PartialEq, get_size2::GetSize)] -pub struct PartialSpecialization<'a, 'db> { - generic_context: GenericContext<'db>, - types: &'a [Type<'db>], - /// An optional typevar to _not_ substitute when applying the specialization. We use this to - /// avoid recursively substituting a type inside of itself. - skip: Option, +pub enum PartialSpecialization<'a, 'db> { + FromGenericContext { + generic_context: GenericContext<'db>, + types: &'a [Type<'db>], + /// An optional typevar to _not_ substitute when applying the specialization. We use this to + /// avoid recursively substituting a type inside of itself. + skip: Option, + }, } impl<'db> PartialSpecialization<'_, 'db> { @@ -1468,14 +1470,21 @@ impl<'db> PartialSpecialization<'_, 'db> { db: &'db dyn Db, bound_typevar: BoundTypeVarInstance<'db>, ) -> Option> { - let index = self - .generic_context - .variables_inner(db) - .get_index_of(&bound_typevar.identity(db))?; - if self.skip.is_some_and(|skip| skip == index) { - return Some(Type::Never); + match self { + PartialSpecialization::FromGenericContext { + generic_context, + types, + skip, + } => { + let index = generic_context + .variables_inner(db) + .get_index_of(&bound_typevar.identity(db))?; + if skip.is_some_and(|skip| skip == index) { + return Some(Type::Never); + } + types.get(index).copied() + } } - self.types.get(index).copied() } }