Skip to main content

rustc_hir_analysis/diagnostics/
wrong_number_of_generic_args.rs

1use GenericArgsInfo::*;
2use rustc_errors::codes::*;
3use rustc_errors::{Applicability, Diag, Diagnostic, MultiSpan, pluralize};
4use rustc_hir as hir;
5use rustc_hir::def::DefKind;
6use rustc_middle::ty::{self as ty, AssocItem, AssocItems, Ty, TyCtxt};
7use rustc_span::def_id::{DefId, LocalDefId};
8use rustc_span::{Symbol, kw};
9use tracing::debug;
10
11/// Handles the `wrong number of type / lifetime / ... arguments` family of error messages.
12pub(crate) struct WrongNumberOfGenericArgs<'a, 'tcx> {
13    pub(crate) tcx: TyCtxt<'tcx>,
14
15    pub(crate) angle_brackets: AngleBrackets,
16
17    pub(crate) gen_args_info: GenericArgsInfo,
18
19    /// Offending path segment
20    pub(crate) path_segment: &'a hir::PathSegment<'a>,
21
22    /// Generic parameters as expected by type or trait
23    pub(crate) gen_params: &'a ty::Generics,
24
25    /// Index offset into parameters. Depends on whether `Self` is included and on
26    /// number of lifetime parameters in case we're processing missing or redundant
27    /// type or constant arguments.
28    pub(crate) params_offset: usize,
29
30    /// Generic arguments as provided by user
31    pub(crate) gen_args: &'a hir::GenericArgs<'a>,
32
33    /// DefId of the generic type
34    pub(crate) def_id: DefId,
35
36    /// DefId of the type that contains the generic
37    pub(crate) cx_def_id: LocalDefId,
38}
39
40// Provides information about the kind of arguments that were provided for
41// the PathSegment, for which missing generic arguments were detected
42#[derive(#[automatically_derived]impl ::core::fmt::Debug for AngleBrackets {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                AngleBrackets::Implied => "Implied",
                AngleBrackets::Missing => "Missing",
                AngleBrackets::Available => "Available",
            })
    }
}Debug)]
43pub(crate) enum AngleBrackets {
44    // No angle brackets were provided, but generic arguments exist in elided form
45    Implied,
46
47    // No angle brackets were provided
48    Missing,
49
50    // Angle brackets are available, but missing some generic arguments
51    Available,
52}
53
54// Information about the kind of arguments that are either missing or are unexpected
55#[derive(#[automatically_derived]impl ::core::fmt::Debug for GenericArgsInfo {
    #[inline]
    #[rustc_trivial_field_reads]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::MissingLifetimes { num_missing_args: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "MissingLifetimes num_missing_args", &__self_0),
            Self::ExcessLifetimes { num_redundant_args: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "ExcessLifetimes num_redundant_args", &__self_0),
            Self::MissingTypesOrConsts {
                num_missing_args: __self_0,
                num_default_params: __self_1,
                args_offset: __self_2 } =>
                ::core::fmt::Formatter::debug_struct_field3_finish(f,
                    "MissingTypesOrConsts num_missing_args num_default_params args_offset",
                    __self_0, __self_1, &__self_2),
            Self::ExcessTypesOrConsts {
                num_redundant_args: __self_0,
                num_default_params: __self_1,
                args_offset: __self_2,
                synth_provided: __self_3 } =>
                ::core::fmt::Formatter::debug_struct_field4_finish(f,
                    "ExcessTypesOrConsts num_redundant_args num_default_params args_offset synth_provided",
                    __self_0, __self_1, __self_2, &__self_3),
        }
    }
}Debug)]
56pub(crate) enum GenericArgsInfo {
57    MissingLifetimes {
58        num_missing_args: usize,
59    },
60    ExcessLifetimes {
61        num_redundant_args: usize,
62    },
63    MissingTypesOrConsts {
64        num_missing_args: usize,
65
66        // type or const generic arguments can have default values
67        num_default_params: usize,
68
69        // lifetime arguments precede type and const parameters, this
70        // field gives the number of generic lifetime arguments to let
71        // us infer the position of type and const generic arguments
72        // in the angle brackets
73        args_offset: usize,
74    },
75
76    ExcessTypesOrConsts {
77        num_redundant_args: usize,
78
79        // type or const generic arguments can have default values
80        num_default_params: usize,
81
82        // lifetime arguments precede type and const parameters, this
83        // field gives the number of generic lifetime arguments to let
84        // us infer the position of type and const generic arguments
85        // in the angle brackets
86        args_offset: usize,
87
88        // if synthetic type arguments (e.g. `impl Trait`) are specified
89        synth_provided: bool,
90    },
91}
92
93impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
94    pub(crate) fn new(
95        tcx: TyCtxt<'tcx>,
96        gen_args_info: GenericArgsInfo,
97        path_segment: &'a hir::PathSegment<'_>,
98        gen_params: &'a ty::Generics,
99        params_offset: usize,
100        gen_args: &'a hir::GenericArgs<'a>,
101        def_id: DefId,
102        cx_def_id: LocalDefId,
103    ) -> Self {
104        let angle_brackets = if gen_args.span_ext().is_none() {
105            if gen_args.is_empty() { AngleBrackets::Missing } else { AngleBrackets::Implied }
106        } else {
107            AngleBrackets::Available
108        };
109
110        Self {
111            tcx,
112            angle_brackets,
113            gen_args_info,
114            path_segment,
115            gen_params,
116            params_offset,
117            gen_args,
118            def_id,
119            cx_def_id,
120        }
121    }
122
123    fn missing_lifetimes(&self) -> bool {
124        match self.gen_args_info {
125            MissingLifetimes { .. } | ExcessLifetimes { .. } => true,
126            MissingTypesOrConsts { .. } | ExcessTypesOrConsts { .. } => false,
127        }
128    }
129
130    fn kind(&self) -> &str {
131        if self.missing_lifetimes() { "lifetime" } else { "generic" }
132    }
133
134    /// Returns true if the generic type is a trait
135    /// and is being referred to from one of its trait impls
136    fn is_in_trait_impl(&self) -> bool {
137        if self.tcx.is_trait(self.def_id) {
138            // Here we check if the reference to the generic type
139            // is from the 'of_trait' field of the enclosing impl
140
141            let parent = self.tcx.parent_hir_node(self.path_segment.hir_id);
142            let parent_item = self
143                .tcx
144                .hir_node_by_def_id(self.tcx.hir_get_parent_item(self.path_segment.hir_id).def_id);
145
146            // Get the HIR id of the trait ref
147            let hir::Node::TraitRef(hir::TraitRef { hir_ref_id: trait_ref_id, .. }) = parent else {
148                return false;
149            };
150
151            // Get the HIR id of the 'of_trait' field of the impl
152            let hir::Node::Item(hir::Item {
153                kind:
154                    hir::ItemKind::Impl(hir::Impl {
155                        of_trait:
156                            Some(hir::TraitImplHeader {
157                                trait_ref: hir::TraitRef { hir_ref_id: id_in_of_trait, .. },
158                                ..
159                            }),
160                        ..
161                    }),
162                ..
163            }) = parent_item
164            else {
165                return false;
166            };
167
168            // Check that trait is referred to from the of_trait field of impl
169            trait_ref_id == id_in_of_trait
170        } else {
171            false
172        }
173    }
174
175    fn num_provided_args(&self) -> usize {
176        if self.missing_lifetimes() {
177            self.num_provided_lifetime_args()
178        } else {
179            self.num_provided_type_or_const_args()
180        }
181    }
182
183    fn num_provided_lifetime_args(&self) -> usize {
184        match self.angle_brackets {
185            AngleBrackets::Missing => 0,
186            // Only lifetime arguments can be implied
187            AngleBrackets::Implied => self.gen_args.args.len(),
188            AngleBrackets::Available => self.gen_args.num_lifetime_args(),
189        }
190    }
191
192    fn num_provided_type_or_const_args(&self) -> usize {
193        match self.angle_brackets {
194            AngleBrackets::Missing => 0,
195            // Only lifetime arguments can be implied
196            AngleBrackets::Implied => 0,
197            AngleBrackets::Available => self.gen_args.num_generic_params(),
198        }
199    }
200
201    fn num_expected_lifetime_args(&self) -> usize {
202        let num_provided_args = self.num_provided_lifetime_args();
203        match self.gen_args_info {
204            MissingLifetimes { num_missing_args } => num_provided_args + num_missing_args,
205            ExcessLifetimes { num_redundant_args } => num_provided_args - num_redundant_args,
206            _ => 0,
207        }
208    }
209
210    fn num_expected_type_or_const_args(&self) -> usize {
211        let num_provided_args = self.num_provided_type_or_const_args();
212        match self.gen_args_info {
213            MissingTypesOrConsts { num_missing_args, .. } => num_provided_args + num_missing_args,
214            ExcessTypesOrConsts { num_redundant_args, .. } => {
215                num_provided_args - num_redundant_args
216            }
217            _ => 0,
218        }
219    }
220
221    // Gives the number of expected arguments taking into account default arguments
222    fn num_expected_type_or_const_args_including_defaults(&self) -> usize {
223        let provided_args = self.num_provided_type_or_const_args();
224        match self.gen_args_info {
225            MissingTypesOrConsts { num_missing_args, num_default_params, .. } => {
226                provided_args + num_missing_args - num_default_params
227            }
228            ExcessTypesOrConsts { num_redundant_args, num_default_params, .. } => {
229                provided_args - num_redundant_args - num_default_params
230            }
231            _ => 0,
232        }
233    }
234
235    fn num_missing_lifetime_args(&self) -> usize {
236        let missing_args = self.num_expected_lifetime_args() - self.num_provided_lifetime_args();
237        if !(missing_args > 0) {
    ::core::panicking::panic("assertion failed: missing_args > 0")
};assert!(missing_args > 0);
238        missing_args
239    }
240
241    fn num_missing_type_or_const_args(&self) -> usize {
242        let missing_args = self.num_expected_type_or_const_args_including_defaults()
243            - self.num_provided_type_or_const_args();
244        if !(missing_args > 0) {
    ::core::panicking::panic("assertion failed: missing_args > 0")
};assert!(missing_args > 0);
245        missing_args
246    }
247
248    fn num_excess_lifetime_args(&self) -> usize {
249        match self.gen_args_info {
250            ExcessLifetimes { num_redundant_args } => num_redundant_args,
251            _ => 0,
252        }
253    }
254
255    fn num_excess_type_or_const_args(&self) -> usize {
256        match self.gen_args_info {
257            ExcessTypesOrConsts { num_redundant_args, .. } => num_redundant_args,
258            _ => 0,
259        }
260    }
261
262    fn too_many_args_provided(&self) -> bool {
263        match self.gen_args_info {
264            MissingLifetimes { .. } | MissingTypesOrConsts { .. } => false,
265            ExcessLifetimes { num_redundant_args }
266            | ExcessTypesOrConsts { num_redundant_args, .. } => {
267                if !(num_redundant_args > 0) {
    ::core::panicking::panic("assertion failed: num_redundant_args > 0")
};assert!(num_redundant_args > 0);
268                true
269            }
270        }
271    }
272
273    fn not_enough_args_provided(&self) -> bool {
274        match self.gen_args_info {
275            MissingLifetimes { num_missing_args }
276            | MissingTypesOrConsts { num_missing_args, .. } => {
277                if !(num_missing_args > 0) {
    ::core::panicking::panic("assertion failed: num_missing_args > 0")
};assert!(num_missing_args > 0);
278                true
279            }
280            ExcessLifetimes { .. } | ExcessTypesOrConsts { .. } => false,
281        }
282    }
283
284    // Helper method to get the index offset in angle brackets, at which type or const arguments
285    // start appearing
286    fn get_lifetime_args_offset(&self) -> usize {
287        match self.gen_args_info {
288            MissingLifetimes { .. } | ExcessLifetimes { .. } => 0,
289            MissingTypesOrConsts { args_offset, .. } | ExcessTypesOrConsts { args_offset, .. } => {
290                args_offset
291            }
292        }
293    }
294
295    fn get_num_default_params(&self) -> usize {
296        match self.gen_args_info {
297            MissingTypesOrConsts { num_default_params, .. }
298            | ExcessTypesOrConsts { num_default_params, .. } => num_default_params,
299            _ => 0,
300        }
301    }
302
303    fn is_synth_provided(&self) -> bool {
304        match self.gen_args_info {
305            ExcessTypesOrConsts { synth_provided, .. } => synth_provided,
306            _ => false,
307        }
308    }
309
310    // Helper function to choose a quantifier word for the number of expected arguments
311    // and to give a bound for the number of expected arguments
312    fn get_quantifier_and_bound(&self) -> (&'static str, usize) {
313        if self.get_num_default_params() == 0 {
314            match self.gen_args_info {
315                MissingLifetimes { .. } | ExcessLifetimes { .. } => {
316                    ("", self.num_expected_lifetime_args())
317                }
318                MissingTypesOrConsts { .. } | ExcessTypesOrConsts { .. } => {
319                    ("", self.num_expected_type_or_const_args())
320                }
321            }
322        } else {
323            match self.gen_args_info {
324                MissingLifetimes { .. } => ("at least ", self.num_expected_lifetime_args()),
325                MissingTypesOrConsts { .. } => {
326                    ("at least ", self.num_expected_type_or_const_args_including_defaults())
327                }
328                ExcessLifetimes { .. } => ("at most ", self.num_expected_lifetime_args()),
329                ExcessTypesOrConsts { .. } => ("at most ", self.num_expected_type_or_const_args()),
330            }
331        }
332    }
333
334    // Creates lifetime name suggestions from the lifetime parameter names
335    fn get_lifetime_args_suggestions_from_param_names(
336        &self,
337        path_hir_id: hir::HirId,
338        num_params_to_take: usize,
339    ) -> String {
340        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs:340",
                        "rustc_hir_analysis::diagnostics::wrong_number_of_generic_args",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs"),
                        ::tracing_core::__macro_support::Option::Some(340u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::diagnostics::wrong_number_of_generic_args"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("path_hir_id")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("path_hir_id");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path_hir_id)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(?path_hir_id);
341
342        // If there was already a lifetime among the arguments, just replicate that one.
343        if let Some(lt) = self.gen_args.args.iter().find_map(|arg| match arg {
344            hir::GenericArg::Lifetime(lt) => Some(lt),
345            _ => None,
346        }) {
347            return std::iter::repeat_n(lt.to_string(), num_params_to_take)
348                .collect::<Vec<_>>()
349                .join(", ");
350        }
351
352        let mut ret = Vec::new();
353        let mut ty_id = None;
354        for (id, node) in self.tcx.hir_parent_iter(path_hir_id) {
355            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs:355",
                        "rustc_hir_analysis::diagnostics::wrong_number_of_generic_args",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs"),
                        ::tracing_core::__macro_support::Option::Some(355u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::diagnostics::wrong_number_of_generic_args"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("id")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("id");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&id)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(?id);
356            if let hir::Node::Ty(_) = node {
357                ty_id = Some(id);
358            }
359
360            // Suggest `'_` when in function parameter or elided function return.
361            if let Some(fn_decl) = node.fn_decl()
362                && let Some(ty_id) = ty_id
363            {
364                let in_arg = fn_decl.inputs.iter().any(|t| t.hir_id == ty_id);
365                let in_ret =
366                    #[allow(non_exhaustive_omitted_patterns)] match fn_decl.output {
    hir::FnRetTy::Return(ty) if ty.hir_id == ty_id => true,
    _ => false,
}matches!(fn_decl.output, hir::FnRetTy::Return(ty) if ty.hir_id == ty_id);
367
368                if in_arg || (in_ret && fn_decl.lifetime_elision_allowed()) {
369                    return std::iter::repeat_n("'_".to_owned(), num_params_to_take)
370                        .collect::<Vec<_>>()
371                        .join(", ");
372                }
373            }
374
375            // Suggest `'static` when in const/static item-like.
376            if let hir::Node::Item(hir::Item {
377                kind: hir::ItemKind::Static { .. } | hir::ItemKind::Const { .. },
378                ..
379            })
380            | hir::Node::TraitItem(hir::TraitItem {
381                kind: hir::TraitItemKind::Const { .. },
382                ..
383            })
384            | hir::Node::ImplItem(hir::ImplItem {
385                kind: hir::ImplItemKind::Const { .. },
386                ..
387            })
388            | hir::Node::ForeignItem(hir::ForeignItem {
389                kind: hir::ForeignItemKind::Static { .. },
390                ..
391            })
392            | hir::Node::AnonConst(..) = node
393            {
394                return std::iter::repeat_n(
395                    "'static".to_owned(),
396                    num_params_to_take.saturating_sub(ret.len()),
397                )
398                .collect::<Vec<_>>()
399                .join(", ");
400            }
401
402            let params = if let Some(generics) = node.generics() {
403                generics.params
404            } else if let hir::Node::Ty(ty) = node
405                && let hir::TyKind::FnPtr(fn_ptr) = ty.kind
406            {
407                fn_ptr.generic_params
408            } else {
409                &[]
410            };
411            ret.extend(params.iter().filter_map(|p| {
412                let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } =
413                    p.kind
414                else {
415                    return None;
416                };
417                let hir::ParamName::Plain(name) = p.name else { return None };
418                Some(name.to_string())
419            }));
420
421            if ret.len() >= num_params_to_take {
422                return ret[..num_params_to_take].join(", ");
423            }
424            // We cannot refer to lifetimes defined in an outer function.
425            if let hir::Node::Item(_) = node {
426                break;
427            }
428        }
429
430        // We could not gather enough lifetime parameters in the scope.
431        // We use the parameter names from the target type's definition instead.
432        self.gen_params
433            .own_params
434            .iter()
435            .skip(self.params_offset + self.num_provided_lifetime_args())
436            .take(num_params_to_take)
437            .map(|param| param.name.to_string())
438            .collect::<Vec<_>>()
439            .join(", ")
440    }
441
442    // Creates type or constant name suggestions from the provided parameter names
443    fn get_type_or_const_args_suggestions_from_param_names(
444        &self,
445        num_params_to_take: usize,
446    ) -> String {
447        self.get_type_or_const_arg_names(num_params_to_take)
448            .map(|(n, _)| n.to_string())
449            .intersperse(", ".to_string())
450            .collect()
451    }
452
453    // Lists type or constant names from the provided parameter names
454    fn get_type_or_const_arg_names(
455        &self,
456        num_params_to_take: usize,
457    ) -> impl Iterator<Item = (Symbol, Option<Ty<'tcx>>)> {
458        let is_in_a_method_call = self
459            .tcx
460            .hir_parent_iter(self.path_segment.hir_id)
461            .skip(1)
462            .find_map(|(_, node)| match node {
463                hir::Node::Expr(expr) => Some(expr),
464                _ => None,
465            })
466            .is_some_and(|expr| {
467                #[allow(non_exhaustive_omitted_patterns)] match expr.kind {
    hir::ExprKind::MethodCall(hir::PathSegment { args: Some(_), .. }, ..) =>
        true,
    _ => false,
}matches!(
468                    expr.kind,
469                    hir::ExprKind::MethodCall(hir::PathSegment { args: Some(_), .. }, ..)
470                )
471            });
472
473        let fn_sig = self.tcx.hir_get_if_local(self.def_id).and_then(hir::Node::fn_sig);
474        let is_used_in_input = move |def_id| {
475            fn_sig.is_some_and(|fn_sig| {
476                fn_sig.decl.inputs.iter().any(|ty| match ty.kind {
477                    hir::TyKind::Path(hir::QPath::Resolved(
478                        None,
479                        hir::Path { res: hir::def::Res::Def(_, id), .. },
480                    )) => *id == def_id,
481                    _ => false,
482                })
483            })
484        };
485        self.gen_params
486            .own_params
487            .iter()
488            .skip(self.params_offset + self.num_provided_type_or_const_args())
489            .take(num_params_to_take)
490            .map(move |param| match param.kind {
491                // If it's in method call (turbofish), it might be inferred from the expression (e.g. `.collect::<Vec<_>>()`)
492                // If it is being inferred from the item's inputs, no need to set it.
493                ty::GenericParamDefKind::Type { .. }
494                    if is_in_a_method_call || is_used_in_input(param.def_id) =>
495                {
496                    (kw::Underscore, None)
497                }
498                // FIXME: tcx.type_of(param.def_id) for consts
499                ty::GenericParamDefKind::Const { .. } => (
500                    param.name,
501                    Some(self.tcx.type_of(param.def_id).instantiate_identity().skip_norm_wip()),
502                ),
503                _ => (param.name, None),
504            })
505    }
506
507    fn get_unbound_associated_item(&self) -> Vec<&AssocItem> {
508        if self.tcx.is_trait(self.def_id) {
509            let items: &AssocItems = self.tcx.associated_items(self.def_id);
510            items
511                .in_definition_order()
512                .filter(|item| {
513                    item.can_have_equality_constraint(self.tcx)
514                        && !item.is_impl_trait_in_trait()
515                        && !self
516                            .gen_args
517                            .constraints
518                            .iter()
519                            .any(|constraint| constraint.ident.name == item.name())
520                })
521                .collect()
522        } else {
523            Vec::default()
524        }
525    }
526
527    fn create_error_message(&self) -> String {
528        let def_path = self.tcx.def_path_str(self.def_id);
529        let def_kind = self.tcx.def_descr(self.def_id);
530        let (quantifier, bound) = self.get_quantifier_and_bound();
531        let kind = self.kind();
532        let provided_lt_args = self.num_provided_lifetime_args();
533        let provided_type_or_const_args = self.num_provided_type_or_const_args();
534
535        let (provided_args_str, verb) = match self.gen_args_info {
536            MissingLifetimes { .. } | ExcessLifetimes { .. } => (
537                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} lifetime argument{1}",
                provided_lt_args,
                if provided_lt_args == 1 { "" } else { "s" }))
    })format!("{} lifetime argument{}", provided_lt_args, pluralize!(provided_lt_args)),
538                if provided_lt_args == 1 { "was" } else { "were" }pluralize!("was", provided_lt_args),
539            ),
540            MissingTypesOrConsts { .. } | ExcessTypesOrConsts { .. } => (
541                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} generic argument{1}",
                provided_type_or_const_args,
                if provided_type_or_const_args == 1 { "" } else { "s" }))
    })format!(
542                    "{} generic argument{}",
543                    provided_type_or_const_args,
544                    pluralize!(provided_type_or_const_args)
545                ),
546                if provided_type_or_const_args == 1 { "was" } else { "were" }pluralize!("was", provided_type_or_const_args),
547            ),
548        };
549
550        if self.gen_args.span_ext().is_some() {
551            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} takes {1}{2} {3} argument{4} but {5} {6} supplied",
                def_kind, quantifier, bound, kind,
                if bound == 1 { "" } else { "s" }, provided_args_str.as_str(),
                verb))
    })format!(
552                "{} takes {}{} {} argument{} but {} {} supplied",
553                def_kind,
554                quantifier,
555                bound,
556                kind,
557                pluralize!(bound),
558                provided_args_str.as_str(),
559                verb
560            )
561        } else {
562            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("missing generics for {0} `{1}`",
                def_kind, def_path))
    })format!("missing generics for {def_kind} `{def_path}`")
563        }
564    }
565
566    /// Builds the `expected 1 type argument / supplied 2 type arguments` message.
567    fn notify(&self, err: &mut Diag<'_>) {
568        let (quantifier, bound) = self.get_quantifier_and_bound();
569        let provided_args = self.num_provided_args();
570
571        err.span_label(
572            self.path_segment.ident.span,
573            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected {0}{1} {2} argument{3}",
                quantifier, bound, self.kind(),
                if bound == 1 { "" } else { "s" }))
    })format!(
574                "expected {}{} {} argument{}",
575                quantifier,
576                bound,
577                self.kind(),
578                pluralize!(bound),
579            ),
580        );
581
582        // When too many arguments were provided, we don't highlight each of them, because it
583        // would overlap with the suggestion to remove them:
584        //
585        // ```
586        // type Foo = Bar<usize, usize>;
587        //                -----  ----- supplied 2 type arguments
588        //                     ^^^^^^^ remove this type argument
589        // ```
590        if self.too_many_args_provided() {
591            return;
592        }
593
594        let args = self
595            .gen_args
596            .args
597            .iter()
598            .skip(self.get_lifetime_args_offset())
599            .take(provided_args)
600            .enumerate();
601
602        for (i, arg) in args {
603            err.span_label(
604                arg.span(),
605                if i + 1 == provided_args {
606                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("supplied {0} {1} argument{2}",
                provided_args, self.kind(),
                if provided_args == 1 { "" } else { "s" }))
    })format!(
607                        "supplied {} {} argument{}",
608                        provided_args,
609                        self.kind(),
610                        pluralize!(provided_args)
611                    )
612                } else {
613                    String::new()
614                },
615            );
616        }
617    }
618
619    fn suggest(&self, err: &mut Diag<'_>) {
620        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs:620",
                        "rustc_hir_analysis::diagnostics::wrong_number_of_generic_args",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs"),
                        ::tracing_core::__macro_support::Option::Some(620u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::diagnostics::wrong_number_of_generic_args"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("suggest(self.provided {0:?}, self.gen_args.span(): {1:?})",
                                                    self.num_provided_args(), self.gen_args.span()) as
                                            &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(
621            "suggest(self.provided {:?}, self.gen_args.span(): {:?})",
622            self.num_provided_args(),
623            self.gen_args.span(),
624        );
625
626        match self.angle_brackets {
627            AngleBrackets::Missing | AngleBrackets::Implied => self.suggest_adding_args(err),
628            AngleBrackets::Available => {
629                if self.not_enough_args_provided() {
630                    self.suggest_adding_args(err);
631                } else if self.too_many_args_provided() {
632                    self.suggest_moving_args_from_assoc_fn_to_trait(err);
633                    self.suggest_removing_args_or_generics(err);
634                } else {
635                    ::core::panicking::unreachable_default_msg();unreachable!();
636                }
637            }
638        }
639    }
640
641    /// Suggests to add missing argument(s) when current invocation site already contains some
642    /// generics:
643    ///
644    /// ```text
645    /// type Map = HashMap<String>;
646    /// ```
647    fn suggest_adding_args(&self, err: &mut Diag<'_>) {
648        if self.gen_args.parenthesized != hir::GenericArgsParentheses::No {
649            return;
650        }
651
652        // Do not suggest angle-bracketed arguments that require the unstable feature.
653        if !self.tcx.features().unboxed_closures()
654            && self.tcx.is_trait(self.def_id)
655            && self.tcx.trait_def(self.def_id).paren_sugar
656        {
657            return;
658        }
659
660        match self.gen_args_info {
661            MissingLifetimes { .. } => {
662                self.suggest_adding_lifetime_args(err);
663            }
664            MissingTypesOrConsts { .. } => {
665                self.suggest_adding_type_and_const_args(err);
666            }
667            ExcessTypesOrConsts { .. } => {
668                // this can happen with `[const] T` where T isn't a `const trait`.
669            }
670            _ => ::core::panicking::unreachable_default_msg()unreachable!(),
671        }
672    }
673
674    fn suggest_adding_lifetime_args(&self, err: &mut Diag<'_>) {
675        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs:675",
                        "rustc_hir_analysis::diagnostics::wrong_number_of_generic_args",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs"),
                        ::tracing_core::__macro_support::Option::Some(675u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::diagnostics::wrong_number_of_generic_args"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("suggest_adding_lifetime_args(path_segment: {0:?})",
                                                    self.path_segment) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("suggest_adding_lifetime_args(path_segment: {:?})", self.path_segment);
676        let num_missing_args = self.num_missing_lifetime_args();
677        let num_params_to_take = num_missing_args;
678        let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("add missing {0} argument{1}",
                self.kind(), if num_missing_args == 1 { "" } else { "s" }))
    })format!("add missing {} argument{}", self.kind(), pluralize!(num_missing_args));
679
680        let suggested_args = self.get_lifetime_args_suggestions_from_param_names(
681            self.path_segment.hir_id,
682            num_params_to_take,
683        );
684        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs:684",
                        "rustc_hir_analysis::diagnostics::wrong_number_of_generic_args",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs"),
                        ::tracing_core::__macro_support::Option::Some(684u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::diagnostics::wrong_number_of_generic_args"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("suggested_args: {0:?}",
                                                    suggested_args) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("suggested_args: {suggested_args:?}");
685
686        match self.angle_brackets {
687            AngleBrackets::Missing => {
688                let span = self.path_segment.ident.span;
689
690                // insert a suggestion of the form "Y<'a, 'b>"
691                let sugg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}>", suggested_args))
    })format!("<{suggested_args}>");
692                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs:692",
                        "rustc_hir_analysis::diagnostics::wrong_number_of_generic_args",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs"),
                        ::tracing_core::__macro_support::Option::Some(692u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::diagnostics::wrong_number_of_generic_args"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("sugg: {0:?}",
                                                    sugg) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("sugg: {:?}", sugg);
693
694                err.span_suggestion_verbose(
695                    span.shrink_to_hi(),
696                    msg,
697                    sugg,
698                    Applicability::HasPlaceholders,
699                );
700            }
701
702            AngleBrackets::Available => {
703                let (sugg_span, is_first) = if self.num_provided_lifetime_args() == 0 {
704                    (self.gen_args.span().unwrap().shrink_to_lo(), true)
705                } else {
706                    let last_lt = &self.gen_args.args[self.num_provided_lifetime_args() - 1];
707                    (last_lt.span().shrink_to_hi(), false)
708                };
709                let has_non_lt_args = self.num_provided_type_or_const_args() != 0;
710                let has_constraints = !self.gen_args.constraints.is_empty();
711
712                let sugg_prefix = if is_first { "" } else { ", " };
713                let sugg_suffix =
714                    if is_first && (has_non_lt_args || has_constraints) { ", " } else { "" };
715
716                let sugg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}{2}", sugg_prefix,
                suggested_args, sugg_suffix))
    })format!("{sugg_prefix}{suggested_args}{sugg_suffix}");
717                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs:717",
                        "rustc_hir_analysis::diagnostics::wrong_number_of_generic_args",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs"),
                        ::tracing_core::__macro_support::Option::Some(717u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::diagnostics::wrong_number_of_generic_args"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("sugg: {0:?}",
                                                    sugg) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("sugg: {:?}", sugg);
718
719                err.span_suggestion_verbose(sugg_span, msg, sugg, Applicability::HasPlaceholders);
720            }
721            AngleBrackets::Implied => {
722                // We never encounter missing lifetimes in situations in which lifetimes are elided
723                ::core::panicking::unreachable_default_msg();unreachable!();
724            }
725        }
726    }
727
728    fn suggest_adding_type_and_const_args(&self, err: &mut Diag<'_>) {
729        let num_missing_args = self.num_missing_type_or_const_args();
730        let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("add missing {0} argument{1}",
                self.kind(), if num_missing_args == 1 { "" } else { "s" }))
    })format!("add missing {} argument{}", self.kind(), pluralize!(num_missing_args));
731
732        let suggested_args =
733            self.get_type_or_const_args_suggestions_from_param_names(num_missing_args);
734        let arg_names: Vec<_> = self.get_type_or_const_arg_names(num_missing_args).collect();
735        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs:735",
                        "rustc_hir_analysis::diagnostics::wrong_number_of_generic_args",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs"),
                        ::tracing_core::__macro_support::Option::Some(735u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::diagnostics::wrong_number_of_generic_args"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("suggested_args: {0:?}",
                                                    suggested_args) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("suggested_args: {:?}", suggested_args);
736        let mut impl_sugg = None;
737        if let DefKind::Impl { .. } = self.tcx.def_kind(self.cx_def_id) {
738            let mut impl_args = ::alloc::vec::Vec::new()vec![];
739            let i = self.tcx.hir_node_by_def_id(self.cx_def_id).expect_item().expect_impl();
740            for (arg, const_ty) in arg_names {
741                if i.generics.get_named(arg).is_none() {
742                    impl_args.push(match const_ty {
743                        Some(ty) => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("const {0}: {1}", arg, ty))
    })format!("const {arg}: {ty}"),
744                        None => arg.to_string(),
745                    })
746                }
747            }
748            if !impl_args.is_empty() {
749                impl_sugg = Some(match i.generics.span_for_param_suggestion() {
750                    Some(span) => (span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(", {0}", impl_args.join(", ")))
    })format!(", {}", impl_args.join(", "))),
751                    None => (i.generics.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}>", impl_args.join(", ")))
    })format!("<{}>", impl_args.join(", "))),
752                });
753            }
754        }
755
756        match self.angle_brackets {
757            AngleBrackets::Missing | AngleBrackets::Implied => {
758                let span = self.path_segment.ident.span;
759
760                // insert a suggestion of the form "Y<T, U>"
761                let mut sugg = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(span.shrink_to_hi(),
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("<{0}>", suggested_args))
                        }))]))vec![(span.shrink_to_hi(), format!("<{suggested_args}>"))];
762                if let Some(impl_sugg) = impl_sugg {
763                    sugg.insert(0, impl_sugg);
764                }
765                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs:765",
                        "rustc_hir_analysis::diagnostics::wrong_number_of_generic_args",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs"),
                        ::tracing_core::__macro_support::Option::Some(765u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::diagnostics::wrong_number_of_generic_args"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("sugg")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("sugg");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sugg)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(?sugg);
766                err.multipart_suggestion(msg, sugg, Applicability::HasPlaceholders);
767            }
768            AngleBrackets::Available => {
769                let gen_args_span = self.gen_args.span().unwrap();
770                let sugg_offset =
771                    self.get_lifetime_args_offset() + self.num_provided_type_or_const_args();
772
773                let (sugg_span, is_first) = if sugg_offset == 0 {
774                    (gen_args_span.shrink_to_lo(), true)
775                } else {
776                    let arg_span = self.gen_args.args[sugg_offset - 1].span();
777                    // If we came here then inferred lifetime's spans can only point
778                    // to either the opening bracket or to the space right after.
779                    // Both of these spans have an `hi` lower than or equal to the span
780                    // of the generics excluding the brackets.
781                    // This allows us to check if `arg_span` is the artificial span of
782                    // an inferred lifetime, in which case the generic we're suggesting to
783                    // add will be the first visible, even if it isn't the actual first generic.
784                    (arg_span.shrink_to_hi(), arg_span.hi() <= gen_args_span.lo())
785                };
786
787                let sugg_prefix = if is_first { "" } else { ", " };
788                let sugg_suffix =
789                    if is_first && !self.gen_args.constraints.is_empty() { ", " } else { "" };
790
791                let mut sugg =
792                    ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(sugg_span,
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("{0}{1}{2}", sugg_prefix,
                                    suggested_args, sugg_suffix))
                        }))]))vec![(sugg_span, format!("{sugg_prefix}{suggested_args}{sugg_suffix}"))];
793                if let Some(impl_sugg) = impl_sugg {
794                    sugg.insert(0, impl_sugg);
795                }
796                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs:796",
                        "rustc_hir_analysis::diagnostics::wrong_number_of_generic_args",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs"),
                        ::tracing_core::__macro_support::Option::Some(796u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::diagnostics::wrong_number_of_generic_args"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("sugg")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("sugg");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sugg)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(?sugg);
797                err.multipart_suggestion(msg, sugg, Applicability::HasPlaceholders);
798            }
799        }
800    }
801
802    /// Suggests moving redundant argument(s) of an associate function to the
803    /// trait it belongs to.
804    ///
805    /// ```compile_fail
806    /// Into::into::<Option<_>>(42) // suggests considering `Into::<Option<_>>::into(42)`
807    /// ```
808    fn suggest_moving_args_from_assoc_fn_to_trait(&self, err: &mut Diag<'_>) {
809        let Some(trait_) = self.tcx.trait_of_assoc(self.def_id) else {
810            return;
811        };
812
813        // Skip suggestion when the associated function is itself generic, it is unclear
814        // how to split the provided parameters between those to suggest to the trait and
815        // those to remain on the associated type.
816        let num_assoc_fn_expected_args =
817            self.num_expected_type_or_const_args() + self.num_expected_lifetime_args();
818        if num_assoc_fn_expected_args > 0 {
819            return;
820        }
821
822        let num_assoc_fn_excess_args =
823            self.num_excess_type_or_const_args() + self.num_excess_lifetime_args();
824
825        let trait_generics = self.tcx.generics_of(trait_);
826        let num_trait_generics_except_self =
827            trait_generics.count() - if trait_generics.has_self { 1 } else { 0 };
828
829        let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider moving {0} generic argument{1} to the `{2}` trait, which takes up to {3} argument{1}",
                if num_assoc_fn_excess_args == 1 { "this" } else { "these" },
                if num_assoc_fn_excess_args == 1 { "" } else { "s" },
                self.tcx.item_name(trait_), num_trait_generics_except_self))
    })format!(
830            "consider moving {these} generic argument{s} to the `{name}` trait, which takes up to {num} argument{s}",
831            these = pluralize!("this", num_assoc_fn_excess_args),
832            s = pluralize!(num_assoc_fn_excess_args),
833            name = self.tcx.item_name(trait_),
834            num = num_trait_generics_except_self,
835        );
836
837        if let hir::Node::Expr(expr) = self.tcx.parent_hir_node(self.path_segment.hir_id) {
838            match &expr.kind {
839                hir::ExprKind::Path(qpath) => self
840                    .suggest_moving_args_from_assoc_fn_to_trait_for_qualified_path(
841                        err,
842                        qpath,
843                        msg,
844                        num_assoc_fn_excess_args,
845                        num_trait_generics_except_self,
846                    ),
847                hir::ExprKind::MethodCall(..) => self
848                    .suggest_moving_args_from_assoc_fn_to_trait_for_method_call(
849                        err,
850                        trait_,
851                        expr,
852                        msg,
853                        num_assoc_fn_excess_args,
854                        num_trait_generics_except_self,
855                    ),
856                _ => return,
857            }
858        }
859    }
860
861    fn suggest_moving_args_from_assoc_fn_to_trait_for_qualified_path(
862        &self,
863        err: &mut Diag<'_>,
864        qpath: &'tcx hir::QPath<'tcx>,
865        msg: String,
866        num_assoc_fn_excess_args: usize,
867        num_trait_generics_except_self: usize,
868    ) {
869        if let hir::QPath::Resolved(_, path) = qpath
870            && let Some(trait_path_segment) = path.segments.get(0)
871        {
872            let num_generic_args_supplied_to_trait = trait_path_segment.args().num_generic_params();
873
874            if num_generic_args_supplied_to_trait + num_assoc_fn_excess_args
875                == num_trait_generics_except_self
876                && let Some(span) = self.gen_args.span_ext()
877                && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
878            {
879                let sugg = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(self.path_segment.ident.span,
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("{0}::{1}", snippet,
                                    self.path_segment.ident))
                        })),
                (span.with_lo(self.path_segment.ident.span.hi()),
                    "".to_owned())]))vec![
880                    (
881                        self.path_segment.ident.span,
882                        format!("{}::{}", snippet, self.path_segment.ident),
883                    ),
884                    (span.with_lo(self.path_segment.ident.span.hi()), "".to_owned()),
885                ];
886
887                err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect);
888            }
889        }
890    }
891
892    fn suggest_moving_args_from_assoc_fn_to_trait_for_method_call(
893        &self,
894        err: &mut Diag<'_>,
895        trait_def_id: DefId,
896        expr: &'tcx hir::Expr<'tcx>,
897        msg: String,
898        num_assoc_fn_excess_args: usize,
899        num_trait_generics_except_self: usize,
900    ) {
901        let sm = self.tcx.sess.source_map();
902        let hir::ExprKind::MethodCall(_, rcvr, args, _) = expr.kind else {
903            return;
904        };
905        if num_assoc_fn_excess_args != num_trait_generics_except_self {
906            return;
907        }
908        let Some(gen_args) = self.gen_args.span_ext() else {
909            return;
910        };
911        let Ok(generics) = sm.span_to_snippet(gen_args) else {
912            return;
913        };
914        let Ok(rcvr) =
915            sm.span_to_snippet(rcvr.span.find_ancestor_inside(expr.span).unwrap_or(rcvr.span))
916        else {
917            return;
918        };
919        let Ok(rest) = (match args {
920            [] => Ok(String::new()),
921            [arg] => {
922                sm.span_to_snippet(arg.span.find_ancestor_inside(expr.span).unwrap_or(arg.span))
923            }
924            [first, .., last] => {
925                let first_span = first.span.find_ancestor_inside(expr.span).unwrap_or(first.span);
926                let last_span = last.span.find_ancestor_inside(expr.span).unwrap_or(last.span);
927                sm.span_to_snippet(first_span.to(last_span))
928            }
929        }) else {
930            return;
931        };
932        let comma = if args.len() > 0 { ", " } else { "" };
933        let trait_path = self.tcx.def_path_str(trait_def_id);
934        let method_name = self.tcx.item_name(self.def_id);
935        err.span_suggestion_verbose(
936            expr.span,
937            msg,
938            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}::{1}::{2}({3}{4}{5})",
                trait_path, generics, method_name, rcvr, comma, rest))
    })format!("{trait_path}::{generics}::{method_name}({rcvr}{comma}{rest})"),
939            Applicability::MaybeIncorrect,
940        );
941    }
942
943    /// Suggests to remove redundant argument(s):
944    ///
945    /// ```text
946    /// type Map = HashMap<String, String, String, String>;
947    /// ```
948    fn suggest_removing_args_or_generics(&self, err: &mut Diag<'_>) {
949        let num_provided_lt_args = self.num_provided_lifetime_args();
950        let num_provided_type_const_args = self.num_provided_type_or_const_args();
951        let unbound_assoc_items = self.get_unbound_associated_item();
952        let num_provided_args = num_provided_lt_args + num_provided_type_const_args;
953        if !(num_provided_args > 0) {
    ::core::panicking::panic("assertion failed: num_provided_args > 0")
};assert!(num_provided_args > 0);
954
955        let num_redundant_lt_args = self.num_excess_lifetime_args();
956        let num_redundant_type_or_const_args = self.num_excess_type_or_const_args();
957        let num_redundant_args = num_redundant_lt_args + num_redundant_type_or_const_args;
958
959        let redundant_lifetime_args = num_redundant_lt_args > 0;
960        let redundant_type_or_const_args = num_redundant_type_or_const_args > 0;
961
962        let remove_entire_generics = num_redundant_args >= self.gen_args.args.len();
963
964        let remove_lifetime_args = |err: &mut Diag<'_>| {
965            let mut lt_arg_spans = Vec::new();
966            let mut found_redundant = false;
967            for arg in self.gen_args.args {
968                if let hir::GenericArg::Lifetime(_) = arg {
969                    lt_arg_spans.push(arg.span());
970                    if lt_arg_spans.len() > self.num_expected_lifetime_args() {
971                        found_redundant = true;
972                    }
973                } else if found_redundant {
974                    // Argument which is redundant and separated like this `'c`
975                    // is not included to avoid including `Bar` in span.
976                    // ```
977                    // type Foo<'a, T> = &'a T;
978                    // let _: Foo<'a, 'b, Bar, 'c>;
979                    // ```
980                    break;
981                }
982            }
983
984            let span_lo_redundant_lt_args = if self.num_expected_lifetime_args() == 0 {
985                lt_arg_spans[0]
986            } else {
987                lt_arg_spans[self.num_expected_lifetime_args() - 1]
988            };
989            let span_hi_redundant_lt_args = lt_arg_spans[lt_arg_spans.len() - 1];
990
991            let span_redundant_lt_args =
992                span_lo_redundant_lt_args.shrink_to_hi().to(span_hi_redundant_lt_args);
993            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs:993",
                        "rustc_hir_analysis::diagnostics::wrong_number_of_generic_args",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs"),
                        ::tracing_core::__macro_support::Option::Some(993u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::diagnostics::wrong_number_of_generic_args"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("span_redundant_lt_args: {0:?}",
                                                    span_redundant_lt_args) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("span_redundant_lt_args: {:?}", span_redundant_lt_args);
994
995            let num_redundant_lt_args = lt_arg_spans.len() - self.num_expected_lifetime_args();
996            let msg_lifetimes =
997                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("remove the lifetime argument{0}",
                if num_redundant_lt_args == 1 { "" } else { "s" }))
    })format!("remove the lifetime argument{s}", s = pluralize!(num_redundant_lt_args));
998
999            err.span_suggestion_short(
1000                span_redundant_lt_args,
1001                msg_lifetimes,
1002                "",
1003                Applicability::MaybeIncorrect,
1004            );
1005        };
1006
1007        let remove_type_or_const_args = |err: &mut Diag<'_>| {
1008            let mut gen_arg_spans = Vec::new();
1009            let mut found_redundant = false;
1010            for arg in self.gen_args.args {
1011                match arg {
1012                    hir::GenericArg::Type(_)
1013                    | hir::GenericArg::Const(_)
1014                    | hir::GenericArg::Infer(_) => {
1015                        gen_arg_spans.push(arg.span());
1016                        if gen_arg_spans.len() > self.num_expected_type_or_const_args() {
1017                            found_redundant = true;
1018                        }
1019                    }
1020                    _ if found_redundant => break,
1021                    _ => {}
1022                }
1023            }
1024
1025            let span_lo_redundant_type_or_const_args =
1026                if self.num_expected_type_or_const_args() == 0 {
1027                    gen_arg_spans[0]
1028                } else {
1029                    gen_arg_spans[self.num_expected_type_or_const_args() - 1]
1030                };
1031            let span_hi_redundant_type_or_const_args = gen_arg_spans[gen_arg_spans.len() - 1];
1032            if span_lo_redundant_type_or_const_args.ctxt()
1033                != span_hi_redundant_type_or_const_args.ctxt()
1034            {
1035                return;
1036            }
1037            let span_redundant_type_or_const_args = span_lo_redundant_type_or_const_args
1038                .shrink_to_hi()
1039                .to(span_hi_redundant_type_or_const_args);
1040
1041            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs:1041",
                        "rustc_hir_analysis::diagnostics::wrong_number_of_generic_args",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs"),
                        ::tracing_core::__macro_support::Option::Some(1041u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::diagnostics::wrong_number_of_generic_args"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("span_redundant_type_or_const_args: {0:?}",
                                                    span_redundant_type_or_const_args) as
                                            &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("span_redundant_type_or_const_args: {:?}", span_redundant_type_or_const_args);
1042
1043            let num_redundant_gen_args =
1044                gen_arg_spans.len() - self.num_expected_type_or_const_args();
1045            let msg_types_or_consts = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("remove the unnecessary generic argument{0}",
                if num_redundant_gen_args == 1 { "" } else { "s" }))
    })format!(
1046                "remove the unnecessary generic argument{s}",
1047                s = pluralize!(num_redundant_gen_args),
1048            );
1049
1050            err.span_suggestion_short(
1051                span_redundant_type_or_const_args,
1052                msg_types_or_consts,
1053                "",
1054                Applicability::MaybeIncorrect,
1055            );
1056        };
1057
1058        // If there is an identical amount of unbound associated items and excess generic args
1059        // suggest turning the generic args into associated item bindings
1060        if unbound_assoc_items.len() == num_redundant_type_or_const_args
1061            && !unbound_assoc_items.is_empty()
1062        {
1063            // Don't suggest if we're in a trait impl as
1064            // that would result in invalid syntax (fixes #116464)
1065            if !self.is_in_trait_impl() {
1066                let unused_generics = &self.gen_args.args[self.num_expected_type_or_const_args()..];
1067                let mut unbound_assoc_consts = unbound_assoc_items
1068                    .iter()
1069                    .filter(|item| #[allow(non_exhaustive_omitted_patterns)] match item.kind {
    ty::AssocKind::Const { .. } => true,
    _ => false,
}matches!(item.kind, ty::AssocKind::Const { .. }));
1070                let mut unbound_assoc_types =
1071                    unbound_assoc_items.iter().filter(|item| item.is_type());
1072                let suggestions = unused_generics
1073                    .iter()
1074                    .filter_map(|potential| {
1075                        let item = match potential {
1076                            hir::GenericArg::Const(_) => unbound_assoc_consts.next(),
1077                            hir::GenericArg::Type(_) => unbound_assoc_types.next(),
1078                            _ => None,
1079                        }?;
1080                        Some((
1081                            potential.span().shrink_to_lo(),
1082                            // FIXME: This doesn't account for generic associated items
1083                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} = ",
                self.tcx.item_ident(item.def_id)))
    })format!("{} = ", self.tcx.item_ident(item.def_id)),
1084                        ))
1085                    })
1086                    .collect::<Vec<_>>();
1087
1088                if !suggestions.is_empty() {
1089                    let s = if suggestions.len() == 1 { "" } else { "s" }pluralize!(suggestions.len());
1090                    let article = if suggestions.len() == 1 { "an " } else { "" };
1091                    err.multipart_suggestion(
1092                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("turn the generic argument{0} into {1}associated item binding{0}",
                s, article))
    })format!(
1093                            "turn the generic argument{s} into {article}associated item binding{s}"
1094                        ),
1095                        suggestions,
1096                        Applicability::MaybeIncorrect,
1097                    );
1098                }
1099            }
1100        } else if remove_entire_generics {
1101            let span = self
1102                .path_segment
1103                .args
1104                .unwrap()
1105                .span_ext()
1106                .unwrap()
1107                .with_lo(self.path_segment.ident.span.hi());
1108
1109            let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("remove the unnecessary {0}generics",
                if self.gen_args.parenthesized ==
                        hir::GenericArgsParentheses::ParenSugar {
                    "parenthetical "
                } else { "" }))
    })format!(
1110                "remove the unnecessary {}generics",
1111                if self.gen_args.parenthesized == hir::GenericArgsParentheses::ParenSugar {
1112                    "parenthetical "
1113                } else {
1114                    ""
1115                },
1116            );
1117
1118            if span.is_empty() {
1119                // HACK: Avoid ICE when types with the same name with `derive`s are in the same scope:
1120                //     struct NotSM;
1121                //     #[derive(PartialEq, Eq)]
1122                //     struct NotSM<T>(T);
1123                // With the above code, the suggestion would be to remove the generics of the first
1124                // `NotSM`, which doesn't *have* generics, so we would suggest to remove no code with
1125                // no code, which would trigger an `assert!` later. Ideally, we would do something a
1126                // bit more principled. See closed PR #109082.
1127            } else {
1128                err.span_suggestion_short(span, msg, "", Applicability::MaybeIncorrect);
1129            }
1130        } else if redundant_lifetime_args && redundant_type_or_const_args {
1131            remove_lifetime_args(err);
1132            remove_type_or_const_args(err);
1133        } else if redundant_lifetime_args {
1134            remove_lifetime_args(err);
1135        } else {
1136            if !redundant_type_or_const_args {
    ::core::panicking::panic("assertion failed: redundant_type_or_const_args")
};assert!(redundant_type_or_const_args);
1137            remove_type_or_const_args(err);
1138        }
1139    }
1140
1141    /// Builds the `type defined here` message.
1142    fn show_definition(&self, err: &mut Diag<'_>) {
1143        let Some(def_span) = self.tcx.def_ident_span(self.def_id) else { return };
1144        if !self.tcx.sess.source_map().is_span_accessible(def_span) {
1145            return;
1146        };
1147        let mut spans: MultiSpan = def_span.into();
1148
1149        let msg = {
1150            let def_kind = self.tcx.def_descr(self.def_id);
1151            let (quantifier, bound) = self.get_quantifier_and_bound();
1152            if let hir::def::DefKind::AssocFn | hir::def::DefKind::AssocTy =
1153                self.tcx.def_kind(self.def_id)
1154            {
1155                spans.push_span_context(
1156                    self.tcx.def_span(self.tcx.parent(self.def_id)).shrink_to_lo(),
1157                );
1158            }
1159
1160            let params = if bound == 0 {
1161                String::new()
1162            } else {
1163                let params = self
1164                    .gen_params
1165                    .own_params
1166                    .iter()
1167                    .skip(self.params_offset)
1168                    .take(bound)
1169                    .map(|param| {
1170                        let span = self.tcx.def_span(param.def_id);
1171                        spans.push_span_label(span, "");
1172                        param
1173                    })
1174                    .map(|param| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}`", param.name))
    })format!("`{}`", param.name))
1175                    .collect::<Vec<_>>()
1176                    .join(", ");
1177
1178                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(": {0}", params))
    })format!(": {params}")
1179            };
1180
1181            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} defined here, with {1}{2} {3} parameter{4}{5}",
                def_kind, quantifier, bound, self.kind(),
                if bound == 1 { "" } else { "s" }, params))
    })format!(
1182                "{} defined here, with {}{} {} parameter{}{}",
1183                def_kind,
1184                quantifier,
1185                bound,
1186                self.kind(),
1187                pluralize!(bound),
1188                params,
1189            )
1190        };
1191
1192        err.span_note(spans, msg);
1193    }
1194
1195    /// Add note if `impl Trait` is explicitly specified.
1196    fn note_synth_provided(&self, err: &mut Diag<'_>) {
1197        if !self.is_synth_provided() {
1198            return;
1199        }
1200
1201        err.note("`impl Trait` cannot be explicitly specified as a generic argument");
1202    }
1203}
1204
1205impl<'a> Diagnostic<'a> for WrongNumberOfGenericArgs<'_, '_> {
1206    fn into_diag(
1207        self,
1208        dcx: rustc_errors::DiagCtxtHandle<'a>,
1209        level: rustc_errors::Level,
1210    ) -> Diag<'a> {
1211        let msg = self.create_error_message();
1212        let mut err = Diag::new(dcx, level, msg);
1213        err.code(E0107);
1214        err.span(self.path_segment.ident.span);
1215
1216        let cx_span = self.tcx.def_span(self.cx_def_id);
1217        if cx_span.in_derive_expansion() {
1218            // Very likely this is a botched `derive` which passes the iten name straight
1219            // through, but doesn't support type parameters.
1220            err.span_label(
1221                cx_span.ctxt().outer_expn_data().call_site,
1222                "this derive macro might not support items with generic parameters",
1223            );
1224        } else {
1225            self.notify(&mut err);
1226            self.suggest(&mut err);
1227            self.show_definition(&mut err);
1228            self.note_synth_provided(&mut err);
1229        }
1230
1231        err
1232    }
1233}