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

Code before:
    }
}

/// Format a list of elements as a human-readable enumeration.
///
/// Encloses every element in backticks (`1`, `2` and `3`).
pub(crate) fn format_enumeration<I, IT, D>(elements: I) -> String
where
    I: IntoIterator<IntoIter = IT>,
    IT: ExactSizeIterator<Item = D> + DoubleEndedIterator,
    D: std::fmt::Display,
{
    let mut elements = elements.into_iter();
    debug_assert!(elements.len() >= 2);

    let final_element = elements.next_back().unwrap();
    let penultimate_element = elements.next_back().unwrap();

    let mut buffer = String::new();
    for element in elements {
        write!(&mut buffer, "`{element}`, ").ok();
    }
    write!(&mut buffer, "`{penultimate_element}` and `{final_element}`").ok();

    buffer
}

/// An abstraction for mutating a diagnostic.
///
/// Callers likely should use `LintDiagnosticGuard` via
/// `InferContext::report_lint` instead. This guard is only intended for use
/// with non-lint diagnostics or non-type checking diagnostics. It is fundamentally lower level and easier to
/// get things wrong by using it.
///
/// Unlike `LintDiagnosticGuard`, this API does not guarantee that the
/// constructed `Diagnostic` not only has a primary annotation, but its
/// associated file is equivalent to the file being type checked. As a result,
/// if either is violated, then the `Drop` impl on `DiagnosticGuard` will
/// panic.
pub(super) struct DiagnosticGuard<'sink> {
    file: File,

    sink: &'sink std::cell::RefCell<TypeCheckDiagnostics>,

    /// The diagnostic that we want to report.
    ///
    /// This is always `Some` until the `Drop` impl.
    diag: Option<Diagnostic>,
}

impl std::ops::Deref for DiagnosticGuard<'_> {

Review comment (suggestion):
This is just a move except that `DiagnosticGuard` now stores a `file` and `sink` instead of a `&InferContext`

Code after:

/// Format a list of elements as a human-readable enumeration.
///
/// Encloses every element in backticks (`1`, `2` and `3`).
pub(crate) fn format_enumeration<I, IT, D>(elements: I) -> String
where
    I: IntoIterator<IntoIter = IT>,
    IT: ExactSizeIterator<Item = D> + DoubleEndedIterator,
    D: std::fmt::Display,
{
    let mut elements = elements.into_iter();
    debug_assert!(elements.len() >= 2);

    let final_element = elements.next_back().unwrap();
    let penultimate_element = elements.next_back().unwrap();

    let mut buffer = String::new();
    for element in elements {
        write!(&mut buffer, "`{element}`, ").ok();
    }
    write!(&mut buffer, "`{penultimate_element}` and `{final_element}`").ok();

    buffer
}

/// An abstraction for mutating a diagnostic.
///
/// Callers likely should use `LintDiagnosticGuard` via
/// `InferContext::report_lint` instead. This guard is only intended for use
/// with non-lint diagnostics or non-type checking diagnostics. It is fundamentally lower level and easier to
/// get things wrong by using it.
///
/// Unlike `LintDiagnosticGuard`, this API does not guarantee that the
/// constructed `Diagnostic` not only has a primary annotation, but its
/// associated file is equivalent to the file being type checked. As a result,
/// if either is violated, then the `Drop` impl on `DiagnosticGuard` will
/// panic.
pub(super) struct DiagnosticGuard<'sink> {
    /// The file of the primary span (to which file does this diagnostic belong).
    file: File,

    /// The target where to emit the diagnostic to.
    ///
    /// We use a [`RefCell`] here over a `&mut TypeCheckDiagnostics` to ensure the fact that
    /// `InferContext` (and other contexts with diagnostics) use a [`RefCell`] internally
    /// remains abstracted away. Specifically, we want to ensure that calling `report_lint` on
    /// `InferContext` twice doesn't result in a panic:
    ///
    /// ```ignore
    /// let diag1 = context.report_lint(...);
    ///