diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index 00289f9bfb411..a8ae43d52978d 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -54,13 +54,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     }
                     (ty::Param(expected), ty::Param(found)) => {
                         let generics = tcx.generics_of(body_owner_def_id);
-                        let e_span = tcx.def_span(generics.type_param(expected, tcx).def_id);
-                        if !sp.contains(e_span) {
-                            diag.span_label(e_span, "expected type parameter");
+                        if let Some(param) = generics.opt_type_param(expected, tcx) {
+                            let e_span = tcx.def_span(param.def_id);
+                            if !sp.contains(e_span) {
+                                diag.span_label(e_span, "expected type parameter");
+                            }
                         }
-                        let f_span = tcx.def_span(generics.type_param(found, tcx).def_id);
-                        if !sp.contains(f_span) {
-                            diag.span_label(f_span, "found type parameter");
+                        if let Some(param) = generics.opt_type_param(found, tcx) {
+                            let f_span = tcx.def_span(param.def_id);
+                            if !sp.contains(f_span) {
+                                diag.span_label(f_span, "found type parameter");
+                            }
                         }
                         diag.note(
                             "a type parameter was expected, but a different one was found; \
@@ -83,23 +87,29 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     | (ty::Alias(ty::Projection, proj), ty::Param(p))
                         if !tcx.is_impl_trait_in_trait(proj.def_id) =>
                     {
-                        let p_def_id = tcx.generics_of(body_owner_def_id).type_param(p, tcx).def_id;
-                        let p_span = tcx.def_span(p_def_id);
-                        let expected = match (values.expected.kind(), values.found.kind()) {
-                            (ty::Param(_), _) => "expected ",
-                            (_, ty::Param(_)) => "found ",
-                            _ => "",
-                        };
-                        if !sp.contains(p_span) {
-                            diag.span_label(p_span, format!("{expected}this type parameter"));
-                        }
-                        let hir = tcx.hir();
+                        let parent = tcx.generics_of(body_owner_def_id)
+                            .opt_type_param(p, tcx)
+                            .and_then(|param| {
+                                let p_def_id = param.def_id;
+                                let p_span = tcx.def_span(p_def_id);
+                                let expected = match (values.expected.kind(), values.found.kind()) {
+                                    (ty::Param(_), _) => "expected ",
+                                    (_, ty::Param(_)) => "found ",
+                                    _ => "",
+                                };
+                                if !sp.contains(p_span) {
+                                    diag.span_label(
+                                        p_span,
+                                        format!("{expected}this type parameter"),
+                                    );
+                                }
+                                p_def_id.as_local().and_then(|id| {
+                                    let local_id = tcx.hir().local_def_id_to_hir_id(id);
+                                    let generics = tcx.hir().find_parent(local_id)?.generics()?;
+                                    Some((id, generics))
+                                })
+                            });
                         let mut note = true;
-                        let parent = p_def_id.as_local().and_then(|id| {
-                            let local_id = hir.local_def_id_to_hir_id(id);
-                            let generics = tcx.hir().find_parent(local_id)?.generics()?;
-                            Some((id, generics))
-                        });
                         if let Some((local_id, generics)) = parent {
                             // Synthesize the associated type restriction `Add<Output = Expected>`.
                             // FIXME: extract this logic for use in other diagnostics.
@@ -172,14 +182,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     (ty::Param(p), ty::Dynamic(..) | ty::Alias(ty::Opaque, ..))
                     | (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => {
                         let generics = tcx.generics_of(body_owner_def_id);
-                        let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
-                        let expected = match (values.expected.kind(), values.found.kind()) {
-                            (ty::Param(_), _) => "expected ",
-                            (_, ty::Param(_)) => "found ",
-                            _ => "",
-                        };
-                        if !sp.contains(p_span) {
-                            diag.span_label(p_span, format!("{expected}this type parameter"));
+                        if let Some(param) = generics.opt_type_param(p, tcx) {
+                            let p_span = tcx.def_span(param.def_id);
+                            let expected = match (values.expected.kind(), values.found.kind()) {
+                                (ty::Param(_), _) => "expected ",
+                                (_, ty::Param(_)) => "found ",
+                                _ => "",
+                            };
+                            if !sp.contains(p_span) {
+                                diag.span_label(p_span, format!("{expected}this type parameter"));
+                            }
                         }
                         diag.help("type parameters must be constrained to match other types");
                         if tcx.sess.teach(&diag.get_code().unwrap()) {
@@ -217,9 +229,11 @@ impl<T> Trait<T> for X {
                     }
                     (ty::Param(p), ty::Closure(..) | ty::Coroutine(..)) => {
                         let generics = tcx.generics_of(body_owner_def_id);
-                        let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
-                        if !sp.contains(p_span) {
-                            diag.span_label(p_span, "expected this type parameter");
+                        if let Some(param) = generics.opt_type_param(p, tcx) {
+                            let p_span = tcx.def_span(param.def_id);
+                            if !sp.contains(p_span) {
+                                diag.span_label(p_span, "expected this type parameter");
+                            }
                         }
                         diag.help(format!(
                             "every closure has a distinct type and so could not always match the \
@@ -228,14 +242,16 @@ impl<T> Trait<T> for X {
                     }
                     (ty::Param(p), _) | (_, ty::Param(p)) => {
                         let generics = tcx.generics_of(body_owner_def_id);
-                        let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
-                        let expected = match (values.expected.kind(), values.found.kind()) {
-                            (ty::Param(_), _) => "expected ",
-                            (_, ty::Param(_)) => "found ",
-                            _ => "",
-                        };
-                        if !sp.contains(p_span) {
-                            diag.span_label(p_span, format!("{expected}this type parameter"));
+                        if let Some(param) = generics.opt_type_param(p, tcx) {
+                            let p_span = tcx.def_span(param.def_id);
+                            let expected = match (values.expected.kind(), values.found.kind()) {
+                                (ty::Param(_), _) => "expected ",
+                                (_, ty::Param(_)) => "found ",
+                                _ => "",
+                            };
+                            if !sp.contains(p_span) {
+                                diag.span_label(p_span, format!("{expected}this type parameter"));
+                            }
                         }
                     }
                     (ty::Alias(ty::Projection | ty::Inherent, proj_ty), _)
@@ -364,13 +380,14 @@ impl<T> Trait<T> for X {
         };
         // Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
         // This will also work for `impl Trait`.
-        let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() {
-            let generics = tcx.generics_of(body_owner_def_id);
-            generics.type_param(param_ty, tcx).def_id
-        } else {
+        let ty::Param(param_ty) = proj_ty.self_ty().kind() else {
             return false;
         };
-        let Some(def_id) = def_id.as_local() else {
+        let generics = tcx.generics_of(body_owner_def_id);
+        let Some(param) = generics.opt_type_param(param_ty, tcx) else {
+            return false;
+        };
+        let Some(def_id) = param.def_id.as_local() else {
             return false;
         };
 
@@ -390,6 +407,10 @@ impl<T> Trait<T> for X {
                 return true;
             }
         }
+        if (param_ty.index as usize) >= generics.parent_count {
+            // The param comes from the current item, do not look at the parent. (#117209)
+            return false;
+        }
         // If associated item, look to constrain the params of the trait/impl.
         let hir_id = match item {
             hir::Node::ImplItem(item) => item.hir_id(),
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 44e88d3e2302f..888ee1d237ae7 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -237,6 +237,20 @@ impl<'tcx> Generics {
         }
     }
 
+    /// Returns the `GenericParamDef` with the given index if available.
+    pub fn opt_param_at(
+        &'tcx self,
+        param_index: usize,
+        tcx: TyCtxt<'tcx>,
+    ) -> Option<&'tcx GenericParamDef> {
+        if let Some(index) = param_index.checked_sub(self.parent_count) {
+            self.params.get(index)
+        } else {
+            tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
+                .opt_param_at(param_index, tcx)
+        }
+    }
+
     pub fn params_to(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx [GenericParamDef] {
         if let Some(index) = param_index.checked_sub(self.parent_count) {
             &self.params[..index]
@@ -268,6 +282,20 @@ impl<'tcx> Generics {
         }
     }
 
+    /// Returns the `GenericParamDef` associated with this `ParamTy` if it belongs to this
+    /// `Generics`.
+    pub fn opt_type_param(
+        &'tcx self,
+        param: &ParamTy,
+        tcx: TyCtxt<'tcx>,
+    ) -> Option<&'tcx GenericParamDef> {
+        let param = self.opt_param_at(param.index as usize, tcx)?;
+        match param.kind {
+            GenericParamDefKind::Type { .. } => Some(param),
+            _ => None,
+        }
+    }
+
     /// Returns the `GenericParamDef` associated with this `ParamConst`.
     pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef {
         let param = self.param_at(param.index as usize, tcx);
diff --git a/tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.rs b/tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.rs
new file mode 100644
index 0000000000000..c1047d85645c5
--- /dev/null
+++ b/tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.rs
@@ -0,0 +1,28 @@
+use std::collections::HashMap;
+use std::hash::Hash;
+
+trait LowT: Identify {}
+
+trait Identify {
+    type Id: Clone + Hash + PartialEq + Eq;
+    fn identify(&self) -> Self::Id;
+}
+
+struct MapStore<L, I>
+where
+    L: LowT + Identify<Id = I>,
+{
+    lows: HashMap<I, L>,
+}
+
+impl<L, I> MapStore<L, I>
+where
+    L: LowT + Identify<Id = I>,
+    I: Clone + Hash + PartialEq + Eq,
+{
+    fn remove_low(&mut self, low: &impl LowT) {
+        let _low = self.lows.remove(low.identify()).unwrap(); //~ ERROR mismatched types
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.stderr b/tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.stderr
new file mode 100644
index 0000000000000..78bf93c32d57c
--- /dev/null
+++ b/tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.rs:24:37
+   |
+LL |         let _low = self.lows.remove(low.identify()).unwrap();
+   |                              ------ ^^^^^^^^^^^^^^ expected `&I`, found associated type
+   |                              |
+   |                              arguments to this method are incorrect
+   |
+   = note:    expected reference `&I`
+           found associated type `<impl LowT as Identify>::Id`
+   = help: consider constraining the associated type `<impl LowT as Identify>::Id` to `&I`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+note: method defined here
+  --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/malformed/do-not-ice-on-note_and_explain.rs b/tests/ui/malformed/do-not-ice-on-note_and_explain.rs
new file mode 100644
index 0000000000000..e65276fb738dd
--- /dev/null
+++ b/tests/ui/malformed/do-not-ice-on-note_and_explain.rs
@@ -0,0 +1,7 @@
+struct A<B>(B);
+impl<B>A<B>{fn d(){fn d(){Self(1)}}}
+//~^ ERROR the size for values of type `B` cannot be known at compilation time
+//~| ERROR the size for values of type `B` cannot be known at compilation time
+//~| ERROR mismatched types
+//~| ERROR mismatched types
+//~| ERROR `main` function not found in crate
diff --git a/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr b/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr
new file mode 100644
index 0000000000000..27b86145e90f4
--- /dev/null
+++ b/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr
@@ -0,0 +1,79 @@
+error[E0601]: `main` function not found in crate `do_not_ice_on_note_and_explain`
+  --> $DIR/do-not-ice-on-note_and_explain.rs:2:37
+   |
+LL | impl<B>A<B>{fn d(){fn d(){Self(1)}}}
+   |                                     ^ consider adding a `main` function to `$DIR/do-not-ice-on-note_and_explain.rs`
+
+error[E0277]: the size for values of type `B` cannot be known at compilation time
+  --> $DIR/do-not-ice-on-note_and_explain.rs:2:32
+   |
+LL | impl<B>A<B>{fn d(){fn d(){Self(1)}}}
+   |      -                    ---- ^ doesn't have a size known at compile-time
+   |      |                    |
+   |      |                    required by a bound introduced by this call
+   |      this type parameter needs to be `Sized`
+   |
+note: required by a bound in `A`
+  --> $DIR/do-not-ice-on-note_and_explain.rs:1:10
+   |
+LL | struct A<B>(B);
+   |          ^ required by this bound in `A`
+
+error[E0308]: mismatched types
+  --> $DIR/do-not-ice-on-note_and_explain.rs:2:32
+   |
+LL | impl<B>A<B>{fn d(){fn d(){Self(1)}}}
+   |                           ---- ^ expected type parameter `B`, found integer
+   |                           |
+   |                           arguments to this function are incorrect
+   |
+   = note: expected type parameter `B`
+                        found type `{integer}`
+note: tuple struct defined here
+  --> $DIR/do-not-ice-on-note_and_explain.rs:1:8
+   |
+LL | struct A<B>(B);
+   |        ^
+
+error[E0308]: mismatched types
+  --> $DIR/do-not-ice-on-note_and_explain.rs:2:27
+   |
+LL | impl<B>A<B>{fn d(){fn d(){Self(1)}}}
+   |                           ^^^^^^^ expected `()`, found `A<B>`
+   |
+   = note: expected unit type `()`
+                 found struct `A<B>`
+help: consider using a semicolon here
+   |
+LL | impl<B>A<B>{fn d(){fn d(){Self(1);}}}
+   |                                  +
+help: try adding a return type
+   |
+LL | impl<B>A<B>{fn d(){fn d() -> A<B>{Self(1)}}}
+   |                           +++++++
+
+error[E0277]: the size for values of type `B` cannot be known at compilation time
+  --> $DIR/do-not-ice-on-note_and_explain.rs:2:27
+   |
+LL | impl<B>A<B>{fn d(){fn d(){Self(1)}}}
+   |      -                    ^^^^^^^ doesn't have a size known at compile-time
+   |      |
+   |      this type parameter needs to be `Sized`
+   |
+note: required by a bound in `A`
+  --> $DIR/do-not-ice-on-note_and_explain.rs:1:10
+   |
+LL | struct A<B>(B);
+   |          ^ required by this bound in `A`
+help: you could relax the implicit `Sized` bound on `B` if it were used through indirection like `&B` or `Box<B>`
+  --> $DIR/do-not-ice-on-note_and_explain.rs:1:10
+   |
+LL | struct A<B>(B);
+   |          ^  - ...if indirection were used here: `Box<B>`
+   |          |
+   |          this could be changed to `B: ?Sized`...
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0277, E0308, E0601.
+For more information about an error, try `rustc --explain E0277`.