Skip to content

Commit 354ec66

Browse files
committed
skip typevar propagation when it's not helpful
1 parent 8cae925 commit 354ec66

File tree

2 files changed

+19
-8
lines changed

2 files changed

+19
-8
lines changed

crates/ty_python_semantic/resources/mdtest/type_properties/implies_subtype_of.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,9 +335,7 @@ def mutually_constrained[T, U]():
335335

336336
# If (T = U ∧ U = int), then (T = int) must be true as well. That is an equality constraint, so
337337
# even though T is invariant, it does imply that (Invariant[T] ≤ Invariant[int]).
338-
given_int = ConstraintSet.range(Never, T, U) & ConstraintSet.range(Never, U, int)
339-
# TODO: no error
340-
# error: [static-assert-error]
338+
given_int = ConstraintSet.range(U, T, U) & ConstraintSet.range(int, U, int)
341339
static_assert(given_int.implies_subtype_of(Invariant[T], Invariant[int]))
342340
static_assert(not given_int.implies_subtype_of(Invariant[T], Invariant[bool]))
343341
static_assert(not given_int.implies_subtype_of(Invariant[T], Invariant[str]))

crates/ty_python_semantic/src/types/constraints.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,10 +1427,12 @@ impl<'db> InteriorNode<'db> {
14271427
_ => continue,
14281428
};
14291429

1430-
let new_node = Node::new_constraint(
1431-
db,
1432-
ConstrainedTypeVar::new(db, constrained_typevar, new_lower, new_upper),
1433-
);
1430+
let new_constraint =
1431+
ConstrainedTypeVar::new(db, constrained_typevar, new_lower, new_upper);
1432+
if seen_constraints.contains(&new_constraint) {
1433+
continue;
1434+
}
1435+
let new_node = Node::new_constraint(db, new_constraint);
14341436
let positive_left_node =
14351437
Node::new_satisfied_constraint(db, left_constraint.when_true());
14361438
let positive_right_node =
@@ -1444,7 +1446,18 @@ impl<'db> InteriorNode<'db> {
14441446
continue;
14451447
}
14461448

1447-
// From here on out we know that both constraints constrain the same typevar.
1449+
// From here on out we know that both constraints constrain the same typevar. The
1450+
// clause above will propagate all that we know about the current typevar relative to
1451+
// other typevars, producing constraints on this typevar that have concrete lower/upper
1452+
// bounds. That means we can skip the simplifications below if any bound is another
1453+
// typevar.
1454+
if left_constraint.lower(db).is_type_var()
1455+
|| left_constraint.upper(db).is_type_var()
1456+
|| right_constraint.lower(db).is_type_var()
1457+
|| right_constraint.upper(db).is_type_var()
1458+
{
1459+
continue;
1460+
}
14481461

14491462
// Containment: The range of one constraint might completely contain the range of the
14501463
// other. If so, there are several potential simplifications.

0 commit comments

Comments
 (0)