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

Code before:
            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())
            {
                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 {
                sm.span_to_snippet(impl_m_sig.span).ok().and_then(|s| {
                    let bytes = s.as_bytes();
                    let right = bytes.iter().rposition(|&b| b == b')')?;
                    let mut depth = 0usize;
                    let mut left = None;
                    for i in (0..=right).rev() {
                        match bytes[i] {
                            b')' => depth += 1,
                            b'(' => {
                                depth -= 1;
                                if depth == 0 {
                                    left = Some(i);
                                    break;
                                }
                            }
                            _ => {}
                        }
                    }
                    let left = left?;
                    let lo = impl_m_sig.span.lo() + BytePos((left + 1) as u32);
                    let hi = impl_m_sig.span.lo() + BytePos(right as u32);
                    Some(impl_m_sig.span.with_lo(lo).with_hi(hi))
                })
            };
            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

Review comment (suggestion):
Nit: This could now take advantage of only being used when there are 0 arguments, right?

So maybe it should be simplified to the following?

```suggestion
                // 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))
                })
```


Code after:
            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)
                                .map(|ident| ident.to_string())
                                .unwrap_or_else(|| "_".to_string());
                            format!("{name}: {ty}")
                        })
                        .collect::<Vec<_>>();

                    if missing.is_empty() {
                        None
                    } else {
                        impl_inputs_span.map(|s| {