partial spec is an enum

This commit is contained in:
Douglas Creager
2025-12-17 19:23:56 -05:00
parent 7d38dc8685
commit 566bfc5ecb

View File

@@ -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<usize>,
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<usize>,
},
}
impl<'db> PartialSpecialization<'_, 'db> {
@@ -1468,14 +1470,21 @@ impl<'db> PartialSpecialization<'_, 'db> {
db: &'db dyn Db,
bound_typevar: BoundTypeVarInstance<'db>,
) -> Option<Type<'db>> {
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()
}
}