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

Code before:

                            if let Some(params) = transformer_params {
                                // If this function was called with a keyword argument like
                                // `order=False`, we extract the argument type and overwrite
                                // the corresponding flag in `dataclass_params`.
                                let dataclass_params =
                                    DataclassParams::from_transformer_params(db, params);
                                let mut flags = dataclass_params.flags(db);

                                for (param, flag) in DATACLASS_FLAGS {
                                    if let Ok(Some(Type::BooleanLiteral(value))) =
                                        overload.parameter_type_by_name(param, false)
                                    {
                                        flags.set(*flag, value);
                                    }
                                }

                                let dataclass_params = DataclassParams::new(
                                    db,
                                    flags,
                                    dataclass_params.field_specifiers(db),
                                );

                                // If the return type is class-like and the first argument is a
                                // class, return it with dataclass params applied. Otherwise,
                                // return a `DataclassDecorator` for application to a class later.
                                let declared_return_type = overload.return_type();
                                let returns_class = matches!(
                                    declared_return_type,
                                    Type::ClassLiteral(_)
                                        | Type::GenericAlias(_)
                                        | Type::SubclassOf(_)
                                );

                                if returns_class {
                                    match overload.parameter_types().first() {
                                        Some(Some(Type::ClassLiteral(class_literal))) => {
                                            overload.set_return_type(Type::from(
                                                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),
                                                ),
                                            ));
                                        }
                                        Some(Some(Type::GenericAlias(generic_alias))) => {

Review comment (bug):
I think this is wrong. It's intended to address cases like:
```python
@dataclass_transform()
def hydrated_dataclass(target: type, *, frozen: bool = False) -> Callable[[type[T]], type[T]]:
    def decorator(cls: type[T]) -> type[T]:
        return cls
    return decorator

@hydrated_dataclass(SomeConfig, frozen=True)
class MyConfig:
    pass
```

If we make this change _without_ this declared return type handling, then `hydrated_dataclass(SomeConfig, frozen=True)` returns `type[SomeConfig]` with dataclass params, and we apply _that_ as a decorator.

Code after:
                        }

                        Some(KnownFunction::NamedTuple) => {
                            overload
                                .set_return_type(todo_type!("Support for functional `namedtuple`"));
                        }

                        _ => {
                            // Ideally, either the implementation, or exactly one of the overloads
                            // of the function can have the dataclass_transform decorator applied.
                            // However, we do not yet enforce this, and in the case of multiple
                            // applications of the decorator, we will only consider the last one.
                            let transformer_params = function_type
                                .iter_overloads_and_implementation(db)
                                .rev()
                                .find_map(|function_overload| {
                                    function_overload.dataclass_transformer_params(db)
                                });

                            if let Some(params) = transformer_params {
                                // If this function was called with a keyword argument like
                                // `order=False`, we extract the argument type and overwrite
                                // the corresponding flag in `dataclass_params`.
                                let dataclass_params =
                                    DataclassParams::from_transformer_params(db, params);
                                let mut flags = dataclass_params.flags(db);

                                for (param, flag) in DATACLASS_FLAGS {
                                    if let Ok(Some(Type::BooleanLiteral(value))) =
                                        overload.parameter_type_by_name(param, false)
                                    {
                                        flags.set(*flag, value);
                                    }
                                }

                                let dataclass_params = DataclassParams::new(
                                    db,
                                    flags,
                                    dataclass_params.field_specifiers(db),
                                );

                                // The dataclass_transform spec doesn't clarify how to tell whether
                                // a decorated function is a decorator or a decorator factory. We
                                // use heuristics based on the number and type of positional arguments:
                                //
                                // - 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