about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-08-15 07:05:47 +0000
committerbors <bors@rust-lang.org>2024-08-15 07:05:47 +0000
commite20180d0d3cd1cc1a22291940905e18e744852ea (patch)
treea9acfa192ad042ee9418308df76c074576353a20 /src
parent89cd5856d943220fb6f7dde893529aeb4d3fc4ff (diff)
parentb0183f81f4bd9745f4259fb1350202e71931ce34 (diff)
downloadrust-e20180d0d3cd1cc1a22291940905e18e744852ea.tar.gz
rust-e20180d0d3cd1cc1a22291940905e18e744852ea.zip
Auto merge of #17893 - ShoyuVanilla:issue-17871, r=flodiebold
fix: Panic while hovering associated function with type annotation on generic param that not inherited from its container type

Fixes #17871

We call `generic_args_sans_defaults` here;

https://github.com/rust-lang/rust-analyzer/blob/64a140527b383e3a2fe95908881624fc5374c60c/crates/hir-ty/src/display.rs#L1021-L1034

but the following substitution inside that function panic in #17871;

https://github.com/rust-lang/rust-analyzer/blob/64a140527b383e3a2fe95908881624fc5374c60c/crates/hir-ty/src/display.rs#L1468

it's because the `Binders.binder` inside `default_parameters` has a same length with the generics of the function we are hovering on, but the generics of it is split into two, `fn_params` and `parent_params`.
Because of this, it may panic if the function has one or more default parameters and both `fn_params` and `parent_params` are non-empty, like the case in the title of this PR.

So, we must call `generic_args_sans_default` first and then split it into `fn_params` and `parent_params`
Diffstat (limited to 'src')
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs15
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs28
2 files changed, 35 insertions, 8 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index 7c481958d1a..5a96d396ab8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -1019,26 +1019,25 @@ impl HirDisplay for Ty {
                     let (parent_len, self_param, type_, const_, impl_, lifetime) =
                         generics.provenance_split();
                     let parameters = parameters.as_slice(Interner);
+                    debug_assert_eq!(
+                        parameters.len(),
+                        parent_len + self_param as usize + type_ + const_ + impl_ + lifetime
+                    );
                     // 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 parameters =
+                            generic_args_sans_defaults(f, Some(generic_def_id), parameters);
                         let without_impl = self_param as usize + type_ + const_ + lifetime;
                         // parent's params (those from enclosing impl or trait, if any).
                         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)
-                                [0..without_impl];
 
                         write!(f, "<")?;
                         hir_fmt_generic_arguments(f, parent_params, None)?;
                         if !parent_params.is_empty() && !fn_params.is_empty() {
                             write!(f, ", ")?;
                         }
-                        hir_fmt_generic_arguments(f, fn_params, None)?;
+                        hir_fmt_generic_arguments(f, &fn_params[0..without_impl], None)?;
                         write!(f, ">")?;
                     }
                 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
index 516e32ef917..18f0aeba29e 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -8602,3 +8602,31 @@ fn test() {
         "#]],
     );
 }
+
+#[test]
+fn issue_17871() {
+    check(
+        r#"
+trait T {
+    fn f<A>();
+}
+
+struct S {}
+impl T for S {
+    fn f<A>() {}
+}
+
+fn main() {
+    let x$0 = S::f::<i32>;
+}
+"#,
+        expect![[r#"
+            *x*
+
+            ```rust
+            // size = 0, align = 1
+            let x: fn f<S, i32>()
+            ```
+        "#]],
+    );
+}