Repository: rust-lang/rust-analyzer (rust)

Issue:
Building hover information for fn pointers from generic with impl args panics.
<!--
Troubleshooting guide: https://rust-analyzer.github.io/manual.html#troubleshooting
Forum for questions: https://users.rust-lang.org/c/ide/14

Before submitting, please make sure that you're not running into one of these known issues:

 1. on-the-fly diagnostics are mostly unimplemented (`cargo check` diagnostics will be shown when saving a file): #3107

Otherwise please try to provide information which will help us to fix the issue faster. Minimal reproducible examples with few dependencies are especially lovely <3.
-->

While trying out https://github.com/rust-lang/rust-analyzer/pull/17809 on mozilla-central, I noticed a failure in the time crate when building the hover information for the `format_number` function pointer [here](https://github.com/time-rs/time/blob/866c3a0c795445b15bfcb18cb7f005827de0db1c/time/src/formatting/mod.rs#L309).

I managed to write a failing test, see b93994b1356c1264dc6cc197496de9b2ddaddef4.

The issue is we end up in `hir_ty::display::generic_args_sans_defaults` with more binders than parameters. I'm not 100% sure how to fix this, I'm also surprised we don't hit this in more cases since `generic_args_sans_defaults` is called multiple times with different numbers of parameters at least [here](https://github.com/rust-lang/rust-analyzer/blob/b23142209ef632475915e858f5f20901ef7c12da/crates/hir-ty/src/display.rs#L1032) and [here](https://github.com/rust-lang/rust-analyzer/blob/b23142209ef632475915e858f5f20901ef7c12da/crates/hir-ty/src/display.rs#L1034).

**rust-analyzer version**: current `HEAD`

**rustc version**: rustc 1.80.0 (051478957 2024-07-21)

**editor or extension**: Kate / SCIP generator

**relevant settings**: 

**repository link (if public, optional)**: initially found with in [time](https://github.com/time-rs/time/blob/866c3a0c795445b15bfcb18cb7f005827de0db1c/time/src/formatting/mod.rs#L309), minimal test at b93994b1356c1264dc6cc197496de9b2ddaddef4

**code snippet to reproduce**: 
```rust
fn bar<const WIDTH: u8>(_: impl Copy) {}
fn test() {
    let f = bar::<3>;
    f(4);
}
```
hovering over `f` panics.


<!-- TRIAGEBOT_START -->

<!-- TRIAGEBOT_ASSIGN_START -->

<!-- TRIAGEBOT_ASSIGN_DATA_START$${"user":"ShoyuVanilla"}$$TRIAGEBOT_ASSIGN_DATA_END -->

<!-- TRIAGEBOT_ASSIGN_END -->
<!-- TRIAGEBOT_END -->

Pull request:
fix: Panic while rendering function type hint with impl trait arg
Fixes #17811

Patch:
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index a433ecfd77..47ea2f5347 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -1022,16 +1022,16 @@ impl HirDisplay for Ty {
                     // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
                     if parameters.len() - impl_ > 0 {
                         // `parameters` are in the order of fn's params (including impl traits), fn's lifetimes
+                        let without_impl = self_param as usize + type_ + const_ + lifetime;
                         // parent's params (those from enclosing impl or trait, if any).
-                        let (fn_params, other) =
-                            parameters.split_at(self_param as usize + type_ + const_ + lifetime);
-                        let (_impl, parent_params) = other.split_at(impl_);
+                        let (fn_params, parent_params) = parameters.split_at(without_impl + impl_);
                         debug_assert_eq!(parent_params.len(), parent_len);
 
                         let parent_params =
                             generic_args_sans_defaults(f, Some(generic_def_id), parent_params);
                         let fn_params =
-                            generic_args_sans_defaults(f, Some(generic_def_id), fn_params);
+                            &generic_args_sans_defaults(f, Some(generic_def_id), fn_params)
+                                [0..without_impl];
 
                         write!(f, "<")?;
                         hir_fmt_generic_arguments(f, parent_params, None)?;


Test patch:
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index ecfcf82e00..516e32ef91 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -8579,3 +8579,26 @@ fn main(a$0: T) {}
         "#]],
     );
 }
+
+#[test]
+fn hover_fn_with_impl_trait_arg() {
+    check(
+        r#"
+trait Foo {}
+impl Foo for bool {}
+fn bar<const WIDTH: u8>(_: impl Foo) {}
+fn test() {
+    let f = bar::<3>;
+    f$0(true);
+}
+"#,
+        expect![[r#"
+            *f*
+
+            ```rust
+            // size = 0, align = 1
+            let f: fn bar<3>(bool)
+            ```
+        "#]],
+    );
+}