Repository: rust-lang/rust
File: compiler/rustc_hir_analysis/src/check/compare_impl_item.rs (Rust)

Code before:
                            .get(idx)
                            .and_then(|ident| *ident)
                            .map(|ident| ident.to_string())
                            .unwrap_or_else(|| format!("_{}", idx + 1));
                        format!("{name}: {ty}")
                    })
                    .collect::<Vec<_>>();

                let replacement = if existing.trim().is_empty() {
                    missing.join(", ")
                } else {
                    format!("{existing}, {}", missing.join(", "))
                };
                Some(("add the missing parameter from the trait", replacement))
            } else if impl_number_args > trait_number_args {
                let kept = impl_m_sig
                    .decl
                    .inputs
                    .iter()
                    .take(trait_number_args)
                    .filter_map(|arg| sm.span_to_snippet(arg.span).ok())
                    .collect::<Vec<_>>();
                let replacement = if kept.is_empty() { String::new() } else { kept.join(", ") };
                Some(("remove the extra parameter to match the trait", replacement))
            } else {
                None
            };

            if let (Some(span), Some((msg, replacement))) = (impl_inputs_span, suggestion_text) {
                err.span_suggestion_verbose(span, msg, replacement, Applicability::MaybeIncorrect);
            }
        }

        return Err(err.emit_unless_delay(delay));
    }

    Ok(())
}

fn find_param_bounds(snippet: &str) -> Option<(usize, usize)> {
    let start = snippet.find('(')?;
    let mut depth = 1usize;
    let bytes = snippet.as_bytes();
    let mut i = start + 1;
    while i < bytes.len() {
        match bytes[i] {
            b'(' => depth += 1,
            b')' => {
                depth -= 1;
                if depth == 0 {
                    return Some((start + 1, i));

Review comment (suggestion):
Nit: We already checked `trait_number_args != impl_number_args` above, this case should be unreachable.

Code after:
                "expected {}, found {}",
                potentially_plural_count(trait_number_args, "parameter"),
                impl_number_args
            ),
        );

        // Only emit verbose suggestions when the trait span isn’t local (e.g., cross-crate).
        if !trait_m.def_id.is_local() {
            let trait_sig = tcx.fn_sig(trait_m.def_id);
            let trait_arg_idents = tcx.fn_arg_idents(trait_m.def_id);
            let sm = tcx.sess.source_map();
            // Find the span of the space between the parentheses in a method.
            // fn foo(...) {}
            //        ^^^
            let impl_inputs_span = if let (Some(first), Some(last)) =
                (impl_m_sig.decl.inputs.first(), impl_m_sig.decl.inputs.last())
            {
                // We have inputs; construct the span from those.
                // fn foo( a: i32, b: u32 ) {}
                //        ^^^^^^^^^^^^^^^^
                let arg_idents = tcx.fn_arg_idents(impl_m.def_id);
                let first_lo = arg_idents
                    .get(0)
                    .and_then(|id| id.map(|id| id.span.lo()))
                    .unwrap_or(first.span.lo());
                Some(impl_m_sig.span.with_lo(first_lo).with_hi(last.span.hi()))
            } else {
                // We have no inputs; construct the span to the left of the last parenthesis
                // fn foo( ) {}
                //        ^
                // FIXME: Keep spans for function parentheses around to make this more robust.
                sm.span_to_snippet(impl_m_sig.span).ok().and_then(|s| {
                    let right_paren = s.as_bytes().iter().rposition(|&b| b == b')')?;
                    let pos = impl_m_sig.span.lo() + BytePos(right_paren as u32);
                    Some(impl_m_sig.span.with_lo(pos).with_hi(pos))
                })
            };
            let suggestion = match trait_number_args.cmp(&impl_number_args) {
                Ordering::Greater => {
                    // Span is right before the end parenthesis:
                    // fn foo(a: i32 ) {}
                    //              ^
                    let trait_inputs = trait_sig.skip_binder().inputs().skip_binder();
                    let missing = trait_inputs
                        .iter()
                        .enumerate()
                        .skip(impl_number_args)
                        .map(|(idx, ty)| {
                            let name = trait_arg_idents
                                .get(idx)
                                .and_then(|ident| *ident)