use csa for instance checks

This commit is contained in:
Douglas Creager 2025-12-10 12:57:27 -05:00
parent c02bd11b93
commit fef0ba39d3
1 changed files with 3 additions and 46 deletions

View File

@ -9,10 +9,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
use crate::semantic_index::definition::Definition; use crate::semantic_index::definition::Definition;
use crate::semantic_index::scope::{FileScopeId, NodeWithScopeKind, ScopeId}; use crate::semantic_index::scope::{FileScopeId, NodeWithScopeKind, ScopeId};
use crate::semantic_index::{SemanticIndex, semantic_index}; use crate::semantic_index::{SemanticIndex, semantic_index};
use crate::types::class::ClassType;
use crate::types::class_base::ClassBase;
use crate::types::constraints::{ConstraintSet, IteratorConstraintsExtension}; use crate::types::constraints::{ConstraintSet, IteratorConstraintsExtension};
use crate::types::instance::{Protocol, ProtocolInstanceType};
use crate::types::signatures::Parameters; use crate::types::signatures::Parameters;
use crate::types::tuple::{TupleSpec, TupleType, walk_tuple_type}; use crate::types::tuple::{TupleSpec, TupleType, walk_tuple_type};
use crate::types::variance::VarianceInferable; use crate::types::variance::VarianceInferable;
@ -1887,49 +1884,9 @@ impl<'db> SpecializationBuilder<'db> {
return Ok(()); return Ok(());
} }
// Extract formal_alias if this is a generic class let when =
let formal_alias = match formal { actual.when_constraint_set_assignable_to(self.db, formal, self.inferable);
Type::NominalInstance(formal_nominal) => { self.add_type_mappings_from_constraint_set(formal, when, &mut f);
formal_nominal.class(self.db).into_generic_alias()
}
// TODO: This will only handle classes that explicit implement a generic protocol
// by listing it as a base class. To handle classes that implicitly implement a
// generic protocol, we will need to check the types of the protocol members to be
// able to infer the specialization of the protocol that the class implements.
Type::ProtocolInstance(ProtocolInstanceType {
inner: Protocol::FromClass(class),
..
}) => class.into_generic_alias(),
_ => None,
};
if let Some(formal_alias) = formal_alias {
let formal_origin = formal_alias.origin(self.db);
for base in actual_nominal.class(self.db).iter_mro(self.db) {
let ClassBase::Class(ClassType::Generic(base_alias)) = base else {
continue;
};
if formal_origin != base_alias.origin(self.db) {
continue;
}
let generic_context = formal_alias
.specialization(self.db)
.generic_context(self.db)
.variables(self.db);
let formal_specialization =
formal_alias.specialization(self.db).types(self.db);
let base_specialization = base_alias.specialization(self.db).types(self.db);
for (typevar, formal_ty, base_ty) in itertools::izip!(
generic_context,
formal_specialization,
base_specialization
) {
let variance = typevar.variance_with_polarity(self.db, polarity);
self.infer_map_impl(*formal_ty, *base_ty, variance, &mut f)?;
}
return Ok(());
}
}
} }
(Type::Callable(formal_callable), _) => { (Type::Callable(formal_callable), _) => {