Skip to main content

rustc_hir_analysis/hir_ty_lowering/
generics.rs

1use rustc_ast::ast::ParamKindOrd;
2use rustc_errors::codes::*;
3use rustc_errors::{
4    Applicability, Diag, DiagCtxtHandle, Diagnostic, ErrorGuaranteed, Level, MultiSpan,
5    struct_span_code_err,
6};
7use rustc_hir::def::{DefKind, Res};
8use rustc_hir::def_id::DefId;
9use rustc_hir::{self as hir, GenericArg};
10use rustc_middle::ty::{
11    self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty,
12};
13use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS;
14use rustc_span::kw;
15use rustc_trait_selection::traits;
16use smallvec::SmallVec;
17use tracing::{debug, instrument};
18
19use super::{HirTyLowerer, IsMethodCall};
20use crate::diagnostics::wrong_number_of_generic_args::{GenericArgsInfo, WrongNumberOfGenericArgs};
21use crate::hir_ty_lowering::errors::prohibit_assoc_item_constraint;
22use crate::hir_ty_lowering::{
23    ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition,
24    GenericArgsLowerer,
25};
26
27/// Report an error that a generic argument did not match the generic parameter that was
28/// expected.
29fn generic_arg_mismatch_err(
30    cx: &dyn HirTyLowerer<'_>,
31    arg: &GenericArg<'_>,
32    param: &GenericParamDef,
33    possible_ordering_error: bool,
34    help: Option<String>,
35) -> ErrorGuaranteed {
36    let tcx = cx.tcx();
37    let sess = tcx.sess;
38    let mut err = {
    cx.dcx().struct_span_err(arg.span(),
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("{0} provided when a {1} was expected",
                            arg.descr(), param.kind.descr()))
                })).with_code(E0747)
}struct_span_code_err!(
39        cx.dcx(),
40        arg.span(),
41        E0747,
42        "{} provided when a {} was expected",
43        arg.descr(),
44        param.kind.descr(),
45    );
46
47    let add_braces_suggestion = |arg: &GenericArg<'_>, err: &mut Diag<'_>| {
48        let suggestions = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(arg.span().shrink_to_lo(), String::from("{ ")),
                (arg.span().shrink_to_hi(), String::from(" }"))]))vec![
49            (arg.span().shrink_to_lo(), String::from("{ ")),
50            (arg.span().shrink_to_hi(), String::from(" }")),
51        ];
52        err.multipart_suggestion(
53            "if this generic argument was intended as a const parameter, \
54                 surround it with braces",
55            suggestions,
56            Applicability::MaybeIncorrect,
57        );
58    };
59
60    // Specific suggestion set for diagnostics
61    match (arg, &param.kind) {
62        (
63            GenericArg::Type(hir::Ty {
64                kind: hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)),
65                ..
66            }),
67            GenericParamDefKind::Const { .. },
68        ) => match path.res {
69            Res::Err => {
70                add_braces_suggestion(arg, &mut err);
71                return err
72                    .with_primary_message("unresolved item provided when a constant was expected")
73                    .emit();
74            }
75            Res::Def(DefKind::TyParam, src_def_id) => {
76                if let Some(param_local_id) = param.def_id.as_local() {
77                    let param_name = tcx.hir_ty_param_name(param_local_id);
78                    let param_type =
79                        tcx.type_of(param.def_id).instantiate_identity().skip_norm_wip();
80                    if param_type.is_suggestable(tcx, false) {
81                        err.span_suggestion_verbose(
82                            tcx.def_span(src_def_id),
83                            "consider changing this type parameter to a const parameter",
84                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("const {0}: {1}", param_name,
                param_type))
    })format!("const {param_name}: {param_type}"),
85                            Applicability::MaybeIncorrect,
86                        );
87                    };
88                }
89            }
90            _ => add_braces_suggestion(arg, &mut err),
91        },
92        (
93            GenericArg::Type(hir::Ty { kind: hir::TyKind::Path(_), .. }),
94            GenericParamDefKind::Const { .. },
95        ) => add_braces_suggestion(arg, &mut err),
96        (
97            GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
98            GenericParamDefKind::Const { .. },
99        ) if tcx.type_of(param.def_id).skip_binder() == tcx.types.usize => {
100            let snippet = sess.source_map().span_to_snippet(tcx.hir_span(len.hir_id));
101            if let Ok(snippet) = snippet {
102                err.span_suggestion(
103                    arg.span(),
104                    "array type provided where a `usize` was expected, try",
105                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{{ {0} }}", snippet))
    })format!("{{ {snippet} }}"),
106                    Applicability::MaybeIncorrect,
107                );
108            }
109        }
110        (GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => {
111            if let hir::ConstArgKind::Path(qpath) = cnst.kind
112                && let rustc_hir::QPath::Resolved(_, path) = qpath
113                && let Res::Def(DefKind::Fn { .. }, id) = path.res
114            {
115                err.help(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` is a function item, not a type",
                tcx.item_name(id)))
    })format!("`{}` is a function item, not a type", tcx.item_name(id)));
116                err.help("function item types cannot be named directly");
117            } else if let hir::ConstArgKind::Anon(anon) = cnst.kind
118                && let body = tcx.hir_body(anon.body)
119                && let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) =
120                    body.value.kind
121                && let Res::Def(DefKind::Fn { .. }, id) = path.res
122            {
123                // FIXME(mgca): this branch is dead once new const path lowering
124                // (for single-segment paths) is no longer gated
125                err.help(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` is a function item, not a type",
                tcx.item_name(id)))
    })format!("`{}` is a function item, not a type", tcx.item_name(id)));
126                err.help("function item types cannot be named directly");
127            }
128        }
129        _ => {}
130    }
131
132    let kind_ord = param.kind.to_ord();
133    let arg_ord = arg.to_ord();
134
135    // This note is only true when generic parameters are strictly ordered by their kind.
136    if possible_ordering_error && kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal {
137        let (first, last) = if kind_ord < arg_ord {
138            (param.kind.descr(), arg.descr())
139        } else {
140            (arg.descr(), param.kind.descr())
141        };
142        err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} arguments must be provided before {1} arguments",
                first, last))
    })format!("{first} arguments must be provided before {last} arguments"));
143        if let Some(help) = help {
144            err.help(help);
145        }
146    }
147
148    err.emit()
149}
150
151/// Lower generic arguments from the HIR to the [`rustc_middle::ty`] representation.
152///
153/// This is a rather complex function. Let us try to explain the role
154/// of each of its parameters:
155///
156/// To start, we are given the `def_id` of the thing whose generic parameters we
157/// are creating, and a partial set of arguments `parent_args`. In general,
158/// the generic arguments for an item begin with arguments for all the "parents"
159/// of that item -- e.g., for a method it might include the parameters from the impl.
160///
161/// Therefore, the method begins by walking down these parents,
162/// starting with the outermost parent and proceed inwards until
163/// it reaches `def_id`. For each parent `P`, it will check `parent_args`
164/// first to see if the parent's arguments are listed in there. If so,
165/// we can append those and move on. Otherwise, it uses the provided
166/// [`GenericArgsLowerer`] `ctx` which has the following methods:
167///
168/// - `args_for_def_id`: given the `DefId` `P`, supplies back the
169///   generic arguments that were given to that parent from within
170///   the path; so e.g., if you have `<T as Foo>::Bar`, the `DefId`
171///   might refer to the trait `Foo`, and the arguments might be
172///   `[T]`. The boolean value indicates whether to infer values
173///   for arguments whose values were not explicitly provided.
174/// - `provided_kind`: given the generic parameter and the value
175///   from `args_for_def_id`, creating a `GenericArg`.
176/// - `inferred_kind`: if no parameter was provided, and inference
177///   is enabled, then creates a suitable inference variable.
178pub fn lower_generic_args<'tcx: 'a, 'a>(
179    cx: &dyn HirTyLowerer<'tcx>,
180    def_id: DefId,
181    parent_args: &[ty::GenericArg<'tcx>],
182    has_self: bool,
183    self_ty: Option<Ty<'tcx>>,
184    arg_count: &GenericArgCountResult,
185    ctx: &mut impl GenericArgsLowerer<'a, 'tcx>,
186) -> GenericArgsRef<'tcx> {
187    let tcx = cx.tcx();
188    // Collect the segments of the path; we need to instantiate arguments
189    // for parameters throughout the entire path (wherever there are
190    // generic parameters).
191    let mut parent_defs = tcx.generics_of(def_id);
192    let count = parent_defs.count();
193    let mut stack = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(def_id, parent_defs)]))vec![(def_id, parent_defs)];
194    while let Some(def_id) = parent_defs.parent {
195        parent_defs = tcx.generics_of(def_id);
196        stack.push((def_id, parent_defs));
197    }
198
199    // We manually build up the generic arguments, rather than using convenience
200    // methods in `rustc_middle/src/ty/generic_args.rs`, so that we can iterate over the arguments and
201    // parameters in lock-step linearly, instead of trying to match each pair.
202    let mut args: SmallVec<[ty::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
203    // Iterate over each segment of the path.
204    while let Some((def_id, defs)) = stack.pop() {
205        let mut params = defs.own_params.iter().peekable();
206
207        // If we have already computed the generic arguments for parents,
208        // we can use those directly.
209        while let Some(&param) = params.peek() {
210            if let Some(&kind) = parent_args.get(param.index as usize) {
211                args.push(kind);
212                params.next();
213            } else {
214                break;
215            }
216        }
217
218        // `Self` is handled first, unless it's been handled in `parent_args`.
219        if has_self {
220            if let Some(&param) = params.peek() {
221                if param.index == 0 {
222                    if let GenericParamDefKind::Type { .. } = param.kind {
223                        {
    match (&&args[..], &&[]) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    }
};assert_eq!(&args[..], &[]);
224                        args.push(
225                            self_ty
226                                .map(|ty| ty.into())
227                                .unwrap_or_else(|| ctx.inferred_kind(&args, param, true)),
228                        );
229                        params.next();
230                    }
231                }
232            }
233        }
234
235        // Check whether this segment takes generic arguments and the user has provided any.
236        let (generic_args, infer_args) = ctx.args_for_def_id(def_id);
237
238        let mut args_iter =
239            generic_args.iter().flat_map(|generic_args| generic_args.args.iter()).peekable();
240
241        // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
242        // If we later encounter a lifetime, we know that the arguments were provided in the
243        // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be
244        // inferred, so we can use it for diagnostics later.
245        let mut force_infer_lt = None;
246
247        loop {
248            // We're going to iterate through the generic arguments that the user
249            // provided, matching them with the generic parameters we expect.
250            // Mismatches can occur as a result of elided lifetimes, or for malformed
251            // input. We try to handle both sensibly.
252            match (args_iter.peek(), params.peek()) {
253                (Some(&arg), Some(&param)) => {
254                    match (arg, &param.kind, arg_count.explicit_late_bound) {
255                        (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
256                        | (
257                            GenericArg::Type(_) | GenericArg::Infer(_),
258                            GenericParamDefKind::Type { .. },
259                            _,
260                        )
261                        | (
262                            GenericArg::Const(_) | GenericArg::Infer(_),
263                            GenericParamDefKind::Const { .. },
264                            _,
265                        ) => {
266                            // We lower to an infer even when the feature gate is not enabled
267                            // as it is useful for diagnostics to be able to see a `ConstKind::Infer`
268                            args.push(ctx.provided_kind(&args, param, arg));
269                            args_iter.next();
270                            params.next();
271                        }
272                        (
273                            GenericArg::Infer(_) | GenericArg::Type(_) | GenericArg::Const(_),
274                            GenericParamDefKind::Lifetime,
275                            _,
276                        ) => {
277                            // We expected a lifetime argument, but got a type or const
278                            // argument. That means we're inferring the lifetimes.
279                            args.push(ctx.inferred_kind(&args, param, infer_args));
280                            force_infer_lt = Some((arg, param));
281                            params.next();
282                        }
283                        (GenericArg::Lifetime(_), _, ExplicitLateBound::Yes) => {
284                            // We've come across a lifetime when we expected something else in
285                            // the presence of explicit late bounds. This is most likely
286                            // due to the presence of the explicit bound so we're just going to
287                            // ignore it.
288                            args_iter.next();
289                        }
290                        (_, _, _) => {
291                            // We expected one kind of parameter, but the user provided
292                            // another. This is an error. However, if we already know that
293                            // the arguments don't match up with the parameters, we won't issue
294                            // an additional error, as the user already knows what's wrong.
295                            if arg_count.correct.is_ok() {
296                                // We're going to iterate over the parameters to sort them out, and
297                                // show that order to the user as a possible order for the parameters
298                                let mut param_types_present = defs
299                                    .own_params
300                                    .iter()
301                                    .map(|param| (param.kind.to_ord(), param.clone()))
302                                    .collect::<Vec<(ParamKindOrd, GenericParamDef)>>();
303                                param_types_present.sort_by_key(|(ord, _)| *ord);
304                                let (mut param_types_present, ordered_params): (
305                                    Vec<ParamKindOrd>,
306                                    Vec<GenericParamDef>,
307                                ) = param_types_present.into_iter().unzip();
308                                param_types_present.dedup();
309
310                                generic_arg_mismatch_err(
311                                    cx,
312                                    arg,
313                                    param,
314                                    !args_iter.clone().is_sorted_by_key(|arg| arg.to_ord()),
315                                    Some(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("reorder the arguments: {0}: `<{1}>`",
                param_types_present.into_iter().map(|ord|
                                ::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("{0}s", ord))
                                    })).collect::<Vec<String>>().join(", then "),
                ordered_params.into_iter().filter_map(|param|
                                {
                                    if param.name == kw::SelfUpper {
                                        None
                                    } else { Some(param.name.to_string()) }
                                }).collect::<Vec<String>>().join(", ")))
    })format!(
316                                        "reorder the arguments: {}: `<{}>`",
317                                        param_types_present
318                                            .into_iter()
319                                            .map(|ord| format!("{ord}s"))
320                                            .collect::<Vec<String>>()
321                                            .join(", then "),
322                                        ordered_params
323                                            .into_iter()
324                                            .filter_map(|param| {
325                                                if param.name == kw::SelfUpper {
326                                                    None
327                                                } else {
328                                                    Some(param.name.to_string())
329                                                }
330                                            })
331                                            .collect::<Vec<String>>()
332                                            .join(", ")
333                                    )),
334                                );
335                            }
336
337                            // We've reported the error, but we want to make sure that this
338                            // problem doesn't bubble down and create additional, irrelevant
339                            // errors. In this case, we're simply going to ignore the argument
340                            // and any following arguments. The rest of the parameters will be
341                            // inferred.
342                            while args_iter.next().is_some() {}
343                        }
344                    }
345                }
346
347                (Some(&arg), None) => {
348                    // We should never be able to reach this point with well-formed input.
349                    // There are three situations in which we can encounter this issue.
350                    //
351                    //  1. The number of arguments is incorrect. In this case, an error
352                    //     will already have been emitted, and we can ignore it.
353                    //  2. There are late-bound lifetime parameters present, yet the
354                    //     lifetime arguments have also been explicitly specified by the
355                    //     user.
356                    //  3. We've inferred some lifetimes, which have been provided later (i.e.
357                    //     after a type or const). We want to throw an error in this case.
358
359                    if arg_count.correct.is_ok()
360                        && arg_count.explicit_late_bound == ExplicitLateBound::No
361                    {
362                        let kind = arg.descr();
363                        {
    match (&kind, &"lifetime") {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    }
};assert_eq!(kind, "lifetime");
364                        let (provided_arg, param) =
365                            force_infer_lt.expect("lifetimes ought to have been inferred");
366                        generic_arg_mismatch_err(cx, provided_arg, param, false, None);
367                    }
368
369                    break;
370                }
371
372                (None, Some(&param)) => {
373                    // If there are fewer arguments than parameters, it means
374                    // we're inferring the remaining arguments.
375                    args.push(ctx.inferred_kind(&args, param, infer_args));
376                    params.next();
377                }
378
379                (None, None) => break,
380            }
381        }
382    }
383
384    tcx.mk_args(&args)
385}
386
387/// Checks that the correct number of generic arguments have been provided.
388/// Used specifically for function calls.
389pub fn check_generic_arg_count_for_value_path(
390    cx: &dyn HirTyLowerer<'_>,
391    def_id: DefId,
392    generics: &ty::Generics,
393    seg: &hir::PathSegment<'_>,
394    is_method_call: IsMethodCall,
395) -> GenericArgCountResult {
396    let gen_pos = GenericArgPosition::Value(is_method_call);
397    check_generic_arg_count(cx, def_id, seg, generics, gen_pos, generics.has_own_self())
398}
399
400/// Checks that the correct number of generic arguments have been provided.
401/// This is used both for datatypes and function calls.
402#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("check_generic_arg_count",
                                    "rustc_hir_analysis::hir_ty_lowering::generics",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs"),
                                    ::tracing_core::__macro_support::Option::Some(402u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::generics"),
                                    ::tracing_core::field::FieldSet::new(&["def_id", "seg",
                                                    "gen_params", "has_self"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&seg)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&gen_params)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&has_self as
                                                            &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: GenericArgCountResult = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let gen_args = seg.args();
            let default_counts = gen_params.own_defaults();
            let param_counts = gen_params.own_counts();
            let synth_type_param_count =
                gen_params.own_params.iter().filter(|param|
                            #[allow(non_exhaustive_omitted_patterns)] match param.kind {
                                ty::GenericParamDefKind::Type { synthetic: true, .. } =>
                                    true,
                                _ => false,
                            }).count();
            let named_type_param_count =
                param_counts.types - has_self as usize -
                    synth_type_param_count;
            let named_const_param_count = param_counts.consts;
            let infer_lifetimes =
                (gen_pos != GenericArgPosition::Type || seg.infer_args) &&
                    !gen_args.has_lifetime_args();
            if gen_pos != GenericArgPosition::Type &&
                    let Some(c) = gen_args.constraints.first() {
                prohibit_assoc_item_constraint(cx, c, None);
            }
            let tcx = cx.tcx();
            let explicit_late_bound =
                match tcx.hir_is_delegation_child_segment(seg) {
                    true => ExplicitLateBound::No,
                    false =>
                        prohibit_explicit_late_bound_lifetimes(cx, gen_params,
                            gen_args, gen_pos),
                };
            let mut invalid_args = ::alloc::vec::Vec::new();
            let mut check_lifetime_args =
                |min_expected_args: usize, max_expected_args: usize,
                    provided_args: usize, late_bounds_ignore: bool|
                    {
                        if (min_expected_args..=max_expected_args).contains(&provided_args)
                            {
                            return Ok(());
                        }
                        if late_bounds_ignore { return Ok(()); }
                        invalid_args.extend(min_expected_args..provided_args);
                        let gen_args_info =
                            if provided_args > min_expected_args {
                                let num_redundant_args = provided_args - min_expected_args;
                                GenericArgsInfo::ExcessLifetimes { num_redundant_args }
                            } else {
                                let num_missing_args = min_expected_args - provided_args;
                                GenericArgsInfo::MissingLifetimes { num_missing_args }
                            };
                        let reported =
                            cx.dcx().emit_err(WrongNumberOfGenericArgs::new(tcx,
                                    gen_args_info, seg, gen_params, has_self as usize, gen_args,
                                    def_id));
                        Err(reported)
                    };
            let min_expected_lifetime_args =
                if infer_lifetimes { 0 } else { param_counts.lifetimes };
            let max_expected_lifetime_args = param_counts.lifetimes;
            let num_provided_lifetime_args = gen_args.num_lifetime_args();
            let lifetimes_correct =
                check_lifetime_args(min_expected_lifetime_args,
                    max_expected_lifetime_args, num_provided_lifetime_args,
                    explicit_late_bound == ExplicitLateBound::Yes);
            let mut check_types_and_consts =
                |expected_min, expected_max, expected_max_with_synth,
                    provided, params_offset, args_offset|
                    {
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs:496",
                                                "rustc_hir_analysis::hir_ty_lowering::generics",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs"),
                                                ::tracing_core::__macro_support::Option::Some(496u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::generics"),
                                                ::tracing_core::field::FieldSet::new(&["message",
                                                                "expected_min", "expected_max", "provided", "params_offset",
                                                                "args_offset"],
                                                    ::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};
                                        let mut iter = __CALLSITE.metadata().fields().iter();
                                        __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&format_args!("check_types_and_consts")
                                                                    as &dyn Value)),
                                                        (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&expected_min)
                                                                    as &dyn Value)),
                                                        (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&expected_max)
                                                                    as &dyn Value)),
                                                        (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&provided)
                                                                    as &dyn Value)),
                                                        (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&params_offset)
                                                                    as &dyn Value)),
                                                        (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&args_offset)
                                                                    as &dyn Value))])
                                    });
                            } else { ; }
                        };
                        if (expected_min..=expected_max).contains(&provided) {
                            return Ok(());
                        }
                        let num_default_params = expected_max - expected_min;
                        let mut all_params_are_binded = false;
                        let gen_args_info =
                            if provided > expected_max {
                                invalid_args.extend((expected_max..provided).map(|i|
                                            i + args_offset));
                                let num_redundant_args = provided - expected_max;
                                let synth_provided = provided <= expected_max_with_synth;
                                GenericArgsInfo::ExcessTypesOrConsts {
                                    num_redundant_args,
                                    num_default_params,
                                    args_offset,
                                    synth_provided,
                                }
                            } else {
                                let parent_is_impl_block =
                                    cx.tcx().hir_parent_owner_iter(seg.hir_id).next().is_some_and(|(_,
                                                owner_node)| owner_node.is_impl_block());
                                if parent_is_impl_block {
                                    let constraint_names: Vec<_> =
                                        gen_args.constraints.iter().map(|b| b.ident.name).collect();
                                    let param_names: Vec<_> =
                                        gen_params.own_params.iter().filter(|param|
                                                        !has_self ||
                                                            param.index != 0).map(|param| param.name).collect();
                                    if constraint_names == param_names {
                                        let has_assoc_ty_with_same_name =
                                            if let DefKind::Trait = tcx.def_kind(def_id) {
                                                gen_args.constraints.iter().any(|constraint|
                                                        {
                                                            traits::supertrait_def_ids(tcx,
                                                                    def_id).any(|trait_did|
                                                                    {
                                                                        cx.probe_trait_that_defines_assoc_item(trait_did,
                                                                            ty::AssocTag::Type, constraint.ident)
                                                                    })
                                                        })
                                            } else { false };
                                        all_params_are_binded = !has_assoc_ty_with_same_name;
                                    };
                                }
                                let num_missing_args = expected_max - provided;
                                GenericArgsInfo::MissingTypesOrConsts {
                                    num_missing_args,
                                    num_default_params,
                                    args_offset,
                                }
                            };
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs:576",
                                                "rustc_hir_analysis::hir_ty_lowering::generics",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs"),
                                                ::tracing_core::__macro_support::Option::Some(576u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::generics"),
                                                ::tracing_core::field::FieldSet::new(&["gen_args_info"],
                                                    ::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};
                                        let mut iter = __CALLSITE.metadata().fields().iter();
                                        __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&gen_args_info)
                                                                    as &dyn Value))])
                                    });
                            } else { ; }
                        };
                        let reported =
                            gen_args.has_err().unwrap_or_else(||
                                    {
                                        cx.dcx().create_err(WrongNumberOfGenericArgs::new(tcx,
                                                    gen_args_info, seg, gen_params, params_offset, gen_args,
                                                    def_id)).emit_unless_delay(all_params_are_binded)
                                    });
                        Err(reported)
                    };
            let args_correct =
                {
                    let expected_min =
                        if seg.infer_args {
                            0
                        } else {
                            param_counts.consts + named_type_param_count -
                                    default_counts.types - default_counts.consts
                        };
                    {
                        use ::tracing::__macro_support::Callsite as _;
                        static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                            {
                                static META: ::tracing::Metadata<'static> =
                                    {
                                        ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs:603",
                                            "rustc_hir_analysis::hir_ty_lowering::generics",
                                            ::tracing::Level::DEBUG,
                                            ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs"),
                                            ::tracing_core::__macro_support::Option::Some(603u32),
                                            ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::generics"),
                                            ::tracing_core::field::FieldSet::new(&["expected_min"],
                                                ::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};
                                    let mut iter = __CALLSITE.metadata().fields().iter();
                                    __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                        ::tracing::__macro_support::Option::Some(&debug(&expected_min)
                                                                as &dyn Value))])
                                });
                        } else { ; }
                    };
                    {
                        use ::tracing::__macro_support::Callsite as _;
                        static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                            {
                                static META: ::tracing::Metadata<'static> =
                                    {
                                        ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs:604",
                                            "rustc_hir_analysis::hir_ty_lowering::generics",
                                            ::tracing::Level::DEBUG,
                                            ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs"),
                                            ::tracing_core::__macro_support::Option::Some(604u32),
                                            ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::generics"),
                                            ::tracing_core::field::FieldSet::new(&["arg_counts.lifetimes"],
                                                ::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};
                                    let mut iter = __CALLSITE.metadata().fields().iter();
                                    __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                        ::tracing::__macro_support::Option::Some(&debug(&gen_args.num_lifetime_args())
                                                                as &dyn Value))])
                                });
                        } else { ; }
                    };
                    let provided = gen_args.num_generic_params();
                    check_types_and_consts(expected_min,
                        named_const_param_count + named_type_param_count,
                        named_const_param_count + named_type_param_count +
                            synth_type_param_count, provided,
                        param_counts.lifetimes + has_self as usize,
                        gen_args.num_lifetime_args())
                };
            GenericArgCountResult {
                explicit_late_bound,
                correct: lifetimes_correct.and(args_correct).map_err(|reported|
                        GenericArgCountMismatch { reported, invalid_args }),
            }
        }
    }
}#[instrument(skip(cx, gen_pos), level = "debug")]
403pub(crate) fn check_generic_arg_count(
404    cx: &dyn HirTyLowerer<'_>,
405    def_id: DefId,
406    seg: &hir::PathSegment<'_>,
407    gen_params: &ty::Generics,
408    gen_pos: GenericArgPosition,
409    has_self: bool,
410) -> GenericArgCountResult {
411    let gen_args = seg.args();
412    let default_counts = gen_params.own_defaults();
413    let param_counts = gen_params.own_counts();
414
415    // Subtracting from param count to ensure type params synthesized from `impl Trait`
416    // cannot be explicitly specified.
417    let synth_type_param_count = gen_params
418        .own_params
419        .iter()
420        .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. }))
421        .count();
422    let named_type_param_count = param_counts.types - has_self as usize - synth_type_param_count;
423    let named_const_param_count = param_counts.consts;
424    let infer_lifetimes =
425        (gen_pos != GenericArgPosition::Type || seg.infer_args) && !gen_args.has_lifetime_args();
426
427    if gen_pos != GenericArgPosition::Type
428        && let Some(c) = gen_args.constraints.first()
429    {
430        prohibit_assoc_item_constraint(cx, c, None);
431    }
432
433    let tcx = cx.tcx();
434
435    // Suppress this warning for delegations as it is compiler generated and lifetimes are
436    // propagated while late-bound lifetimes may be present.
437    let explicit_late_bound = match tcx.hir_is_delegation_child_segment(seg) {
438        true => ExplicitLateBound::No,
439        false => prohibit_explicit_late_bound_lifetimes(cx, gen_params, gen_args, gen_pos),
440    };
441
442    let mut invalid_args = vec![];
443
444    let mut check_lifetime_args = |min_expected_args: usize,
445                                   max_expected_args: usize,
446                                   provided_args: usize,
447                                   late_bounds_ignore: bool| {
448        if (min_expected_args..=max_expected_args).contains(&provided_args) {
449            return Ok(());
450        }
451
452        if late_bounds_ignore {
453            return Ok(());
454        }
455
456        invalid_args.extend(min_expected_args..provided_args);
457
458        let gen_args_info = if provided_args > min_expected_args {
459            let num_redundant_args = provided_args - min_expected_args;
460            GenericArgsInfo::ExcessLifetimes { num_redundant_args }
461        } else {
462            let num_missing_args = min_expected_args - provided_args;
463            GenericArgsInfo::MissingLifetimes { num_missing_args }
464        };
465
466        let reported = cx.dcx().emit_err(WrongNumberOfGenericArgs::new(
467            tcx,
468            gen_args_info,
469            seg,
470            gen_params,
471            has_self as usize,
472            gen_args,
473            def_id,
474        ));
475
476        Err(reported)
477    };
478
479    let min_expected_lifetime_args = if infer_lifetimes { 0 } else { param_counts.lifetimes };
480    let max_expected_lifetime_args = param_counts.lifetimes;
481    let num_provided_lifetime_args = gen_args.num_lifetime_args();
482
483    let lifetimes_correct = check_lifetime_args(
484        min_expected_lifetime_args,
485        max_expected_lifetime_args,
486        num_provided_lifetime_args,
487        explicit_late_bound == ExplicitLateBound::Yes,
488    );
489
490    let mut check_types_and_consts = |expected_min,
491                                      expected_max,
492                                      expected_max_with_synth,
493                                      provided,
494                                      params_offset,
495                                      args_offset| {
496        debug!(
497            ?expected_min,
498            ?expected_max,
499            ?provided,
500            ?params_offset,
501            ?args_offset,
502            "check_types_and_consts"
503        );
504        if (expected_min..=expected_max).contains(&provided) {
505            return Ok(());
506        }
507
508        let num_default_params = expected_max - expected_min;
509
510        let mut all_params_are_binded = false;
511        let gen_args_info = if provided > expected_max {
512            invalid_args.extend((expected_max..provided).map(|i| i + args_offset));
513            let num_redundant_args = provided - expected_max;
514
515            // Provide extra note if synthetic arguments like `impl Trait` are specified.
516            let synth_provided = provided <= expected_max_with_synth;
517
518            GenericArgsInfo::ExcessTypesOrConsts {
519                num_redundant_args,
520                num_default_params,
521                args_offset,
522                synth_provided,
523            }
524        } else {
525            // Check if associated type bounds are incorrectly written in impl block header like:
526            // ```
527            // trait Foo<T> {}
528            // impl Foo<T: Default> for u8 {}
529            // ```
530            let parent_is_impl_block = cx
531                .tcx()
532                .hir_parent_owner_iter(seg.hir_id)
533                .next()
534                .is_some_and(|(_, owner_node)| owner_node.is_impl_block());
535            if parent_is_impl_block {
536                let constraint_names: Vec<_> =
537                    gen_args.constraints.iter().map(|b| b.ident.name).collect();
538                let param_names: Vec<_> = gen_params
539                    .own_params
540                    .iter()
541                    .filter(|param| !has_self || param.index != 0) // Assumes `Self` will always be the first parameter
542                    .map(|param| param.name)
543                    .collect();
544                if constraint_names == param_names {
545                    let has_assoc_ty_with_same_name = if let DefKind::Trait = tcx.def_kind(def_id) {
546                        gen_args.constraints.iter().any(|constraint| {
547                            traits::supertrait_def_ids(tcx, def_id).any(|trait_did| {
548                                cx.probe_trait_that_defines_assoc_item(
549                                    trait_did,
550                                    ty::AssocTag::Type,
551                                    constraint.ident,
552                                )
553                            })
554                        })
555                    } else {
556                        false
557                    };
558                    // We set this to true and delay emitting `WrongNumberOfGenericArgs`
559                    // to provide a succinct error for cases like issue #113073,
560                    // but only if when we don't have any assoc type with the same name with a
561                    // generic arg. Otherwise it will cause an ICE due to a delayed error because we
562                    // don't have any error other than `WrongNumberOfGenericArgs`.
563                    all_params_are_binded = !has_assoc_ty_with_same_name;
564                };
565            }
566
567            let num_missing_args = expected_max - provided;
568
569            GenericArgsInfo::MissingTypesOrConsts {
570                num_missing_args,
571                num_default_params,
572                args_offset,
573            }
574        };
575
576        debug!(?gen_args_info);
577
578        let reported = gen_args.has_err().unwrap_or_else(|| {
579            cx.dcx()
580                .create_err(WrongNumberOfGenericArgs::new(
581                    tcx,
582                    gen_args_info,
583                    seg,
584                    gen_params,
585                    params_offset,
586                    gen_args,
587                    def_id,
588                ))
589                .emit_unless_delay(all_params_are_binded)
590        });
591
592        Err(reported)
593    };
594
595    let args_correct = {
596        let expected_min = if seg.infer_args {
597            0
598        } else {
599            param_counts.consts + named_type_param_count
600                - default_counts.types
601                - default_counts.consts
602        };
603        debug!(?expected_min);
604        debug!(arg_counts.lifetimes=?gen_args.num_lifetime_args());
605
606        let provided = gen_args.num_generic_params();
607
608        check_types_and_consts(
609            expected_min,
610            named_const_param_count + named_type_param_count,
611            named_const_param_count + named_type_param_count + synth_type_param_count,
612            provided,
613            param_counts.lifetimes + has_self as usize,
614            gen_args.num_lifetime_args(),
615        )
616    };
617
618    GenericArgCountResult {
619        explicit_late_bound,
620        correct: lifetimes_correct
621            .and(args_correct)
622            .map_err(|reported| GenericArgCountMismatch { reported, invalid_args }),
623    }
624}
625
626/// Prohibits explicit lifetime arguments if late-bound lifetime parameters
627/// are present. This is used both for datatypes and function calls.
628pub(crate) fn prohibit_explicit_late_bound_lifetimes(
629    cx: &dyn HirTyLowerer<'_>,
630    def: &ty::Generics,
631    args: &hir::GenericArgs<'_>,
632    position: GenericArgPosition,
633) -> ExplicitLateBound {
634    struct LifetimeArgsIssue {
635        msg: &'static str,
636    }
637
638    impl<'a> Diagnostic<'a, ()> for LifetimeArgsIssue {
639        fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
640            let Self { msg } = self;
641            Diag::new(dcx, level, msg)
642        }
643    }
644
645    let param_counts = def.own_counts();
646
647    if let Some(span_late) = def.has_late_bound_regions
648        && args.has_lifetime_args()
649    {
650        let msg = "cannot specify lifetime arguments explicitly \
651                       if late bound lifetime parameters are present";
652        let note = "the late bound lifetime parameter is introduced here";
653        let span = args.args[0].span();
654
655        if position == GenericArgPosition::Value(IsMethodCall::No)
656            && args.num_lifetime_args() != param_counts.lifetimes
657        {
658            {
    cx.dcx().struct_span_err(span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("{0}", msg))
                })).with_code(E0794)
}struct_span_code_err!(cx.dcx(), span, E0794, "{}", msg)
659                .with_span_note(span_late, note)
660                .emit();
661        } else {
662            let mut multispan = MultiSpan::from_span(span);
663            multispan.push_span_label(span_late, note);
664            cx.tcx().emit_node_span_lint(
665                LATE_BOUND_LIFETIME_ARGUMENTS,
666                args.args[0].hir_id(),
667                multispan,
668                LifetimeArgsIssue { msg },
669            );
670        }
671
672        ExplicitLateBound::Yes
673    } else {
674        ExplicitLateBound::No
675    }
676}