about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorShoyu Vanilla <modulo641@gmail.com>2024-12-06 01:10:46 +0900
committerShoyu Vanilla <modulo641@gmail.com>2024-12-06 01:10:46 +0900
commit70380736bc8e899d012011089fdd20d3faf6f70e (patch)
treea16ba0c8ac23544a1b44306afe7e02fd9c537f2e /src
parentb8db0c5a85608bf5e226577d85d811b92a68a24f (diff)
downloadrust-70380736bc8e899d012011089fdd20d3faf6f70e.tar.gz
rust-70380736bc8e899d012011089fdd20d3faf6f70e.zip
fix: Panic when displaying generic params with defaults
Diffstat (limited to 'src')
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs50
2 files changed, 55 insertions, 1 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 94a340fbec2..3dfa0e97cec 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -1047,10 +1047,14 @@ 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 {
+                        let params_len = parameters.len();
                         // `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;
+                        assert!(params_len >= parameters.len());
+                        let defaults = params_len - parameters.len();
+                        let without_impl =
+                            self_param as usize + type_ + const_ + lifetime - defaults;
                         // parent's params (those from enclosing impl or trait, if any).
                         let (fn_params, parent_params) = parameters.split_at(without_impl + impl_);
 
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 0986d5542cd..1c08514a672 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -9416,3 +9416,53 @@ fn f<T: UnCompat$0>
         "#]],
     );
 }
+
+#[test]
+fn issue_18613() {
+    check(
+        r#"
+fn main() {
+    struct S<T, D = bool>();
+    let x$0 = S::<()>;
+}"#,
+        expect![[r#"
+            *x*
+
+            ```rust
+            let x: fn S<()>() -> S<()>
+            ```
+
+            ---
+
+            size = 0, align = 1
+        "#]],
+    );
+
+    check(
+        r#"
+pub struct Global;
+pub struct Box<T, A = Global>(T, A);
+
+impl<T> Box<T> {
+    pub fn new(x: T) -> Self { loop {} }
+}
+
+pub struct String;
+
+fn main() {
+    let box_value$0 = Box::<String>new();
+}
+"#,
+        expect![[r#"
+            *box_value*
+
+            ```rust
+            let box_value: fn Box<String>(String, Global) -> Box<String>
+            ```
+
+            ---
+
+            size = 0, align = 1
+        "#]],
+    );
+}