This commit is contained in:
Ibraheem Ahmed 2025-12-17 21:05:54 -05:00
parent 58160c3d67
commit 14f554b453
3 changed files with 27 additions and 57 deletions

View File

@ -3921,82 +3921,54 @@ impl<'db> Type<'db> {
where where
F: FnMut(BoundTypeVarInstance<'db>, Type<'db>, TypeVarVariance, TypeContext<'db>), F: FnMut(BoundTypeVarInstance<'db>, Type<'db>, TypeVarVariance, TypeContext<'db>),
{ {
let try_visit = &mut |type_var, ty, variance, tcx| -> Result<(), ()> { self.visit_specialization_impl(
f(type_var, ty, variance, tcx);
Ok(())
};
let _ = self.try_visit_specialization(db, tcx, try_visit);
}
pub(crate) fn try_visit_specialization<F, E>(
self,
db: &'db dyn Db,
tcx: TypeContext<'db>,
mut f: F,
) -> Result<(), E>
where
F: FnMut(
BoundTypeVarInstance<'db>,
Type<'db>,
TypeVarVariance,
TypeContext<'db>,
) -> Result<(), E>,
{
self.try_visit_specialization_impl(
db, db,
tcx, tcx,
TypeVarVariance::Covariant, TypeVarVariance::Covariant,
&mut f, &mut f,
&SpecializationVisitor::default(), &SpecializationVisitor::default(),
) );
} }
fn try_visit_specialization_impl<E>( fn visit_specialization_impl(
self, self,
db: &'db dyn Db, db: &'db dyn Db,
tcx: TypeContext<'db>, tcx: TypeContext<'db>,
polarity: TypeVarVariance, polarity: TypeVarVariance,
f: &mut dyn FnMut( f: &mut dyn FnMut(BoundTypeVarInstance<'db>, Type<'db>, TypeVarVariance, TypeContext<'db>),
BoundTypeVarInstance<'db>,
Type<'db>,
TypeVarVariance,
TypeContext<'db>,
) -> Result<(), E>,
visitor: &SpecializationVisitor<'db>, visitor: &SpecializationVisitor<'db>,
) -> Result<(), E> { ) {
let instance = match self { let instance = match self {
Type::Union(union) => { Type::Union(union) => {
for element in union.elements(db) { for element in union.elements(db) {
element.try_visit_specialization_impl(db, tcx, polarity, f, visitor)?; element.visit_specialization_impl(db, tcx, polarity, f, visitor);
} }
return Ok(()); return;
} }
Type::Intersection(intersection) => { Type::Intersection(intersection) => {
for element in intersection.positive(db) { for element in intersection.positive(db) {
element.try_visit_specialization_impl(db, tcx, polarity, f, visitor)?; element.visit_specialization_impl(db, tcx, polarity, f, visitor);
} }
return Ok(()); return;
} }
Type::TypeAlias(alias) => { Type::TypeAlias(alias) => {
visitor.try_visit(self, || { visitor.visit(self, || {
alias alias
.value_type(db) .value_type(db)
.try_visit_specialization_impl(db, tcx, polarity, f, visitor) .visit_specialization_impl(db, tcx, polarity, f, visitor);
})?; });
return;
return Ok(());
} }
Type::NominalInstance(instance) => instance, Type::NominalInstance(instance) => instance,
Type::ProtocolInstance(protocol) => match protocol.to_nominal_instance() { Type::ProtocolInstance(protocol) => match protocol.to_nominal_instance() {
Some(instance) => instance, Some(instance) => instance,
None => return Ok(()), None => return,
}, },
_ => return Ok(()), _ => return,
}; };
let (class_literal, Some(specialization)) = instance.class(db).class_literal(db) else { let (class_literal, Some(specialization)) = instance.class(db).class_literal(db) else {
return Ok(()); return;
}; };
let generic_context = specialization.generic_context(db); let generic_context = specialization.generic_context(db);
@ -4017,14 +3989,12 @@ impl<'db> Type<'db> {
let variance = type_var.variance_with_polarity(db, polarity); let variance = type_var.variance_with_polarity(db, polarity);
let narrowed_tcx = TypeContext::new(tcx_mappings.get(&type_var.identity(db)).copied()); let narrowed_tcx = TypeContext::new(tcx_mappings.get(&type_var.identity(db)).copied());
f(type_var, *ty, variance, narrowed_tcx)?; f(type_var, *ty, variance, narrowed_tcx);
visitor.try_visit(*ty, || { visitor.visit(*ty, || {
ty.try_visit_specialization_impl(db, narrowed_tcx, variance, f, visitor) ty.visit_specialization_impl(db, narrowed_tcx, variance, f, visitor);
})?; });
} }
Ok(())
} }
/// Return true if there is just a single inhabitant for this type. /// Return true if there is just a single inhabitant for this type.

View File

@ -122,14 +122,14 @@ impl<Tag, T: Hash + Eq + Clone, R: Clone> CycleDetector<Tag, T, R> {
ret ret
} }
pub fn try_visit<E>(&self, item: T, func: impl FnOnce() -> Result<R, E>) -> Result<R, E> { pub fn try_visit(&self, item: T, func: impl FnOnce() -> Option<R>) -> Option<R> {
if let Some(val) = self.cache.borrow().get(&item) { if let Some(val) = self.cache.borrow().get(&item) {
return Ok(val.clone()); return Some(val.clone());
} }
// We hit a cycle // We hit a cycle
if !self.seen.borrow_mut().insert(item.clone()) { if !self.seen.borrow_mut().insert(item.clone()) {
return Ok(self.fallback.clone()); return Some(self.fallback.clone());
} }
// Check depth limit to prevent stack overflow from recursive generic protocols // Check depth limit to prevent stack overflow from recursive generic protocols
@ -137,7 +137,7 @@ impl<Tag, T: Hash + Eq + Clone, R: Clone> CycleDetector<Tag, T, R> {
let current_depth = self.depth.get(); let current_depth = self.depth.get();
if current_depth >= MAX_RECURSION_DEPTH { if current_depth >= MAX_RECURSION_DEPTH {
self.seen.borrow_mut().pop(); self.seen.borrow_mut().pop();
return Ok(self.fallback.clone()); return Some(self.fallback.clone());
} }
self.depth.set(current_depth + 1); self.depth.set(current_depth + 1);
@ -147,7 +147,7 @@ impl<Tag, T: Hash + Eq + Clone, R: Clone> CycleDetector<Tag, T, R> {
self.seen.borrow_mut().pop(); self.seen.borrow_mut().pop();
self.cache.borrow_mut().insert(item, ret.clone()); self.cache.borrow_mut().insert(item, ret.clone());
Ok(ret) Some(ret)
} }
} }

View File

@ -1926,14 +1926,14 @@ impl<'db> SpecializationBuilder<'db> {
builder.infer(formal_identity, formal)?; builder.infer(formal_identity, formal)?;
} }
builder.type_mappings().clone() builder.into_type_mappings()
}; };
// Collect the actual type to which each formal type variable is mapped. // Collect the actual type to which each formal type variable is mapped.
let forward_type_mappings = { let forward_type_mappings = {
let mut builder = SpecializationBuilder::new(self.db, inferable); let mut builder = SpecializationBuilder::new(self.db, inferable);
builder.infer(formal_identity, actual)?; builder.infer(formal_identity, actual)?;
builder.type_mappings().clone() builder.into_type_mappings()
}; };
// If there are no forward type mappings, try the other direction. // If there are no forward type mappings, try the other direction.