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

Issue:
Panic when binding a type param to a trait with an impl type param
<!--
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.
-->

Rust-analyzer panics when hovering over T in the definition of test() function. Also panics when using the function anywhere in code. Rust compiles correctly.

**rust-analyzer version**: (eg. output of "rust-analyzer: Show RA Version" command, accessible in VSCode via <kbd>Ctrl/⌘</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>)
rust-analyzer version: 0.3.1940-standalone (f216be4a0 2024-04-27)

**rustc version**: (eg. output of `rustc -V`)
rustc 1.78.0 (9b00956e5 2024-04-29)

**editor or extension**: (eg. VSCode, Vim, Emacs, etc. For VSCode users, specify your extension version; for users of other editors, provide the distribution if applicable)
VSCode v0.3.1940

**relevant settings**: (eg. client settings, or environment variables like `CARGO`, `RUSTC`, `RUSTUP_HOME` or `CARGO_HOME`)

**repository link (if public, optional)**: (eg. [rust-analyzer](https://github.com/rust-lang/rust-analyzer))

**code snippet to reproduce**: 
```rust
trait A {
    type Item;
}

trait B<T: A> {}

fn test<T: B<impl A>>() {}

fn main() {}


```

Error:
```
[Error - 01:02:43] Request textDocument/hover failed.
  Message: request handler panicked: index out of bounds: the len is 1 but the index is 1
  Code: -32603 
Panic context:
> 
version: 0.3.1940-standalone (f216be4a0 2024-04-27)
request: textDocument/hover HoverParams {
    text_document: TextDocumentIdentifier {
        uri: Url {
            scheme: "file",
            cannot_be_a_base: false,
            username: "",
            password: None,
            host: None,
            port: None,
            path: "...",
            query: None,
            fragment: None,
        },
    },
    position: Position(
        Position {
            line: 6,
            character: 9,
        },
    ),
    work_done_progress_params: WorkDoneProgressParams {
        work_done_token: None,
    },
}

thread 'Worker' panicked at /Users/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/chalk-ir-0.97.0/src/fold/subst.rs:55:19:
index out of bounds: the len is 1 but the index is 1
stack backtrace:
   0: _rust_begin_unwind
   1: core::panicking::panic_fmt
   2: core::panicking::panic_bounds_check
   3: <chalk_ir::fold::subst::Subst<I> as chalk_ir::fold::TypeFolder<I>>::fold_free_var_ty
   4: chalk_ir::fold::TypeSuperFoldable::super_fold_with
   5: <smallvec::SmallVec<A> as core::iter::traits::collect::Extend<<A as smallvec::Array>::Item>>::extend
   6: chalk_ir::fold::boring_impls::<impl chalk_ir::fold::TypeFoldable<I> for chalk_ir::Substitution<I>>::try_fold_with
   7: chalk_ir::_::<impl chalk_ir::fold::TypeFoldable<I> for chalk_ir::WhereClause<I>>::try_fold_with
   8: chalk_ir::fold::binder_impls::<impl chalk_ir::fold::TypeFoldable<I> for chalk_ir::Binders<T>>::try_fold_with
   9: chalk_ir::Binders<T>::substitute
  10: <core::iter::adapters::cloned::Cloned<I> as core::iter::traits::iterator::Iterator>::try_fold
  11: <alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter
  12: hir::display::<impl hir_ty::display::HirDisplay for hir::TypeParam>::hir_fmt
  13: <hir_ty::display::HirDisplayWrapper<T> as core::fmt::Display>::fmt
  14: ide_db::defs::Definition::label
  15: ide::hover::render::definition
  16: ide::hover::hover_for_definition
  17: ide::hover::hover_simple
  18: ide::hover::hover
  19: salsa::Cancelled::catch
  20: rust_analyzer::handlers::request::handle_hover
  21: std::panicking::try
  22: core::ops::function::FnOnce::call_once{{vtable.shim}}
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
[Error - 01:02:43] Request textDocument/hover failed.
  Message: request handler panicked: index out of bounds: the len is 1 but the index is 1
  Code: -32603 
```

Pull request:
fix: Insert a generic arg for `impl Trait` when lowering generic args
Fixes #17191 

We are not inserting a generic arg when lowering generics like
```rust
fn foo<T: B<impl A>(..) { ... }
```
but when we are lowering predicates we do;

https://github.com/rust-lang/rust-analyzer/blob/aa00ddcf654a35ba0eafe17247cf189958d33182/crates/hir-ty/src/lower.rs#L1697-L1718
https://github.com/rust-lang/rust-analyzer/blob/aa00ddcf654a35ba0eafe17247cf189958d33182/crates/hir-ty/src/lower.rs#L310

and this mismatch causes index out of bound panic while substituting the predicates

Patch:
diff --git a/crates/hir-def/src/path/lower.rs b/crates/hir-def/src/path/lower.rs
index 7c39773aa6..70918a9358 100644
--- a/crates/hir-def/src/path/lower.rs
+++ b/crates/hir-def/src/path/lower.rs
@@ -194,6 +194,11 @@ pub(super) fn lower_generic_args(
         match generic_arg {
             ast::GenericArg::TypeArg(type_arg) => {
                 let type_ref = TypeRef::from_ast_opt(lower_ctx, type_arg.ty());
+                type_ref.walk(&mut |tr| {
+                    if let TypeRef::ImplTrait(bounds) = tr {
+                        lower_ctx.update_impl_traits_bounds(bounds.clone());
+                    }
+                });
                 args.push(GenericArg::Type(type_ref));
             }
             ast::GenericArg::AssocTypeArg(assoc_type_arg) => {


Test patch:
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index ac2dfea101..2819838612 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -2122,3 +2122,22 @@ fn test() {
 "#,
     )
 }
+
+#[test]
+fn issue_17191() {
+    check_types(
+        r#"
+trait A {
+    type Item;
+}
+
+trait B<T> {}
+
+fn foo<T: B<impl A>>() {}
+
+fn test() {
+    let f = foo;
+      //^ fn foo<{unknown}>()
+}"#,
+    );
+}