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

Code before:
        .collect();

    Some((definitions, callable_type))
}

/// Returns the definitions for an unary operator along with their callable types.
pub fn definitions_for_unary_op<'db>(
    db: &'db dyn Db,
    model: &SemanticModel<'db>,
    unary_op: &ast::ExprUnaryOp,
) -> Option<(Vec<ResolvedDefinition<'db>>, Type<'db>)> {
    let operand_ty = unary_op.operand.inferred_type(model);

    let unary_dunder_method = match unary_op.op {
        ast::UnaryOp::Invert => "__invert__",
        ast::UnaryOp::UAdd => "__pos__",
        ast::UnaryOp::USub => "__neg__",
        ast::UnaryOp::Not => "__bool__",
    };

    let bindings = match operand_ty.try_call_dunder(
        db,
        unary_dunder_method,
        CallArguments::none(),
        TypeContext::default(),
    ) {
        Ok(bindings) => bindings,
        Err(CallDunderError::MethodNotAvailable) if unary_op.op == ast::UnaryOp::Not => {
            // The runtime falls back to `__len__` for `not` if `__bool__` is not defined.
            match operand_ty.try_call_dunder(
                db,
                "__len__",
                CallArguments::none(),
                TypeContext::default(),
            ) {
                Ok(bindings) => bindings,
                Err(CallDunderError::MethodNotAvailable) => return None,
                Err(
                    CallDunderError::PossiblyUnbound(bindings)
                    | CallDunderError::CallError(_, bindings),
                ) => *bindings,
            }
        }
        Err(CallDunderError::MethodNotAvailable) => return None,
        Err(
            CallDunderError::PossiblyUnbound(bindings) | CallDunderError::CallError(_, bindings),
        ) => *bindings,
    };

    let callable_type = promote_literals_for_self(db, bindings.callable_type());


Review comment (suggestion):
I think I remember now facing a similar problem regarding using the `signature_type` on `Binding` struct that we saw during our call last week. For context, the `signature_type` would represent the `FunctionLiteral` which means the display would contain all the overloads and this is the main reason we need to use the display of `Signature` to display the _matching_ overload which leads to requiring https://github.com/astral-sh/ruff/pull/21438.

I faced this issue while implementing https://github.com/astral-sh/ruff/pull/18452 and the way I resolved it is by capturing the required information (`FunctionType`, `BoundMethodType`, etc. and the matching overload index) in [`MatchingOverloadLiteral`](https://github.com/astral-sh/ruff/blob/dcc451d4d2fcf76b4c930f6aaa2f66b4830f7a04/crates/ty_python_semantic/src/types/call/bind.rs#L4130-L4141) and implementing a [`.get`](https://github.com/astral-sh/ruff/blob/dcc451d4d2fcf76b4c930f6aaa2f66b4830f7a04/crates/ty_python_semantic/src/types/call/bind.rs#L4144-L4155) method to return the matching `OverloadLiteral`.

I think we could possibly use a similar approach to get the actual `OverloadLiteral` that needs to be displayed as it does [implement the `Display` trait](https://github.com/astral-sh/ruff/blob/dcc451d4d2fcf76b4c930f6aaa2f66b4830f7a04/crates/ty_python_semantic/src/types/display.rs#L757-L774). You might find it useful to go through this part of the code: https://github.com/astral-sh/ruff/blob/dcc451d4d2fcf76b4c930f6aaa2f66b4830f7a04/crates/ty_python_semantic/src/types/call/bind.rs#L2125-L2162

Another approach could be to expand the `DisplaySettings` to include the `matching_overload_index: MatchingOverloadIndex` which can then be used directly to filter the overloads at the display level. The `None` variant would display all the overloads.

Code after:
    if let Some(binding) = bindings.single_element()
        && binding.overloads().len() < 2
    {
        return None;
    }

    // Hand the overload resolution system as much type info as we have
    let args = CallArguments::from_arguments_typed(&call_expr.arguments, |_, splatted_value| {
        splatted_value.inferred_type(model)
    });

    // Try to resolve overloads with the arguments/types we have
    let mut resolved = bindings
        .match_parameters(db, &args)
        .check_types(db, &args, TypeContext::default(), &[])
        // Only use the Ok
        .iter()
        .flatten()
        .flat_map(|binding| {
            binding.matching_overloads().map(|(_, overload)| {
                overload
                    .signature
                    .display_with(db, DisplaySettings::default().multiline())
                    .to_string()
            })
        })
        .collect::<Vec<_>>();

    // If at the end of this we still got multiple signatures (or no signatures), give up
    if resolved.len() != 1 {
        return None;
    }

    resolved.pop()
}

/// Returns the definitions of the binary operation along with its callable type.
pub fn definitions_for_bin_op<'db>(
    db: &'db dyn Db,
    model: &SemanticModel<'db>,
    binary_op: &ast::ExprBinOp,
) -> Option<(Vec<ResolvedDefinition<'db>>, Type<'db>)> {
    let left_ty = binary_op.left.inferred_type(model);
    let right_ty = binary_op.right.inferred_type(model);

    let Ok(bindings) = Type::try_call_bin_op(db, left_ty, binary_op.op, right_ty) else {
        return None;
    };

    let callable_type = promote_literals_for_self(db, bindings.callable_type());