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

Code before:
            return Err(CallErrorKind::PossiblyNotCallable);
        }

        Ok(())
    }

    fn is_callable(&self) -> bool {
        !self.overloads.is_empty()
    }

    /// Returns whether there were any errors binding this call site.
    ///
    /// This is true if either:
    /// - No overloads matched (all had type/arity errors).
    /// - A matching overload has errors (including semantic errors that don't affect
    ///   overload resolution, like applying `@dataclass` to a `NamedTuple`).
    fn has_binding_errors(&self) -> bool {
        let mut matching_overloads = self.matching_overloads();

        // If there are no matching overloads, we have binding errors.
        let Some((_, first_overload)) = matching_overloads.next() else {
            return true;
        };

        // If any matching overload has errors, we have binding errors.
        if !first_overload.errors.is_empty() {
            return true;
        }
        for (_, overload) in matching_overloads {
            if !overload.errors.is_empty() {
                return true;
            }
        }

        false
    }

    /// Returns the index of the matching overload in the form of [`MatchingOverloadIndex`].
    pub(crate) fn matching_overload_index(&self) -> MatchingOverloadIndex {
        let mut matching_overloads = self.matching_overloads();
        match matching_overloads.next() {
            None => MatchingOverloadIndex::None,
            Some((first, _)) => {
                if let Some((second, _)) = matching_overloads.next() {
                    let mut indexes = vec![first, second];
                    for (index, _) in matching_overloads {
                        indexes.push(index);
                    }
                    MatchingOverloadIndex::Multiple(indexes)
                } else {
                    MatchingOverloadIndex::Single(first)

Review comment (suggestion):
These errors would be "semantic" errors as defined in `affects_overload_resolution`, right? If so, the comment could be updated

Code after:
            return Err(CallErrorKind::PossiblyNotCallable);
        }

        Ok(())
    }

    fn is_callable(&self) -> bool {
        !self.overloads.is_empty()
    }

    /// Returns whether there were any errors binding this call site.
    ///
    /// This is true if either:
    /// - No overloads matched (all had type/arity errors).
    /// - A matching overload has errors (including semantic errors that don't affect
    ///   overload resolution, like applying `@dataclass` to a `NamedTuple`).
    fn has_binding_errors(&self) -> bool {
        let mut matching_overloads = self.matching_overloads();

        // If there are no matching overloads, we have binding errors.
        let Some((_, first_overload)) = matching_overloads.next() else {
            return true;
        };

        // If any matching overload has semantic errors (that don't affect overload
        // resolution), we have binding errors.
        if !first_overload.errors.is_empty() {
            return true;
        }
        for (_, overload) in matching_overloads {
            if !overload.errors.is_empty() {
                return true;
            }
        }

        false
    }

    /// Returns the index of the matching overload in the form of [`MatchingOverloadIndex`].
    pub(crate) fn matching_overload_index(&self) -> MatchingOverloadIndex {
        let mut matching_overloads = self.matching_overloads();
        match matching_overloads.next() {
            None => MatchingOverloadIndex::None,
            Some((first, _)) => {
                if let Some((second, _)) = matching_overloads.next() {
                    let mut indexes = vec![first, second];
                    for (index, _) in matching_overloads {
                        indexes.push(index);
                    }
                    MatchingOverloadIndex::Multiple(indexes)
                } else {