From dedfa8a64212f9d170e6c96ec5ccf60f8a960da3 Mon Sep 17 00:00:00 2001 From: Douglas Creager Date: Tue, 11 Nov 2025 17:17:34 -0500 Subject: [PATCH] document --- .../src/types/constraints.rs | 14 +++++++-- .../src/types/signatures.rs | 30 +++++++------------ 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/crates/ty_python_semantic/src/types/constraints.rs b/crates/ty_python_semantic/src/types/constraints.rs index 232f66abda..9e6bfc82e9 100644 --- a/crates/ty_python_semantic/src/types/constraints.rs +++ b/crates/ty_python_semantic/src/types/constraints.rs @@ -294,7 +294,12 @@ impl<'db> ConstraintSet<'db> { } /// Updates this constraint set to hold the union of itself and another constraint set. - /// XXX: Document not commutative + /// + /// Because constraint sets track the set of inferable typevars, this operation is not + /// commutative! We keep the inferable set of the lhs. If the rhs has inferable typevars that + /// are not inferable in the lhs, those will be existentially quantified away. The result will + /// only mention typevars that are inferable in the lhs, or which both sides consider + /// non-inferable. pub(crate) fn union(&mut self, db: &'db dyn Db, other: Self) -> Self { let other = other.reduce_inferable(db, self.inferable); self.node = self.node.or(db, other.node); @@ -302,7 +307,12 @@ impl<'db> ConstraintSet<'db> { } /// Updates this constraint set to hold the intersection of itself and another constraint set. - /// XXX: Document not commutative + /// + /// Because constraint sets track the set of inferable typevars, this operation is not + /// commutative! We keep the inferable set of the lhs. If the rhs has inferable typevars that + /// are not inferable in the lhs, those will be existentially quantified away. The result will + /// only mention typevars that are inferable in the lhs, or which both sides consider + /// non-inferable. pub(crate) fn intersect(&mut self, db: &'db dyn Db, other: Self) -> Self { let other = other.reduce_inferable(db, self.inferable); self.node = self.node.and(db, other.node); diff --git a/crates/ty_python_semantic/src/types/signatures.rs b/crates/ty_python_semantic/src/types/signatures.rs index 3161f156d4..19eee55f08 100644 --- a/crates/ty_python_semantic/src/types/signatures.rs +++ b/crates/ty_python_semantic/src/types/signatures.rs @@ -651,22 +651,6 @@ impl<'db> Signature<'db> { inferable: InferableTypeVars<'db>, visitor: &IsEquivalentVisitor<'db>, ) -> ConstraintSet<'db> { - self.is_equivalent_to_inner(db, other, inferable, visitor) - .reduce_inferable(db, inferable) - } - - fn is_equivalent_to_inner( - &self, - db: &'db dyn Db, - other: &Signature<'db>, - inferable: InferableTypeVars<'db>, - visitor: &IsEquivalentVisitor<'db>, - ) -> ConstraintSet<'db> { - // The typevars in self and other should also be considered inferable when checking whether - // two signatures are equivalent. - let inferable = inferable.merge(db, self.inferable_typevars(db)); - let inferable = inferable.merge(db, other.inferable_typevars(db)); - let mut result = ConstraintSet::always(inferable); let mut check_types = |self_type: Option>, other_type: Option>| { let self_type = self_type.unwrap_or(Type::unknown()); @@ -756,15 +740,23 @@ impl<'db> Signature<'db> { relation_visitor: &HasRelationToVisitor<'db>, disjointness_visitor: &IsDisjointVisitor<'db>, ) -> ConstraintSet<'db> { - self.has_relation_to_inner( + // If this callable is generic, then `inner` will add all of our typevars to the + // `inferable` set, since we only need to find one specialization that causes the check to + // succeed. + let when = self.has_relation_to_inner( db, other, inferable, relation, relation_visitor, disjointness_visitor, - ) - .reduce_inferable(db, inferable) + ); + + // But the caller does not need to consider those extra typevars. Whatever constraint set + // we produce, we reduce it back down to the inferable set that the caller asked about. + // If we introduced new inferable typevars, those will be existentially quantified away + // before returning. + when.reduce_inferable(db, inferable) } fn has_relation_to_inner(