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

Code before:
                    // `object` is a subtype of `object`
                    _ if target.is_object() => ConstraintSet::from(true),
                    // `object` is a subtype of dynamic types
                    Type::Dynamic(_) => ConstraintSet::from(true),
                    // These cases need more complex checking - delegate to full machinery
                    // (TypeVar needs special handling for inference)
                    Type::Union(_)
                    | Type::ProtocolInstance(_)
                    | Type::Intersection(_)
                    | Type::TypeVar(_) => Type::object().has_relation_to_impl(
                        db,
                        target,
                        inferable,
                        relation,
                        relation_visitor,
                        disjointness_visitor,
                    ),
                    // `object` is not a subtype of any other type
                    _ => ConstraintSet::from(false),
                }
            }

            (Type::Intersection(intersection), _) => {
                // An intersection type is a subtype of another type if at least one of its
                // positive elements is a subtype of that type.
                intersection.positive(db).iter().when_any(db, |&elem_ty| {
                    elem_ty.has_relation_to_impl(
                        db,
                        target,
                        inferable,
                        relation,
                        relation_visitor,
                        disjointness_visitor,
                    )
                })
            }

            // Other than the special cases checked above, no other types are a subtype of a
            // typevar, since there's no guarantee what type the typevar will be specialized to.
            // (If the typevar is bounded, it might be specialized to a smaller type than the
            // bound. This is true even if the bound is a final class, since the typevar can still
            // be specialized to `Never`.)
            (_, Type::TypeVar(bound_typevar)) if !bound_typevar.is_inferable(db, inferable) => {
                ConstraintSet::from(false)
            }

            (_, Type::TypeVar(typevar))
                if typevar.is_inferable(db, inferable)
                    && relation.is_assignability()
                    && typevar.typevar(db).upper_bound(db).is_none_or(|bound| {
                        !self

Review comment (bug):
Wait, this commit removed the `.positive_elements_or_object` here? So it will show full recovery of the regression, but should fail the added test?

Code after:
                // we treat `object` as the implicit positive element (e.g., `~str` is semantically
                // `object & ~str`).
                intersection
                    .positive_elements_or_object(db)
                    .when_any(db, |elem_ty| {
                        elem_ty.has_relation_to_impl(
                            db,
                            target,
                            inferable,
                            relation,
                            relation_visitor,
                            disjointness_visitor,
                        )
                    })
            }

            // Other than the special cases checked above, no other types are a subtype of a
            // typevar, since there's no guarantee what type the typevar will be specialized to.
            // (If the typevar is bounded, it might be specialized to a smaller type than the
            // bound. This is true even if the bound is a final class, since the typevar can still
            // be specialized to `Never`.)
            (_, Type::TypeVar(bound_typevar)) if !bound_typevar.is_inferable(db, inferable) => {
                ConstraintSet::from(false)
            }

            (_, Type::TypeVar(typevar))
                if typevar.is_inferable(db, inferable)
                    && relation.is_assignability()
                    && typevar.typevar(db).upper_bound(db).is_none_or(|bound| {
                        !self
                            .has_relation_to_impl(
                                db,
                                bound,
                                inferable,
                                relation,
                                relation_visitor,
                                disjointness_visitor,
                            )
                            .is_never_satisfied(db)
                    }) =>
            {
                // TODO: record the unification constraints

                typevar.typevar(db).upper_bound(db).when_none_or(|bound| {
                    self.has_relation_to_impl(
                        db,
                        bound,
                        inferable,
                        relation,
                        relation_visitor,
                        disjointness_visitor,