[ty] Eagerly evaluate TYPE_CHECKING constraints (#19044)

## Summary

Evaluate `TYPE_CHECKING` to `ALWAYS_TRUE` and `not TYPE_CHECKING` to
`ALWAYS_FALSE` during semantic index building. This is a follow-up to
https://github.com/astral-sh/ruff/pull/18998 and is in principle just a
performance optimization. We see some (favorable) ecosystem changes
because we can eliminate definitely-unreachable branches early now and
retain narrowing constraints without solving
https://github.com/astral-sh/ty/issues/690 first.
This commit is contained in:
David Peter 2025-07-01 11:05:52 +02:00 committed by GitHub
parent b8653a9d3a
commit 4016521bf6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -542,15 +542,31 @@ impl<'db, 'ast> SemanticIndexBuilder<'db, 'ast> {
}
fn build_predicate(&mut self, predicate_node: &ast::Expr) -> PredicateOrLiteral<'db> {
// Some commonly used test expressions are eagerly evaluated as `true`
// or `false` here for performance reasons. This list does not need to
// be exhaustive. More complex expressions will still evaluate to the
// correct value during type-checking.
fn resolve_to_literal(node: &ast::Expr) -> Option<bool> {
match node {
ast::Expr::BooleanLiteral(ast::ExprBooleanLiteral { value, .. }) => Some(*value),
ast::Expr::Name(ast::ExprName { id, .. }) if id == "TYPE_CHECKING" => Some(true),
ast::Expr::UnaryOp(ast::ExprUnaryOp {
op: ast::UnaryOp::Not,
operand,
..
}) => Some(!resolve_to_literal(operand)?),
_ => None,
}
}
let expression = self.add_standalone_expression(predicate_node);
if let Some(boolean_literal) = predicate_node.as_boolean_literal_expr() {
PredicateOrLiteral::Literal(boolean_literal.value)
} else {
PredicateOrLiteral::Predicate(Predicate {
match resolve_to_literal(predicate_node) {
Some(literal) => PredicateOrLiteral::Literal(literal),
None => PredicateOrLiteral::Predicate(Predicate {
node: PredicateNode::Expression(expression),
is_positive: true,
})
}),
}
}