[ty] Use "typeguard constraints" for two kinds of tuple narrowing (#22348)

## Summary

Since we've already filtered the union in these locations, it seems like
needless overhead to then intersect the previous union with the filtered
union. We know what that intersection will simplify to: it will simplify
to the filtered union. So rather than using a regular intersection-based
constraint, we can use a "typeguard constraint", which will just
directly replace the previous type with the new type instead of creating
an intersection.

## Test Plan

- Existing tests all pass
- The primer report should be clean
This commit is contained in:
Alex Waygood
2026-01-13 23:37:09 +00:00
committed by GitHub
parent 4ebf10cf1b
commit ddd2fc7a90

View File

@@ -1037,8 +1037,8 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> {
&& rhs_ty.is_singleton(self.db)
{
let is_positive_check = is_positive == (ops[0] == ast::CmpOp::Is);
let filtered: Vec<_> = union
.elements(self.db)
let union_elements = union.elements(self.db);
let filtered: Vec<_> = union_elements
.iter()
.filter(|elem| {
elem.as_nominal_instance()
@@ -1056,11 +1056,11 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> {
})
.copied()
.collect();
if filtered.len() < union.elements(self.db).len() {
if filtered.len() < union_elements.len() {
let place = self.expect_place(&subscript_place_expr);
constraints.insert(
place,
NarrowingConstraint::regular(UnionType::from_elements(self.db, filtered)),
NarrowingConstraint::typeguard(UnionType::from_elements(self.db, filtered)),
);
}
}
@@ -1741,8 +1741,8 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> {
}
// Filter the union based on whether each tuple element at the index could match the rhs.
let filtered: Vec<_> = union
.elements(self.db)
let union_elements = union.elements(self.db);
let filtered: Vec<_> = union_elements
.iter()
.filter(|elem| {
elem.as_nominal_instance()
@@ -1762,11 +1762,11 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> {
.collect();
// Only create a constraint if we actually narrowed something.
if filtered.len() < union.elements(self.db).len() {
if filtered.len() < union_elements.len() {
let place = self.expect_place(&subscript_place_expr);
Some((
place,
NarrowingConstraint::regular(UnionType::from_elements(self.db, filtered)),
NarrowingConstraint::typeguard(UnionType::from_elements(self.db, filtered)),
))
} else {
None