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

Code before:
                                                ClassLiteral::new(
                                                    db,
                                                    class_literal.name(db),
                                                    class_literal.body_scope(db),
                                                    class_literal.known(db),
                                                    class_literal.deprecated(db),
                                                    class_literal.type_check_only(db),
                                                    Some(dataclass_params),
                                                    class_literal.dataclass_transformer_params(db),
                                                    class_literal.total_ordering(db),
                                                ),
                                            ));
                                        }
                                        Some(Some(Type::GenericAlias(generic_alias))) => {
                                            let class_literal = generic_alias.origin(db);
                                            let new_origin = ClassLiteral::new(
                                                db,
                                                class_literal.name(db),
                                                class_literal.body_scope(db),
                                                class_literal.known(db),
                                                class_literal.deprecated(db),
                                                class_literal.type_check_only(db),
                                                Some(dataclass_params),
                                                class_literal.dataclass_transformer_params(db),
                                                class_literal.total_ordering(db),
                                            );
                                            overload.set_return_type(Type::GenericAlias(
                                                GenericAlias::new(
                                                    db,
                                                    new_origin,
                                                    generic_alias.specialization(db),
                                                ),
                                            ));
                                        }
                                        _ => {}
                                    }
                                } else {
                                    overload.set_return_type(Type::DataclassDecorator(
                                        dataclass_params,
                                    ));
                                }
                            }
                        }
                    },

                    Type::KnownBoundMethod(KnownBoundMethodType::ConstraintSetRange) => {
                        let [Some(lower), Some(Type::TypeVar(typevar)), Some(upper)] =
                            overload.parameter_types()
                        else {
                            return;
                        };

Review comment (refactor):
Worth adding a `ClassLiteral::with_dataclass_params` to DRY this up a bit? We're mentioning a lot of extraneous field names here.

Code after:
                                // - Zero positional arguments: assume it's a decorator factory.
                                // - More than one positional argument: assume it's a decorator factory.
                                // - Exactly one positional argument that's a class: ambiguous, so check
                                //   the return type to disambiguate (class-like means decorate directly).
                                let mut positional_args = overload
                                    .signature
                                    .parameters()
                                    .iter()
                                    .zip(overload.parameter_types())
                                    .filter(|(param, ty)| ty.is_some() && !param.is_keyword_only())
                                    .map(|(_, ty)| ty);

                                let first_positional = positional_args.next();
                                let has_more = positional_args.next().is_some();

                                // Only attempt direct decoration if exactly one positional argument.
                                if !has_more {
                                    // Helper to check if return type is class-like.
                                    let returns_class = || {
                                        matches!(
                                            overload.return_type(),
                                            Type::ClassLiteral(_)
                                                | Type::GenericAlias(_)
                                                | Type::SubclassOf(_)
                                        )
                                    };

                                    match first_positional {
                                        Some(Some(Type::ClassLiteral(class_literal)))
                                            if returns_class() =>
                                        {
                                            overload.set_return_type(Type::from(
                                                class_literal.with_dataclass_params(
                                                    db,
                                                    Some(dataclass_params),
                                                ),
                                            ));
                                            continue;
                                        }
                                        Some(Some(Type::GenericAlias(generic_alias)))
                                            if returns_class() =>
                                        {
                                            let new_origin = generic_alias
                                                .origin(db)
                                                .with_dataclass_params(db, Some(dataclass_params));
                                            overload.set_return_type(Type::GenericAlias(
                                                GenericAlias::new(
                                                    db,
                                                    new_origin,
                                                    generic_alias.specialization(db),
                                                ),