diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 7c481958d1..5a96d396ab 100644 --- a/crates/hir-ty/src/display.rs +++ b/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/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 516e32ef91..18f0aeba29 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -8602,3 +8602,31 @@ fn test() { "#]], ); } + +#[test] +fn issue_17871() { + check( + r#" +trait T { + fn f(); +} + +struct S {} +impl T for S { + fn f() {} +} + +fn main() { + let x$0 = S::f::; +} +"#, + expect![[r#" + *x* + + ```rust + // size = 0, align = 1 + let x: fn f() + ``` + "#]], + ); +}