Repository: astral-sh/ruff
File: crates/ty_python_semantic/src/types/generics.rs (Rust)

Code before:
        self,
        db: &'db dyn Db,
        other: Self,
        inferable: InferableTypeVars<'_, 'db>,
        disjointness_visitor: &IsDisjointVisitor<'db>,
        relation_visitor: &HasRelationToVisitor<'db>,
    ) -> ConstraintSet<'db> {
        let generic_context = self.generic_context(db);
        if generic_context != other.generic_context(db) {
            return ConstraintSet::from(true);
        }

        if let (Some(self_tuple), Some(other_tuple)) = (self.tuple_inner(db), other.tuple_inner(db))
        {
            return self_tuple.is_disjoint_from_impl(
                db,
                other_tuple,
                inferable,
                disjointness_visitor,
                relation_visitor,
            );
        }

        let mut result = ConstraintSet::from(false);
        for (self_type, other_type) in std::iter::zip(self.types(db), other.types(db)) {
            let disjoint = self_type.is_disjoint_from_impl(
                db,
                *other_type,
                inferable,
                disjointness_visitor,
                relation_visitor,
            );

            if result.union(db, disjoint).is_always_satisfied(db) {
                return result;
            }
        }

        result
    }

    pub(crate) fn is_equivalent_to_impl(
        self,
        db: &'db dyn Db,
        other: Specialization<'db>,
        inferable: InferableTypeVars<'_, 'db>,
        visitor: &IsEquivalentVisitor<'db>,
    ) -> ConstraintSet<'db> {
        if self.materialization_kind(db) != other.materialization_kind(db) {
            return ConstraintSet::from(false);
        }

Review comment (suggestion):
I suppose this is only correct for covariant/contravariant types. Bivariant types are never disjoint, but I'm not sure what the corresponding relationship is for invariant types.

Code after:
        inferable: InferableTypeVars<'_, 'db>,
        disjointness_visitor: &IsDisjointVisitor<'db>,
        relation_visitor: &HasRelationToVisitor<'db>,
    ) -> ConstraintSet<'db> {
        let generic_context = self.generic_context(db);
        if generic_context != other.generic_context(db) {
            return ConstraintSet::from(true);
        }

        if let (Some(self_tuple), Some(other_tuple)) = (self.tuple_inner(db), other.tuple_inner(db))
        {
            return self_tuple.is_disjoint_from_impl(
                db,
                other_tuple,
                inferable,
                disjointness_visitor,
                relation_visitor,
            );
        }

        let types = itertools::izip!(
            generic_context.variables(db),
            self.types(db),
            other.types(db)
        );

        types.when_all(
            db,
            |(bound_typevar, self_type, other_type)| match bound_typevar.variance(db) {
                // TODO: This check can lead to false negatives.
                //
                // For example, `Foo[int]` and `Foo[bool]` are disjoint, even though `bool` is a subtype
                // of `int`. However, given two non-inferable type variables `T` and `U`, `Foo[T]` and
                // `Foo[U]` should not be considered disjoint, as `T` and `U` could be specialized to the
                // same type. We don't currently have a good typing relationship to represent this.
                TypeVarVariance::Invariant => self_type.is_disjoint_from_impl(
                    db,
                    *other_type,
                    inferable,
                    disjointness_visitor,
                    relation_visitor,
                ),

                // If `Foo[T]` is covariant in `T`, `Foo[Never]` is a subtype of `Foo[A]` and `Foo[B]`
                TypeVarVariance::Covariant => ConstraintSet::from(false),

                // If `Foo[T]` is contravariant in `T`, `Foo[A | B]` is a subtype of `Foo[A]` and `Foo[B]`
                TypeVarVariance::Contravariant => ConstraintSet::from(false),

                // If `Foo[T]` is bivariant in `T`, `Foo[A]` and `Foo[B]` are mutual subtypes.
                TypeVarVariance::Bivariant => ConstraintSet::from(false),