[ty] Avoid temporarily storing invalid multi-inference attempts (#22103)
## Summary I missed this in https://github.com/astral-sh/ruff/pull/22062. This avoids exponential runtime in the following snippet: ```py class X1: ... class X2: ... class X3: ... class X4: ... class X5: ... class X6: ... ... def f( x: list[X1 | None] | list[X2 | None] | list[X3 | None] | list[X4 | None] | list[X5 | None] | list[X6 | None] ... ): ... def g[T](x: T) -> list[T]: return [x] def id[T](x: T) -> T: return x f(id(id(id(id(g(X64())))))) ``` Eventually I want to refactor our multi-inference infrastructure (which is currently very brittle) to handle this implicitly, but this is a temporary performance fix until that happens.
This commit is contained in:
@@ -7458,13 +7458,23 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||
}
|
||||
};
|
||||
|
||||
self.store_expression_type(expression, ty);
|
||||
self.store_expression_type_impl(expression, ty, tcx);
|
||||
|
||||
ty
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn store_expression_type(&mut self, expression: &ast::Expr, ty: Type<'db>) {
|
||||
self.store_expression_type_impl(expression, ty, TypeContext::default());
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn store_expression_type_impl(
|
||||
&mut self,
|
||||
expression: &ast::Expr,
|
||||
ty: Type<'db>,
|
||||
tcx: TypeContext<'db>,
|
||||
) {
|
||||
if self.deferred_state.in_string_annotation()
|
||||
|| self.inner_expression_inference_state.is_get()
|
||||
{
|
||||
@@ -7493,7 +7503,14 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||
self.expressions
|
||||
.entry(expression.into())
|
||||
.and_modify(|current| {
|
||||
*current = IntersectionType::from_elements(db, [*current, ty]);
|
||||
// Avoid storing "failed" multi-inference attempts, which can lead to
|
||||
// unnecessary union simplification overhead.
|
||||
if tcx
|
||||
.annotation
|
||||
.is_none_or(|tcx| ty.is_assignable_to(db, tcx))
|
||||
{
|
||||
*current = IntersectionType::from_elements(db, [*current, ty]);
|
||||
}
|
||||
})
|
||||
.or_insert(ty);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user