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

Code before:

        let owner = match owner_type {
            Type::Never => SuperOwnerKind::Dynamic(DynamicType::Unknown),
            Type::Dynamic(dynamic) => SuperOwnerKind::Dynamic(dynamic),
            Type::ClassLiteral(class) => SuperOwnerKind::Class(ClassType::NonGeneric(class)),
            Type::SubclassOf(subclass_of_type) => match subclass_of_type.subclass_of() {
                SubclassOfInner::Class(class) => SuperOwnerKind::Class(class),
                SubclassOfInner::Dynamic(dynamic) => SuperOwnerKind::Dynamic(dynamic),
                SubclassOfInner::TypeVar(bound_typevar) => {
                    let typevar = bound_typevar.typevar(db);
                    match typevar.bound_or_constraints(db) {
                        Some(TypeVarBoundOrConstraints::UpperBound(bound)) => {
                            // For ClassTypeVar, extract the class from the bound.
                            let class = match bound {
                                Type::NominalInstance(instance) => Some(instance.class(db)),
                                _ => bound.to_class_type(db),
                            };
                            match class {
                                Some(class) => SuperOwnerKind::ClassTypeVar(bound_typevar, class),
                                None => {
                                    return Err(BoundSuperError::AbstractOwnerType {
                                        owner_type,
                                        pivot_class: pivot_class_type,
                                        typevar_context: Some(typevar),
                                    });
                                }
                            }
                        }
                        Some(TypeVarBoundOrConstraints::Constraints(constraints)) => {
                            return build_constrained_union(
                                constraints,
                                bound_typevar,
                                typevar,
                                SuperOwnerKind::ClassTypeVar,
                            );
                        }
                        None => {
                            // No bound means the implicit upper bound is `object`.
                            let class = ClassType::object(db);
                            SuperOwnerKind::ClassTypeVar(bound_typevar, class)
                        }
                    }
                }
            },
            Type::NominalInstance(instance) => SuperOwnerKind::Instance(instance),

            Type::ProtocolInstance(protocol) => {
                if let Some(nominal_instance) = protocol.to_nominal_instance() {
                    SuperOwnerKind::Instance(nominal_instance)
                } else {
                    return Err(BoundSuperError::AbstractOwnerType {

Review comment (refactor):
I don't think the fallback `_ => bound.to_class_type(db),` is correct here. We've "unwrapped" the subclass-of type; the typevar within it should have a `NominalInstance` bound. Tests all pass with this change:

```suggestion
                            if let Type::NominalInstance(instance) = bound {
                                SuperOwnerKind::ClassTypeVar(bound_typevar, instance.class(db))
                            } else {
                                return Err(BoundSuperError::AbstractOwnerType {
                                    owner_type,
                                    pivot_class: pivot_class_type,
                                    typevar_context: Some(typevar),
                                });
                            }
```

Code after:
                                    ClassBase::Generic
                                    | ClassBase::Protocol
                                    | ClassBase::TypedDict => false,
                                    ClassBase::Class(superclass) => {
                                        superclass.class_literal(db).0 == pivot
                                    }
                                }) {
                                    return Err(BoundSuperError::FailingConditionCheck {
                                        pivot_class: pivot_class_type,
                                        owner: owner_type,
                                        typevar_context: Some(typevar),
                                    });
                                }
                            }
                            let owner = make_owner(bound_typevar, class);
                            builder = builder.add(Type::BoundSuper(BoundSuperType::new(
                                db,
                                pivot_class,
                                owner,
                            )));
                        }
                        None => {
                            // Delegate to the constraint to get better error messages
                            // if the constraint is incompatible with the pivot class.
                            builder = builder.add(delegate_to(*constraint)?);
                        }
                    }
                }
                Ok(builder.build())
            };

        let owner = match owner_type {
            Type::Never => SuperOwnerKind::Dynamic(DynamicType::Unknown),
            Type::Dynamic(dynamic) => SuperOwnerKind::Dynamic(dynamic),
            Type::ClassLiteral(class) => SuperOwnerKind::Class(ClassType::NonGeneric(class)),
            Type::SubclassOf(subclass_of_type) => match subclass_of_type.subclass_of() {
                SubclassOfInner::Class(class) => SuperOwnerKind::Class(class),
                SubclassOfInner::Dynamic(dynamic) => SuperOwnerKind::Dynamic(dynamic),
                SubclassOfInner::TypeVar(bound_typevar) => {
                    let typevar = bound_typevar.typevar(db);
                    match typevar.bound_or_constraints(db) {
                        Some(TypeVarBoundOrConstraints::UpperBound(bound)) => {
                            let class = match bound {
                                Type::NominalInstance(instance) => Some(instance.class(db)),
                                Type::ProtocolInstance(protocol) => protocol
                                    .to_nominal_instance()
                                    .map(|instance| instance.class(db)),
                                _ => None,
                            };
                            if let Some(class) = class {
                                SuperOwnerKind::ClassTypeVar(bound_typevar, class)