rustc_resolve: improve const generic errors

Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 80538ae..d9d42cf 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -898,7 +898,7 @@ fn build_reduced_graph_for_item(&mut self, item: &'a Item) {
             }
 
             // These items live in both the type and value namespaces.
-            ItemKind::Struct(ident, _, ref vdata) => {
+            ItemKind::Struct(ident, ref generics, ref vdata) => {
                 self.build_reduced_graph_for_struct_variant(
                     vdata.fields(),
                     ident,
@@ -947,6 +947,7 @@ fn build_reduced_graph_for_item(&mut self, item: &'a Item) {
                         .struct_constructors
                         .insert(local_def_id, (ctor_res, ctor_vis.to_def_id(), ret_fields));
                 }
+                self.r.struct_generics.insert(local_def_id, generics.clone());
             }
 
             ItemKind::Union(ident, _, ref vdata) => {
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index 5aa0965..a04fe50 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -884,6 +884,21 @@ pub(crate) struct UnexpectedResChangeTyToConstParamSugg {
 }
 
 #[derive(Subdiagnostic)]
+#[suggestion(
+    "you might have meant to introduce a const parameter `{$item_name}` on the {$item_location}",
+    code = "{snippet}",
+    applicability = "machine-applicable",
+    style = "verbose"
+)]
+pub(crate) struct UnexpectedMissingConstParameter {
+    #[primary_span]
+    pub span: Span,
+    pub snippet: String,
+    pub item_name: String,
+    pub item_location: String,
+}
+
+#[derive(Subdiagnostic)]
 #[multipart_suggestion(
     "you might have meant to write a const parameter here",
     applicability = "has-placeholders",
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 453fe9d..759e622 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -4425,7 +4425,7 @@ fn smart_resolve_path_fragment(
         let Finalize { node_id, path_span, .. } = finalize;
         let report_errors = |this: &mut Self, res: Option<Res>| {
             if this.should_report_errs() {
-                let (err, candidates) = this.smart_resolve_report_errors(
+                let (mut err, candidates) = this.smart_resolve_report_errors(
                     path,
                     None,
                     path_span,
@@ -4436,7 +4436,8 @@ fn smart_resolve_path_fragment(
 
                 let def_id = this.parent_scope.module.nearest_parent_mod();
                 let instead = res.is_some();
-                let suggestion = if let Some((start, end)) = this.diag_metadata.in_range
+                let (suggestion, const_err) = if let Some((start, end)) =
+                    this.diag_metadata.in_range
                     && path[0].ident.span.lo() == end.span.lo()
                     && !matches!(start.kind, ExprKind::Lit(_))
                 {
@@ -4448,12 +4449,15 @@ fn smart_resolve_path_fragment(
                         span = span.with_lo(span.lo() + BytePos(1));
                         sugg = "";
                     }
-                    Some((
-                        span,
-                        "you might have meant to write `.` instead of `..`",
-                        sugg.to_string(),
-                        Applicability::MaybeIncorrect,
-                    ))
+                    (
+                        Some((
+                            span,
+                            "you might have meant to write `.` instead of `..`",
+                            sugg.to_string(),
+                            Applicability::MaybeIncorrect,
+                        )),
+                        None,
+                    )
                 } else if res.is_none()
                     && let PathSource::Type
                     | PathSource::Expr(_)
@@ -4461,9 +4465,14 @@ fn smart_resolve_path_fragment(
                 {
                     this.suggest_adding_generic_parameter(path, source)
                 } else {
-                    None
+                    (None, None)
                 };
 
+                if let Some(const_err) = const_err {
+                    err.cancel();
+                    err = const_err;
+                }
+
                 let ue = UseError {
                     err,
                     candidates,
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 95a6b25..e24389e 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -6,11 +6,12 @@
 
 use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt, Visitor, walk_ty};
 use rustc_ast::{
-    self as ast, AssocItemKind, DUMMY_NODE_ID, Expr, ExprKind, GenericParam, GenericParamKind,
-    Item, ItemKind, MethodCall, NodeId, Path, PathSegment, Ty, TyKind,
+    self as ast, AngleBracketedArg, AssocItemKind, DUMMY_NODE_ID, Expr, ExprKind, GenericArg,
+    GenericArgs, GenericParam, GenericParamKind, Item, ItemKind, MethodCall, NodeId, Path,
+    PathSegment, Ty, TyKind,
 };
 use rustc_ast_pretty::pprust::{path_to_string, where_bound_predicate_to_string};
-use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::codes::*;
 use rustc_errors::{
     Applicability, Diag, ErrorGuaranteed, MultiSpan, SuggestionStyle, pluralize,
@@ -37,8 +38,8 @@
 };
 use crate::ty::fast_reject::SimplifiedType;
 use crate::{
-    Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PathSource, Resolver,
-    ScopeSet, Segment, errors, path_names_to_string,
+    Finalize, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PathSource,
+    Resolver, ScopeSet, Segment, errors, path_names_to_string,
 };
 
 type Res = def::Res<ast::NodeId>;
@@ -3277,11 +3278,203 @@ fn suggest_using_enum_variant(
         }
     }
 
-    pub(crate) fn suggest_adding_generic_parameter(
-        &self,
+    /// Detects missing const parameters in `impl` blocks and suggests adding them.
+    ///
+    /// When a const parameter is used in the self type of an `impl` but not declared
+    /// in the `impl`'s own generic parameter list, this function emits a targeted
+    /// diagnostic with a suggestion to add it at the correct position.
+    ///
+    /// Example:
+    ///
+    /// ```rust,ignore (suggested field is not completely correct, it should be a single suggestion)
+    /// struct C<const A: u8, const X: u8, const P: u32>;
+    ///
+    /// impl Foo for C<A, X, P> {}
+    /// //           ^ the struct `C` in `C<A, X, P>` is used as the self type
+    /// //             ^ ^ ^ but A, X and P are not declared on the impl
+    ///
+    /// Suggested fix:
+    ///
+    /// impl<const A: u8, const X: u8, const P: u32> Foo for C<A, X, P> {}
+    ///
+    /// Current behavior (suggestions are emitted one-by-one):
+    ///
+    /// impl<const A: u8> Foo for C<A, X, P> {}
+    /// impl<const X: u8> Foo for C<A, X, P> {}
+    /// impl<const P: u32> Foo for C<A, X, P> {}
+    ///
+    /// Ideally the suggestion should aggregate them into a single line:
+    ///
+    /// impl<const A: u8, const X: u8, const P: u32> Foo for C<A, X, P> {}
+    /// ```
+    ///
+    pub(crate) fn detect_and_suggest_const_parameter_error(
+        &mut self,
         path: &[Segment],
-        source: PathSource<'_, '_, '_>,
-    ) -> Option<(Span, &'static str, String, Applicability)> {
+        source: PathSource<'_, 'ast, 'ra>,
+    ) -> Option<Diag<'tcx>> {
+        let Some(item) = self.diag_metadata.current_item else { return None };
+        let ItemKind::Impl(impl_) = &item.kind else { return None };
+        let self_ty = &impl_.self_ty;
+
+        // Represents parameter to the struct whether `A`, `X` or `P`
+        let [current_parameter] = path else {
+            return None;
+        };
+
+        let target_ident = current_parameter.ident;
+
+        // Find the parent segment i.e `C` in `C<A, X, C>`
+        let visitor = ParentPathVisitor::new(self_ty, target_ident);
+
+        let Some(parent_segment) = visitor.parent else {
+            return None;
+        };
+
+        let Some(args) = parent_segment.args.as_ref() else {
+            return None;
+        };
+
+        let GenericArgs::AngleBracketed(angle) = args.as_ref() else {
+            return None;
+        };
+
+        // Build map: NodeId of each usage in C<A, X, C> -> its position
+        // e.g NodeId(A) -> 0, NodeId(X) -> 1, NodeId(C) -> 2
+        let usage_to_pos: FxHashMap<NodeId, usize> = angle
+            .args
+            .iter()
+            .enumerate()
+            .filter_map(|(pos, arg)| {
+                if let AngleBracketedArg::Arg(GenericArg::Type(ty)) = arg
+                    && let TyKind::Path(_, path) = &ty.kind
+                    && let [segment] = path.segments.as_slice()
+                {
+                    Some((segment.id, pos))
+                } else {
+                    None
+                }
+            })
+            .collect();
+
+        // Get the position of the missing param in C<A, X, C>
+        // e.g for missing `B` in `C<A, B, C>` this gives idx=1
+        let Some(idx) = current_parameter.id.and_then(|id| usage_to_pos.get(&id).copied()) else {
+            return None;
+        };
+
+        // Now resolve the parent struct `C` to get its definition
+        let ns = source.namespace();
+        let segment = Segment::from(parent_segment);
+        let segments = [segment];
+        let finalize = Finalize::new(parent_segment.id, parent_segment.ident.span);
+
+        if let Ok(Some(resolve)) = self.resolve_qpath_anywhere(
+            &None,
+            &segments,
+            ns,
+            source.defer_to_typeck(),
+            finalize,
+            source,
+        ) && let Some(resolve) = resolve.full_res()
+            && let Res::Def(_, def_id) = resolve
+            && def_id.is_local()
+            && let Some(local_def_id) = def_id.as_local()
+            && let Some(struct_generics) = self.r.struct_generics.get(&local_def_id)
+            && let target_param = &struct_generics.params[idx]
+            && let GenericParamKind::Const { ty, .. } = &target_param.kind
+            && let TyKind::Path(_, path) = &ty.kind
+        {
+            let full_type = path
+                .segments
+                .iter()
+                .map(|seg| seg.ident.to_string())
+                .collect::<Vec<_>>()
+                .join("::");
+
+            // Find the first impl param whose position in C<A, X, C>
+            // is strictly greater than our missing param's index
+            // e.g missing B(idx=1), impl has A(pos=0) and C(pos=2)
+            // C has pos=2 > 1 so insert before C
+            let next_impl_param = impl_.generics.params.iter().find(|impl_param| {
+                angle
+                    .args
+                    .iter()
+                    .find_map(|arg| {
+                        if let AngleBracketedArg::Arg(GenericArg::Type(ty)) = arg
+                            && let TyKind::Path(_, path) = &ty.kind
+                            && let [segment] = path.segments.as_slice()
+                            && segment.ident == impl_param.ident
+                        {
+                            usage_to_pos.get(&segment.id).copied()
+                        } else {
+                            None
+                        }
+                    })
+                    .map_or(false, |pos| pos > idx)
+            });
+
+            let (insert_span, snippet) = match next_impl_param {
+                Some(next_param) => {
+                    // Insert in the middle before next_param
+                    // e.g impl<A, C> -> impl<A, const B: u8, C>
+                    (
+                        next_param.span().shrink_to_lo(),
+                        format!("const {}: {}, ", target_ident, full_type),
+                    )
+                }
+                None => match impl_.generics.params.last() {
+                    Some(last) => {
+                        // Append after last existing param
+                        // e.g impl<A, B> -> impl<A, B, const C: u8>
+                        (
+                            last.span().shrink_to_hi(),
+                            format!(", const {}: {}", target_ident, full_type),
+                        )
+                    }
+                    None => {
+                        // No generics at all on impl
+                        // e.g impl Foo for C<A> -> impl<const A: u8> Foo for C<A>
+                        (
+                            impl_.generics.span.shrink_to_hi(),
+                            format!("<const {}: {}>", target_ident, full_type),
+                        )
+                    }
+                },
+            };
+
+            let mut err = self.r.dcx().struct_span_err(
+                target_ident.span,
+                format!("cannot find const `{}` in this scope", target_ident),
+            );
+
+            err.code(E0425);
+
+            err.span_label(target_ident.span, "not found in this scope");
+
+            err.span_label(
+                target_param.span(),
+                format!("corresponding const parameter on the type defined here",),
+            );
+
+            err.subdiagnostic(errors::UnexpectedMissingConstParameter {
+                span: insert_span,
+                snippet,
+                item_name: format!("{}", target_ident),
+                item_location: String::from("impl"),
+            });
+
+            return Some(err);
+        }
+
+        None
+    }
+
+    pub(crate) fn suggest_adding_generic_parameter(
+        &mut self,
+        path: &[Segment],
+        source: PathSource<'_, 'ast, 'ra>,
+    ) -> (Option<(Span, &'static str, String, Applicability)>, Option<Diag<'tcx>>) {
         let (ident, span) = match path {
             [segment]
                 if !segment.has_generic_args
@@ -3290,13 +3483,13 @@ pub(crate) fn suggest_adding_generic_parameter(
             {
                 (segment.ident.to_string(), segment.ident.span)
             }
-            _ => return None,
+            _ => return (None, None),
         };
         let mut iter = ident.chars().map(|c| c.is_uppercase());
         let single_uppercase_char =
             matches!(iter.next(), Some(true)) && matches!(iter.next(), None);
         if !self.diag_metadata.currently_processing_generic_args && !single_uppercase_char {
-            return None;
+            return (None, None);
         }
         match (self.diag_metadata.current_item, single_uppercase_char, self.diag_metadata.currently_processing_generic_args) {
             (Some(Item { kind: ItemKind::Fn(fn_), .. }), _, _) if fn_.ident.name == sym::main => {
@@ -3326,18 +3519,21 @@ pub(crate) fn suggest_adding_generic_parameter(
                         //   |           ^- help: you might be missing a type parameter: `, A`
                         //   |           |
                         //   |           not found in this scope
-                        return None;
+                        return (None, None);
                     }
 
                     let (msg, sugg) = match source {
                         PathSource::Type | PathSource::PreciseCapturingArg(TypeNS) => {
+                            if let Some(err) = self.detect_and_suggest_const_parameter_error(path, source) {
+                                return (None, Some(err));
+                            }
                             ("you might be missing a type parameter", ident)
                         }
                         PathSource::Expr(_) | PathSource::PreciseCapturingArg(ValueNS) => (
                             "you might be missing a const parameter",
                             format!("const {ident}: /* Type */"),
                         ),
-                        _ => return None,
+                        _ => return (None, None),
                     };
                     let (span, sugg) = if let [.., param] = &generics.params[..] {
                         let span = if let [.., bound] = &param.bounds[..] {
@@ -3355,18 +3551,18 @@ pub(crate) fn suggest_adding_generic_parameter(
                     };
                     // Do not suggest if this is coming from macro expansion.
                     if span.can_be_used_for_suggestions() {
-                        return Some((
+                        return (Some((
                             span.shrink_to_hi(),
                             msg,
                             sugg,
                             Applicability::MaybeIncorrect,
-                        ));
+                        )), None);
                     }
                 }
             }
             _ => {}
         }
-        None
+        (None, None)
     }
 
     /// Given the target `label`, search the `rib_index`th label rib for similarly named labels,
@@ -4349,3 +4545,44 @@ pub(super) fn signal_label_shadowing(sess: &Session, orig: Span, shadower: Ident
         .with_span_label(shadower, format!("label `{name}` already in scope"))
         .emit();
 }
+
+struct ParentPathVisitor<'a> {
+    target: Ident,
+    parent: Option<&'a PathSegment>,
+    stack: Vec<&'a Ty>,
+}
+
+impl<'a> ParentPathVisitor<'a> {
+    fn new(self_ty: &'a Ty, target: Ident) -> Self {
+        let mut v = ParentPathVisitor { target, parent: None, stack: Vec::new() };
+
+        v.visit_ty(self_ty);
+        v
+    }
+}
+
+impl<'a> Visitor<'a> for ParentPathVisitor<'a> {
+    fn visit_ty(&mut self, ty: &'a Ty) {
+        if self.parent.is_some() {
+            return;
+        }
+
+        // push current type
+        self.stack.push(ty);
+
+        if let TyKind::Path(_, path) = &ty.kind
+            // is this just `N`?
+            && let [segment] = path.segments.as_slice()
+            && segment.ident == self.target
+            // parent is previous element in stack
+            && let [.., parent_ty, _ty] = self.stack.as_slice()
+            && let TyKind::Path(_, parent_path) = &parent_ty.kind
+        {
+            self.parent = parent_path.segments.first();
+        }
+
+        walk_ty(self, ty);
+
+        self.stack.pop();
+    }
+}
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 7c94219..249ff1d 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -40,7 +40,7 @@
 use rustc_ast::node_id::NodeMap;
 use rustc_ast::{
     self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, Expr, ExprKind, GenericArg, GenericArgs,
-    NodeId, Path, attr,
+    Generics, NodeId, Path, attr,
 };
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, default};
 use rustc_data_structures::intern::Interned;
@@ -1317,6 +1317,10 @@ pub struct Resolver<'ra, 'tcx> {
     /// Also includes of list of each fields visibility
     struct_constructors: LocalDefIdMap<(Res, Visibility<DefId>, Vec<Visibility<DefId>>)> = Default::default(),
 
+    /// for all the struct
+    /// it's not used during normal resolution, only for better error reporting.
+    struct_generics: LocalDefIdMap<Generics> = Default::default(),
+
     lint_buffer: LintBuffer,
 
     next_node_id: NodeId = CRATE_NODE_ID,
diff --git a/tests/ui/const-generics/const-generic-function.rs b/tests/ui/const-generics/const-generic-function.rs
index c8d2683..03c94d9 100644
--- a/tests/ui/const-generics/const-generic-function.rs
+++ b/tests/ui/const-generics/const-generic-function.rs
@@ -14,7 +14,7 @@ const fn baz() -> i32 {
 
 fn main() {
     foo::<baz()>(); //~ ERROR expected type, found function `baz`
-    //~| ERROR unresolved item provided when a constant was expected
+    //~^ ERROR unresolved item provided when a constant was expected
     foo::<bar(bar(1, 1), bar(1, 1))>(); //~ ERROR expected type, found `1`
     foo::<bar(1, 1)>(); //~ ERROR expected type, found `1`
     foo::<bar(FOO, 2)>(); //~ ERROR expected type, found `2`
diff --git a/tests/ui/const-generics/early/invalid-const-arguments.rs b/tests/ui/const-generics/early/invalid-const-arguments.rs
index 68e6b2a..82cc948 100644
--- a/tests/ui/const-generics/early/invalid-const-arguments.rs
+++ b/tests/ui/const-generics/early/invalid-const-arguments.rs
@@ -1,10 +1,10 @@
-#![crate_type="lib"]
+#![crate_type = "lib"]
 
 struct A<const N: u8>;
 trait Foo {}
 impl Foo for A<N> {}
-//~^ ERROR cannot find type
-//~| ERROR unresolved item provided when a constant
+//~^ ERROR cannot find const `N` in this scope
+//~| ERROR unresolved item provided when a constant was expected
 
 struct B<const N: u8>;
 impl<N> Foo for B<N> {}
@@ -12,5 +12,16 @@ impl<N> Foo for B<N> {}
 
 struct C<const C: u8, const N: u8>;
 impl<const N: u8> Foo for C<N, T> {}
-//~^ ERROR cannot find type
-//~| ERROR unresolved item provided when a constant
+//~^ ERROR cannot find const `T` in this scope
+//~| ERROR unresolved item provided when a constant was expected
+
+struct D<const E: u8, const X: u8, const P: u32>;
+impl Foo for D<E, X, P> {}
+//~^ ERROR cannot find const `E` in this scope
+//~| ERROR unresolved item provided when a constant was expected
+//~| ERROR cannot find const `X` in this scope
+//~| ERROR cannot find const `P` in this scope
+struct R<const O: u8, const G: u8, const F: u32>;
+impl<const F: u8, const H: u32> Foo for D<F, Q, D> {}
+//~^ ERROR cannot find const `Q` in this scope
+//~| ERROR unresolved item provided when a constant was expected
diff --git a/tests/ui/const-generics/early/invalid-const-arguments.stderr b/tests/ui/const-generics/early/invalid-const-arguments.stderr
index a0a6d8c..4d8ab68 100644
--- a/tests/ui/const-generics/early/invalid-const-arguments.stderr
+++ b/tests/ui/const-generics/early/invalid-const-arguments.stderr
@@ -1,40 +1,82 @@
-error[E0425]: cannot find type `N` in this scope
+error[E0425]: cannot find const `N` in this scope
   --> $DIR/invalid-const-arguments.rs:5:16
    |
 LL | struct A<const N: u8>;
-   | ---------------------- similarly named struct `A` defined here
+   |          ----------- corresponding const parameter on the type defined here
 LL | trait Foo {}
 LL | impl Foo for A<N> {}
-   |                ^
+   |                ^ not found in this scope
    |
-help: a struct with a similar name exists
+help: you might have meant to introduce a const parameter `N` on the impl
    |
-LL - impl Foo for A<N> {}
-LL + impl Foo for A<A> {}
-   |
-help: you might be missing a type parameter
-   |
-LL | impl<N> Foo for A<N> {}
-   |     +++
+LL | impl<const N: u8> Foo for A<N> {}
+   |     +++++++++++++
 
-error[E0425]: cannot find type `T` in this scope
+error[E0425]: cannot find const `T` in this scope
   --> $DIR/invalid-const-arguments.rs:14:32
    |
-LL | struct A<const N: u8>;
-   | ---------------------- similarly named struct `A` defined here
-...
+LL | struct C<const C: u8, const N: u8>;
+   |                       ----------- corresponding const parameter on the type defined here
 LL | impl<const N: u8> Foo for C<N, T> {}
-   |                                ^
+   |                                ^ not found in this scope
    |
-help: a struct with a similar name exists
+help: you might have meant to introduce a const parameter `T` on the impl
    |
-LL - impl<const N: u8> Foo for C<N, T> {}
-LL + impl<const N: u8> Foo for C<N, A> {}
+LL | impl<const N: u8, const T: u8> Foo for C<N, T> {}
+   |                 +++++++++++++
+
+error[E0425]: cannot find const `E` in this scope
+  --> $DIR/invalid-const-arguments.rs:19:16
    |
-help: you might be missing a type parameter
+LL | struct D<const E: u8, const X: u8, const P: u32>;
+   |          ----------- corresponding const parameter on the type defined here
+LL | impl Foo for D<E, X, P> {}
+   |                ^ not found in this scope
    |
-LL | impl<const N: u8, T> Foo for C<N, T> {}
-   |                 +++
+help: you might have meant to introduce a const parameter `E` on the impl
+   |
+LL | impl<const E: u8> Foo for D<E, X, P> {}
+   |     +++++++++++++
+
+error[E0425]: cannot find const `X` in this scope
+  --> $DIR/invalid-const-arguments.rs:19:19
+   |
+LL | struct D<const E: u8, const X: u8, const P: u32>;
+   |                       ----------- corresponding const parameter on the type defined here
+LL | impl Foo for D<E, X, P> {}
+   |                   ^ not found in this scope
+   |
+help: you might have meant to introduce a const parameter `X` on the impl
+   |
+LL | impl<const X: u8> Foo for D<E, X, P> {}
+   |     +++++++++++++
+
+error[E0425]: cannot find const `P` in this scope
+  --> $DIR/invalid-const-arguments.rs:19:22
+   |
+LL | struct D<const E: u8, const X: u8, const P: u32>;
+   |                                    ------------ corresponding const parameter on the type defined here
+LL | impl Foo for D<E, X, P> {}
+   |                      ^ not found in this scope
+   |
+help: you might have meant to introduce a const parameter `P` on the impl
+   |
+LL | impl<const P: u32> Foo for D<E, X, P> {}
+   |     ++++++++++++++
+
+error[E0425]: cannot find const `Q` in this scope
+  --> $DIR/invalid-const-arguments.rs:25:46
+   |
+LL | struct D<const E: u8, const X: u8, const P: u32>;
+   |                       ----------- corresponding const parameter on the type defined here
+...
+LL | impl<const F: u8, const H: u32> Foo for D<F, Q, D> {}
+   |                                              ^ not found in this scope
+   |
+help: you might have meant to introduce a const parameter `Q` on the impl
+   |
+LL | impl<const F: u8, const H: u32, const Q: u8> Foo for D<F, Q, D> {}
+   |                               +++++++++++++
 
 error[E0747]: unresolved item provided when a constant was expected
   --> $DIR/invalid-const-arguments.rs:5:16
@@ -70,7 +112,29 @@
 LL | impl<const N: u8> Foo for C<N, { T }> {}
    |                                +   +
 
-error: aborting due to 5 previous errors
+error[E0747]: unresolved item provided when a constant was expected
+  --> $DIR/invalid-const-arguments.rs:19:16
+   |
+LL | impl Foo for D<E, X, P> {}
+   |                ^
+   |
+help: if this generic argument was intended as a const parameter, surround it with braces
+   |
+LL | impl Foo for D<{ E }, X, P> {}
+   |                +   +
+
+error[E0747]: unresolved item provided when a constant was expected
+  --> $DIR/invalid-const-arguments.rs:25:46
+   |
+LL | impl<const F: u8, const H: u32> Foo for D<F, Q, D> {}
+   |                                              ^
+   |
+help: if this generic argument was intended as a const parameter, surround it with braces
+   |
+LL | impl<const F: u8, const H: u32> Foo for D<F, { Q }, D> {}
+   |                                              +   +
+
+error: aborting due to 11 previous errors
 
 Some errors have detailed explanations: E0425, E0747.
 For more information about an error, try `rustc --explain E0425`.
diff --git a/tests/ui/const-generics/invalid-enum.rs b/tests/ui/const-generics/invalid-enum.rs
index 56fac3e..09d06e0 100644
--- a/tests/ui/const-generics/invalid-enum.rs
+++ b/tests/ui/const-generics/invalid-enum.rs
@@ -12,27 +12,27 @@ enum CompileFlag {
 
 pub fn test_1<const CF: CompileFlag>() {}
 pub fn test_2<T, const CF: CompileFlag>(x: T) {}
-pub struct Example<const CF: CompileFlag, T=u32>{
+pub struct Example<const CF: CompileFlag, T = u32> {
     x: T,
 }
 
 impl<const CF: CompileFlag, T> Example<CF, T> {
-  const ASSOC_FLAG: CompileFlag = CompileFlag::A;
+    const ASSOC_FLAG: CompileFlag = CompileFlag::A;
 }
 
 pub fn main() {
-  test_1::<CompileFlag::A>();
-  //~^ ERROR: expected type, found variant
-  //~| ERROR: unresolved item provided when a constant was expected
+    test_1::<CompileFlag::A>();
+    //~^ ERROR: expected type, found variant
+    //~| ERROR: unresolved item provided when a constant was expected
 
-  test_2::<_, CompileFlag::A>(0);
-  //~^ ERROR: expected type, found variant
-  //~| ERROR: unresolved item provided when a constant was expected
+    test_2::<_, CompileFlag::A>(0);
+    //~^ ERROR: expected type, found variant
+    //~| ERROR: unresolved item provided when a constant was expected
 
-  let _: Example<CompileFlag::A, _> = Example { x: 0 };
-  //~^ ERROR: expected type, found variant
-  //~| ERROR: unresolved item provided when a constant was expected
+    let _: Example<CompileFlag::A, _> = Example { x: 0 };
+    //~^ ERROR: expected type, found variant
+    //~| ERROR: unresolved item provided when a constant was expected
 
-  let _: Example<Example::ASSOC_FLAG, _> = Example { x: 0 };
-  //~^ ERROR: type provided when a constant was expected
+    let _: Example<Example::ASSOC_FLAG, _> = Example { x: 0 };
+    //~^ ERROR: type provided when a constant was expected
 }
diff --git a/tests/ui/const-generics/invalid-enum.stderr b/tests/ui/const-generics/invalid-enum.stderr
index 9110523..a557927 100644
--- a/tests/ui/const-generics/invalid-enum.stderr
+++ b/tests/ui/const-generics/invalid-enum.stderr
@@ -1,73 +1,73 @@
 error[E0573]: expected type, found variant `CompileFlag::A`
-  --> $DIR/invalid-enum.rs:24:12
+  --> $DIR/invalid-enum.rs:24:14
    |
-LL |   test_1::<CompileFlag::A>();
-   |            ^^^^^^^^^^^^^^
-   |            |
-   |            not a type
-   |            help: try using the variant's enum: `CompileFlag`
+LL |     test_1::<CompileFlag::A>();
+   |              ^^^^^^^^^^^^^^
+   |              |
+   |              not a type
+   |              help: try using the variant's enum: `CompileFlag`
 
 error[E0573]: expected type, found variant `CompileFlag::A`
-  --> $DIR/invalid-enum.rs:28:15
+  --> $DIR/invalid-enum.rs:28:17
    |
-LL |   test_2::<_, CompileFlag::A>(0);
-   |               ^^^^^^^^^^^^^^
-   |               |
-   |               not a type
-   |               help: try using the variant's enum: `CompileFlag`
+LL |     test_2::<_, CompileFlag::A>(0);
+   |                 ^^^^^^^^^^^^^^
+   |                 |
+   |                 not a type
+   |                 help: try using the variant's enum: `CompileFlag`
 
 error[E0573]: expected type, found variant `CompileFlag::A`
-  --> $DIR/invalid-enum.rs:32:18
+  --> $DIR/invalid-enum.rs:32:20
    |
-LL |   let _: Example<CompileFlag::A, _> = Example { x: 0 };
-   |                  ^^^^^^^^^^^^^^
-   |                  |
-   |                  not a type
-   |                  help: try using the variant's enum: `CompileFlag`
+LL |     let _: Example<CompileFlag::A, _> = Example { x: 0 };
+   |                    ^^^^^^^^^^^^^^
+   |                    |
+   |                    not a type
+   |                    help: try using the variant's enum: `CompileFlag`
 
 error[E0747]: unresolved item provided when a constant was expected
-  --> $DIR/invalid-enum.rs:24:12
+  --> $DIR/invalid-enum.rs:24:14
    |
-LL |   test_1::<CompileFlag::A>();
-   |            ^^^^^^^^^^^^^^
+LL |     test_1::<CompileFlag::A>();
+   |              ^^^^^^^^^^^^^^
    |
 help: if this generic argument was intended as a const parameter, surround it with braces
    |
-LL |   test_1::<{ CompileFlag::A }>();
-   |            +                +
+LL |     test_1::<{ CompileFlag::A }>();
+   |              +                +
 
 error[E0747]: unresolved item provided when a constant was expected
-  --> $DIR/invalid-enum.rs:28:15
+  --> $DIR/invalid-enum.rs:28:17
    |
-LL |   test_2::<_, CompileFlag::A>(0);
-   |               ^^^^^^^^^^^^^^
+LL |     test_2::<_, CompileFlag::A>(0);
+   |                 ^^^^^^^^^^^^^^
    |
 help: if this generic argument was intended as a const parameter, surround it with braces
    |
-LL |   test_2::<_, { CompileFlag::A }>(0);
-   |               +                +
+LL |     test_2::<_, { CompileFlag::A }>(0);
+   |                 +                +
 
 error[E0747]: unresolved item provided when a constant was expected
-  --> $DIR/invalid-enum.rs:32:18
+  --> $DIR/invalid-enum.rs:32:20
    |
-LL |   let _: Example<CompileFlag::A, _> = Example { x: 0 };
-   |                  ^^^^^^^^^^^^^^
+LL |     let _: Example<CompileFlag::A, _> = Example { x: 0 };
+   |                    ^^^^^^^^^^^^^^
    |
 help: if this generic argument was intended as a const parameter, surround it with braces
    |
-LL |   let _: Example<{ CompileFlag::A }, _> = Example { x: 0 };
-   |                  +                +
+LL |     let _: Example<{ CompileFlag::A }, _> = Example { x: 0 };
+   |                    +                +
 
 error[E0747]: type provided when a constant was expected
-  --> $DIR/invalid-enum.rs:36:18
+  --> $DIR/invalid-enum.rs:36:20
    |
-LL |   let _: Example<Example::ASSOC_FLAG, _> = Example { x: 0 };
-   |                  ^^^^^^^^^^^^^^^^^^^
+LL |     let _: Example<Example::ASSOC_FLAG, _> = Example { x: 0 };
+   |                    ^^^^^^^^^^^^^^^^^^^
    |
 help: if this generic argument was intended as a const parameter, surround it with braces
    |
-LL |   let _: Example<{ Example::ASSOC_FLAG }, _> = Example { x: 0 };
-   |                  +                     +
+LL |     let _: Example<{ Example::ASSOC_FLAG }, _> = Example { x: 0 };
+   |                    +                     +
 
 error: aborting due to 7 previous errors
 
diff --git a/tests/ui/missing/missing-items/missing-type-parameter2.rs b/tests/ui/missing/missing-items/missing-type-parameter2.rs
index 772e60b..c52f3157 100644
--- a/tests/ui/missing/missing-items/missing-type-parameter2.rs
+++ b/tests/ui/missing/missing-items/missing-type-parameter2.rs
@@ -1,10 +1,10 @@
 struct X<const N: u8>();
 
 impl X<N> {}
-//~^ ERROR cannot find type `N` in this scope
+//~^ ERROR cannot find const `N` in this scope
 //~| ERROR unresolved item provided when a constant was expected
 impl<T, const A: u8 = 2> X<N> {}
-//~^ ERROR cannot find type `N` in this scope
+//~^ ERROR cannot find const `N` in this scope
 //~| ERROR defaults for generic parameters are not allowed here
 //~| ERROR unresolved item provided when a constant was expected
 
@@ -15,5 +15,4 @@ fn foo(_: T) where T: Send {}
 fn bar<const N: u8>(_: A) {}
 //~^ ERROR cannot find type `A` in this scope
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/ui/missing/missing-items/missing-type-parameter2.stderr b/tests/ui/missing/missing-items/missing-type-parameter2.stderr
index c361ed7..7c85d39 100644
--- a/tests/ui/missing/missing-items/missing-type-parameter2.stderr
+++ b/tests/ui/missing/missing-items/missing-type-parameter2.stderr
@@ -1,39 +1,30 @@
-error[E0425]: cannot find type `N` in this scope
+error[E0425]: cannot find const `N` in this scope
   --> $DIR/missing-type-parameter2.rs:3:8
    |
 LL | struct X<const N: u8>();
-   | ------------------------ similarly named struct `X` defined here
+   |          ----------- corresponding const parameter on the type defined here
 LL |
 LL | impl X<N> {}
-   |        ^
+   |        ^ not found in this scope
    |
-help: a struct with a similar name exists
+help: you might have meant to introduce a const parameter `N` on the impl
    |
-LL - impl X<N> {}
-LL + impl X<X> {}
-   |
-help: you might be missing a type parameter
-   |
-LL | impl<N> X<N> {}
-   |     +++
+LL | impl<const N: u8> X<N> {}
+   |     +++++++++++++
 
-error[E0425]: cannot find type `N` in this scope
+error[E0425]: cannot find const `N` in this scope
   --> $DIR/missing-type-parameter2.rs:6:28
    |
+LL | struct X<const N: u8>();
+   |          ----------- corresponding const parameter on the type defined here
+...
 LL | impl<T, const A: u8 = 2> X<N> {}
-   |      -                     ^
-   |      |
-   |      similarly named type parameter `T` defined here
+   |                            ^ not found in this scope
    |
-help: a type parameter with a similar name exists
+help: you might have meant to introduce a const parameter `N` on the impl
    |
-LL - impl<T, const A: u8 = 2> X<N> {}
-LL + impl<T, const A: u8 = 2> X<T> {}
-   |
-help: you might be missing a type parameter
-   |
-LL | impl<T, const A: u8 = 2, N> X<N> {}
-   |                        +++
+LL | impl<T, const A: u8 = 2, const N: u8> X<N> {}
+   |                        +++++++++++++
 
 error[E0425]: cannot find type `T` in this scope
   --> $DIR/missing-type-parameter2.rs:11:20