[ty] Collapse `never` paths in constraint set BDDs (#21880)

#21744 fixed some non-determinism in our constraint set implementation
by switching our BDD representation from being "fully reduced" to being
"quasi-reduced". We still deduplicate identical nodes (via salsa
interning), but we removed the logic to prune redundant nodes (one with
identical outgoing true and false edges). This ensures that the BDD
"remembers" all of the individual constraints that it was created with.

However, that comes at the cost of creating larger BDDs, and on #21551
that was causing performance issues. `scikit-learn` was producing a
function signature with dozens of overloads, and we were trying to
create a constraint set that would map a return type typevar to any of
those overload's return types. This created a combinatorial explosion in
the BDD, with by far most of the BDD paths leading to the `never`
terminal.

This change updates the quasi-reduction logic to prune nodes that are
redundant _because both edges lead to the `never` terminal_. In this
case, we don't need to "remember" that constraint, since no assignment
to it can lead to a valid specialization. So we keep the "memory" of our
quasi-reduced structure, while still pruning large unneeded portions of
the BDD structure.

Pulling this out of https://github.com/astral-sh/ruff/pull/21551 for
separate review.
This commit is contained in:
Douglas Creager 2025-12-09 18:22:54 -05:00 committed by GitHub
parent f3714fd3c1
commit 270b8d1d14
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 4 additions and 3 deletions

View File

@ -794,6 +794,9 @@ impl<'db> Node<'db> {
root_constraint.ordering(db) > constraint.ordering(db)
})
);
if if_true == Node::AlwaysFalse && if_false == Node::AlwaysFalse {
return Node::AlwaysFalse;
}
Self::Interior(InteriorNode::new(db, constraint, if_true, if_false))
}
@ -3446,9 +3449,7 @@ mod tests {
(U = bool)
always
never
(U = str)
never
never
never
"#}
.trim_end();