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::errors::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 = tcx.type_of(param.def_id).instantiate_identity();
79                    if param_type.is_suggestable(tcx, false) {
80                        err.span_suggestion_verbose(
81                            tcx.def_span(src_def_id),
82                            "consider changing this type parameter to a const parameter",
83                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("const {0}: {1}", param_name,
                param_type))
    })format!("const {param_name}: {param_type}"),
84                            Applicability::MaybeIncorrect,
85                        );
86                    };
87                }
88            }
89            _ => add_braces_suggestion(arg, &mut err),
90        },
91        (
92            GenericArg::Type(hir::Ty { kind: hir::TyKind::Path(_), .. }),
93            GenericParamDefKind::Const { .. },
94        ) => add_braces_suggestion(arg, &mut err),
95        (
96            GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
97            GenericParamDefKind::Const { .. },
98        ) if tcx.type_of(param.def_id).skip_binder() == tcx.types.usize => {
99            let snippet = sess.source_map().span_to_snippet(tcx.hir_span(len.hir_id));
100            if let Ok(snippet) = snippet {
101                err.span_suggestion(
102                    arg.span(),
103                    "array type provided where a `usize` was expected, try",
104                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{{ {0} }}", snippet))
    })format!("{{ {snippet} }}"),
105                    Applicability::MaybeIncorrect,
106                );
107            }
108        }
109        (GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => {
110            if let hir::ConstArgKind::Path(qpath) = cnst.kind
111                && let rustc_hir::QPath::Resolved(_, path) = qpath
112                && let Res::Def(DefKind::Fn { .. }, id) = path.res
113            {
114                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)));
115                err.help("function item types cannot be named directly");
116            } else if let hir::ConstArgKind::Anon(anon) = cnst.kind
117                && let body = tcx.hir_body(anon.body)
118                && let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) =
119                    body.value.kind
120                && let Res::Def(DefKind::Fn { .. }, id) = path.res
121            {
122                // FIXME(mgca): this branch is dead once new const path lowering
123                // (for single-segment paths) is no longer gated
124                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)));
125                err.help("function item types cannot be named directly");
126            }
127        }
128        _ => {}
129    }
130
131    let kind_ord = param.kind.to_ord();
132    let arg_ord = arg.to_ord();
133
134    // This note is only true when generic parameters are strictly ordered by their kind.
135    if possible_ordering_error && kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal {
136        let (first, last) = if kind_ord < arg_ord {
137            (param.kind.descr(), arg.descr())
138        } else {
139            (arg.descr(), param.kind.descr())
140        };
141        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"));
142        if let Some(help) = help {
143            err.help(help);
144        }
145    }
146
147    err.emit()
148}
149
150/// Lower generic arguments from the HIR to the [`rustc_middle::ty`] representation.
151///
152/// This is a rather complex function. Let us try to explain the role
153/// of each of its parameters:
154///
155/// To start, we are given the `def_id` of the thing whose generic parameters we
156/// are creating, and a partial set of arguments `parent_args`. In general,
157/// the generic arguments for an item begin with arguments for all the "parents"
158/// of that item -- e.g., for a method it might include the parameters from the impl.
159///
160/// Therefore, the method begins by walking down these parents,
161/// starting with the outermost parent and proceed inwards until
162/// it reaches `def_id`. For each parent `P`, it will check `parent_args`
163/// first to see if the parent's arguments are listed in there. If so,
164/// we can append those and move on. Otherwise, it uses the provided
165/// [`GenericArgsLowerer`] `ctx` which has the following methods:
166///
167/// - `args_for_def_id`: given the `DefId` `P`, supplies back the
168///   generic arguments that were given to that parent from within
169///   the path; so e.g., if you have `<T as Foo>::Bar`, the `DefId`
170///   might refer to the trait `Foo`, and the arguments might be
171///   `[T]`. The boolean value indicates whether to infer values
172///   for arguments whose values were not explicitly provided.
173/// - `provided_kind`: given the generic parameter and the value
174///   from `args_for_def_id`, creating a `GenericArg`.
175/// - `inferred_kind`: if no parameter was provided, and inference
176///   is enabled, then creates a suitable inference variable.
177pub fn lower_generic_args<'tcx: 'a, 'a>(
178    cx: &dyn HirTyLowerer<'tcx>,
179    def_id: DefId,
180    parent_args: &[ty::GenericArg<'tcx>],
181    has_self: bool,
182    self_ty: Option<Ty<'tcx>>,
183    arg_count: &GenericArgCountResult,
184    ctx: &mut impl GenericArgsLowerer<'a, 'tcx>,
185) -> GenericArgsRef<'tcx> {
186    let tcx = cx.tcx();
187    // Collect the segments of the path; we need to instantiate arguments
188    // for parameters throughout the entire path (wherever there are
189    // generic parameters).
190    let mut parent_defs = tcx.generics_of(def_id);
191    let count = parent_defs.count();
192    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)];
193    while let Some(def_id) = parent_defs.parent {
194        parent_defs = tcx.generics_of(def_id);
195        stack.push((def_id, parent_defs));
196    }
197
198    // We manually build up the generic arguments, rather than using convenience
199    // methods in `rustc_middle/src/ty/generic_args.rs`, so that we can iterate over the arguments and
200    // parameters in lock-step linearly, instead of trying to match each pair.
201    let mut args: SmallVec<[ty::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
202    // Iterate over each segment of the path.
203    while let Some((def_id, defs)) = stack.pop() {
204        let mut params = defs.own_params.iter().peekable();
205
206        // If we have already computed the generic arguments for parents,
207        // we can use those directly.
208        while let Some(&param) = params.peek() {
209            if let Some(&kind) = parent_args.get(param.index as usize) {
210                args.push(kind);
211                params.next();
212            } else {
213                break;
214            }
215        }
216
217        // `Self` is handled first, unless it's been handled in `parent_args`.
218        if has_self {
219            if let Some(&param) = params.peek() {
220                if param.index == 0 {
221                    if let GenericParamDefKind::Type { .. } = param.kind {
222                        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[..], &[]);
223                        args.push(
224                            self_ty
225                                .map(|ty| ty.into())
226                                .unwrap_or_else(|| ctx.inferred_kind(&args, param, true)),
227                        );
228                        params.next();
229                    }
230                }
231            }
232        }
233
234        // Check whether this segment takes generic arguments and the user has provided any.
235        let (generic_args, infer_args) = ctx.args_for_def_id(def_id);
236
237        let mut args_iter =
238            generic_args.iter().flat_map(|generic_args| generic_args.args.iter()).peekable();
239
240        // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
241        // If we later encounter a lifetime, we know that the arguments were provided in the
242        // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be
243        // inferred, so we can use it for diagnostics later.
244        let mut force_infer_lt = None;
245
246        loop {
247            // We're going to iterate through the generic arguments that the user
248            // provided, matching them with the generic parameters we expect.
249            // Mismatches can occur as a result of elided lifetimes, or for malformed
250            // input. We try to handle both sensibly.
251            match (args_iter.peek(), params.peek()) {
252                (Some(&arg), Some(&param)) => {
253                    match (arg, &param.kind, arg_count.explicit_late_bound) {
254                        (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
255                        | (
256                            GenericArg::Type(_) | GenericArg::Infer(_),
257                            GenericParamDefKind::Type { .. },
258                            _,
259                        )
260                        | (
261                            GenericArg::Const(_) | GenericArg::Infer(_),
262                            GenericParamDefKind::Const { .. },
263                            _,
264                        ) => {
265                            // We lower to an infer even when the feature gate is not enabled
266                            // as it is useful for diagnostics to be able to see a `ConstKind::Infer`
267                            args.push(ctx.provided_kind(&args, param, arg));
268                            args_iter.next();
269                            params.next();
270                        }
271                        (
272                            GenericArg::Infer(_) | GenericArg::Type(_) | GenericArg::Const(_),
273                            GenericParamDefKind::Lifetime,
274                            _,
275                        ) => {
276                            // We expected a lifetime argument, but got a type or const
277                            // argument. That means we're inferring the lifetimes.
278                            args.push(ctx.inferred_kind(&args, param, infer_args));
279                            force_infer_lt = Some((arg, param));
280                            params.next();
281                        }
282                        (GenericArg::Lifetime(_), _, ExplicitLateBound::Yes) => {
283                            // We've come across a lifetime when we expected something else in
284                            // the presence of explicit late bounds. This is most likely
285                            // due to the presence of the explicit bound so we're just going to
286                            // ignore it.
287                            args_iter.next();
288                        }
289                        (_, _, _) => {
290                            // We expected one kind of parameter, but the user provided
291                            // another. This is an error. However, if we already know that
292                            // the arguments don't match up with the parameters, we won't issue
293                            // an additional error, as the user already knows what's wrong.
294                            if arg_count.correct.is_ok() {
295                                // We're going to iterate over the parameters to sort them out, and
296                                // show that order to the user as a possible order for the parameters
297                                let mut param_types_present = defs
298                                    .own_params
299                                    .iter()
300                                    .map(|param| (param.kind.to_ord(), param.clone()))
301                                    .collect::<Vec<(ParamKindOrd, GenericParamDef)>>();
302                                param_types_present.sort_by_key(|(ord, _)| *ord);
303                                let (mut param_types_present, ordered_params): (
304                                    Vec<ParamKindOrd>,
305                                    Vec<GenericParamDef>,
306                                ) = param_types_present.into_iter().unzip();
307                                param_types_present.dedup();
308
309                                generic_arg_mismatch_err(
310                                    cx,
311                                    arg,
312                                    param,
313                                    !args_iter.clone().is_sorted_by_key(|arg| arg.to_ord()),
314                                    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!(
315                                        "reorder the arguments: {}: `<{}>`",
316                                        param_types_present
317                                            .into_iter()
318                                            .map(|ord| format!("{ord}s"))
319                                            .collect::<Vec<String>>()
320                                            .join(", then "),
321                                        ordered_params
322                                            .into_iter()
323                                            .filter_map(|param| {
324                                                if param.name == kw::SelfUpper {
325                                                    None
326                                                } else {
327                                                    Some(param.name.to_string())
328                                                }
329                                            })
330                                            .collect::<Vec<String>>()
331                                            .join(", ")
332                                    )),
333                                );
334                            }
335
336                            // We've reported the error, but we want to make sure that this
337                            // problem doesn't bubble down and create additional, irrelevant
338                            // errors. In this case, we're simply going to ignore the argument
339                            // and any following arguments. The rest of the parameters will be
340                            // inferred.
341                            while args_iter.next().is_some() {}
342                        }
343                    }
344                }
345
346                (Some(&arg), None) => {
347                    // We should never be able to reach this point with well-formed input.
348                    // There are three situations in which we can encounter this issue.
349                    //
350                    //  1. The number of arguments is incorrect. In this case, an error
351                    //     will already have been emitted, and we can ignore it.
352                    //  2. There are late-bound lifetime parameters present, yet the
353                    //     lifetime arguments have also been explicitly specified by the
354                    //     user.
355                    //  3. We've inferred some lifetimes, which have been provided later (i.e.
356                    //     after a type or const). We want to throw an error in this case.
357
358                    if arg_count.correct.is_ok()
359                        && arg_count.explicit_late_bound == ExplicitLateBound::No
360                    {
361                        let kind = arg.descr();
362                        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");
363                        let (provided_arg, param) =
364                            force_infer_lt.expect("lifetimes ought to have been inferred");
365                        generic_arg_mismatch_err(cx, provided_arg, param, false, None);
366                    }
367
368                    break;
369                }
370
371                (None, Some(&param)) => {
372                    // If there are fewer arguments than parameters, it means
373                    // we're inferring the remaining arguments.
374                    args.push(ctx.inferred_kind(&args, param, infer_args));
375                    params.next();
376                }
377
378                (None, None) => break,
379            }
380        }
381    }
382
383    tcx.mk_args(&args)
384}
385
386/// Checks that the correct number of generic arguments have been provided.
387/// Used specifically for function calls.
388pub fn check_generic_arg_count_for_value_path(
389    cx: &dyn HirTyLowerer<'_>,
390    def_id: DefId,
391    generics: &ty::Generics,
392    seg: &hir::PathSegment<'_>,
393    is_method_call: IsMethodCall,
394) -> GenericArgCountResult {
395    let gen_pos = GenericArgPosition::Value(is_method_call);
396    check_generic_arg_count(cx, def_id, seg, generics, gen_pos, generics.has_own_self())
397}
398
399/// Checks that the correct number of generic arguments have been provided.
400/// This is used both for datatypes and function calls.
401#[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(401u32),
                                    ::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_params();
            if gen_pos != GenericArgPosition::Type &&
                    let Some(c) = gen_args.constraints.first() {
                prohibit_assoc_item_constraint(cx, c, None);
            }
            let explicit_late_bound =
                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(cx.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_params();
            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:489",
                                                "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(489u32),
                                                ::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 = cx.tcx().def_kind(def_id) {
                                                gen_args.constraints.iter().any(|constraint|
                                                        {
                                                            traits::supertrait_def_ids(cx.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:570",
                                                "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(570u32),
                                                ::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(cx.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:597",
                                            "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(597u32),
                                            ::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:598",
                                            "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(598u32),
                                            ::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_params())
                                                                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_params())
                };
            GenericArgCountResult {
                explicit_late_bound,
                correct: lifetimes_correct.and(args_correct).map_err(|reported|
                        GenericArgCountMismatch { reported, invalid_args }),
            }
        }
    }
}#[instrument(skip(cx, gen_pos), level = "debug")]
402pub(crate) fn check_generic_arg_count(
403    cx: &dyn HirTyLowerer<'_>,
404    def_id: DefId,
405    seg: &hir::PathSegment<'_>,
406    gen_params: &ty::Generics,
407    gen_pos: GenericArgPosition,
408    has_self: bool,
409) -> GenericArgCountResult {
410    let gen_args = seg.args();
411    let default_counts = gen_params.own_defaults();
412    let param_counts = gen_params.own_counts();
413
414    // Subtracting from param count to ensure type params synthesized from `impl Trait`
415    // cannot be explicitly specified.
416    let synth_type_param_count = gen_params
417        .own_params
418        .iter()
419        .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. }))
420        .count();
421    let named_type_param_count = param_counts.types - has_self as usize - synth_type_param_count;
422    let named_const_param_count = param_counts.consts;
423    let infer_lifetimes =
424        (gen_pos != GenericArgPosition::Type || seg.infer_args) && !gen_args.has_lifetime_params();
425
426    if gen_pos != GenericArgPosition::Type
427        && let Some(c) = gen_args.constraints.first()
428    {
429        prohibit_assoc_item_constraint(cx, c, None);
430    }
431
432    let explicit_late_bound =
433        prohibit_explicit_late_bound_lifetimes(cx, gen_params, gen_args, gen_pos);
434
435    let mut invalid_args = vec![];
436
437    let mut check_lifetime_args = |min_expected_args: usize,
438                                   max_expected_args: usize,
439                                   provided_args: usize,
440                                   late_bounds_ignore: bool| {
441        if (min_expected_args..=max_expected_args).contains(&provided_args) {
442            return Ok(());
443        }
444
445        if late_bounds_ignore {
446            return Ok(());
447        }
448
449        invalid_args.extend(min_expected_args..provided_args);
450
451        let gen_args_info = if provided_args > min_expected_args {
452            let num_redundant_args = provided_args - min_expected_args;
453            GenericArgsInfo::ExcessLifetimes { num_redundant_args }
454        } else {
455            let num_missing_args = min_expected_args - provided_args;
456            GenericArgsInfo::MissingLifetimes { num_missing_args }
457        };
458
459        let reported = cx.dcx().emit_err(WrongNumberOfGenericArgs::new(
460            cx.tcx(),
461            gen_args_info,
462            seg,
463            gen_params,
464            has_self as usize,
465            gen_args,
466            def_id,
467        ));
468
469        Err(reported)
470    };
471
472    let min_expected_lifetime_args = if infer_lifetimes { 0 } else { param_counts.lifetimes };
473    let max_expected_lifetime_args = param_counts.lifetimes;
474    let num_provided_lifetime_args = gen_args.num_lifetime_params();
475
476    let lifetimes_correct = check_lifetime_args(
477        min_expected_lifetime_args,
478        max_expected_lifetime_args,
479        num_provided_lifetime_args,
480        explicit_late_bound == ExplicitLateBound::Yes,
481    );
482
483    let mut check_types_and_consts = |expected_min,
484                                      expected_max,
485                                      expected_max_with_synth,
486                                      provided,
487                                      params_offset,
488                                      args_offset| {
489        debug!(
490            ?expected_min,
491            ?expected_max,
492            ?provided,
493            ?params_offset,
494            ?args_offset,
495            "check_types_and_consts"
496        );
497        if (expected_min..=expected_max).contains(&provided) {
498            return Ok(());
499        }
500
501        let num_default_params = expected_max - expected_min;
502
503        let mut all_params_are_binded = false;
504        let gen_args_info = if provided > expected_max {
505            invalid_args.extend((expected_max..provided).map(|i| i + args_offset));
506            let num_redundant_args = provided - expected_max;
507
508            // Provide extra note if synthetic arguments like `impl Trait` are specified.
509            let synth_provided = provided <= expected_max_with_synth;
510
511            GenericArgsInfo::ExcessTypesOrConsts {
512                num_redundant_args,
513                num_default_params,
514                args_offset,
515                synth_provided,
516            }
517        } else {
518            // Check if associated type bounds are incorrectly written in impl block header like:
519            // ```
520            // trait Foo<T> {}
521            // impl Foo<T: Default> for u8 {}
522            // ```
523            let parent_is_impl_block = cx
524                .tcx()
525                .hir_parent_owner_iter(seg.hir_id)
526                .next()
527                .is_some_and(|(_, owner_node)| owner_node.is_impl_block());
528            if parent_is_impl_block {
529                let constraint_names: Vec<_> =
530                    gen_args.constraints.iter().map(|b| b.ident.name).collect();
531                let param_names: Vec<_> = gen_params
532                    .own_params
533                    .iter()
534                    .filter(|param| !has_self || param.index != 0) // Assumes `Self` will always be the first parameter
535                    .map(|param| param.name)
536                    .collect();
537                if constraint_names == param_names {
538                    let has_assoc_ty_with_same_name =
539                        if let DefKind::Trait = cx.tcx().def_kind(def_id) {
540                            gen_args.constraints.iter().any(|constraint| {
541                                traits::supertrait_def_ids(cx.tcx(), def_id).any(|trait_did| {
542                                    cx.probe_trait_that_defines_assoc_item(
543                                        trait_did,
544                                        ty::AssocTag::Type,
545                                        constraint.ident,
546                                    )
547                                })
548                            })
549                        } else {
550                            false
551                        };
552                    // We set this to true and delay emitting `WrongNumberOfGenericArgs`
553                    // to provide a succinct error for cases like issue #113073,
554                    // but only if when we don't have any assoc type with the same name with a
555                    // generic arg. Otherwise it will cause an ICE due to a delayed error because we
556                    // don't have any error other than `WrongNumberOfGenericArgs`.
557                    all_params_are_binded = !has_assoc_ty_with_same_name;
558                };
559            }
560
561            let num_missing_args = expected_max - provided;
562
563            GenericArgsInfo::MissingTypesOrConsts {
564                num_missing_args,
565                num_default_params,
566                args_offset,
567            }
568        };
569
570        debug!(?gen_args_info);
571
572        let reported = gen_args.has_err().unwrap_or_else(|| {
573            cx.dcx()
574                .create_err(WrongNumberOfGenericArgs::new(
575                    cx.tcx(),
576                    gen_args_info,
577                    seg,
578                    gen_params,
579                    params_offset,
580                    gen_args,
581                    def_id,
582                ))
583                .emit_unless_delay(all_params_are_binded)
584        });
585
586        Err(reported)
587    };
588
589    let args_correct = {
590        let expected_min = if seg.infer_args {
591            0
592        } else {
593            param_counts.consts + named_type_param_count
594                - default_counts.types
595                - default_counts.consts
596        };
597        debug!(?expected_min);
598        debug!(arg_counts.lifetimes=?gen_args.num_lifetime_params());
599
600        let provided = gen_args.num_generic_params();
601
602        check_types_and_consts(
603            expected_min,
604            named_const_param_count + named_type_param_count,
605            named_const_param_count + named_type_param_count + synth_type_param_count,
606            provided,
607            param_counts.lifetimes + has_self as usize,
608            gen_args.num_lifetime_params(),
609        )
610    };
611
612    GenericArgCountResult {
613        explicit_late_bound,
614        correct: lifetimes_correct
615            .and(args_correct)
616            .map_err(|reported| GenericArgCountMismatch { reported, invalid_args }),
617    }
618}
619
620/// Prohibits explicit lifetime arguments if late-bound lifetime parameters
621/// are present. This is used both for datatypes and function calls.
622pub(crate) fn prohibit_explicit_late_bound_lifetimes(
623    cx: &dyn HirTyLowerer<'_>,
624    def: &ty::Generics,
625    args: &hir::GenericArgs<'_>,
626    position: GenericArgPosition,
627) -> ExplicitLateBound {
628    struct LifetimeArgsIssue {
629        msg: &'static str,
630    }
631
632    impl<'a> Diagnostic<'a, ()> for LifetimeArgsIssue {
633        fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
634            let Self { msg } = self;
635            Diag::new(dcx, level, msg)
636        }
637    }
638
639    let param_counts = def.own_counts();
640
641    if let Some(span_late) = def.has_late_bound_regions
642        && args.has_lifetime_params()
643    {
644        let msg = "cannot specify lifetime arguments explicitly \
645                       if late bound lifetime parameters are present";
646        let note = "the late bound lifetime parameter is introduced here";
647        let span = args.args[0].span();
648
649        if position == GenericArgPosition::Value(IsMethodCall::No)
650            && args.num_lifetime_params() != param_counts.lifetimes
651        {
652            {
    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)
653                .with_span_note(span_late, note)
654                .emit();
655        } else {
656            let mut multispan = MultiSpan::from_span(span);
657            multispan.push_span_label(span_late, note);
658            cx.tcx().emit_node_span_lint(
659                LATE_BOUND_LIFETIME_ARGUMENTS,
660                args.args[0].hir_id(),
661                multispan,
662                LifetimeArgsIssue { msg },
663            );
664        }
665
666        ExplicitLateBound::Yes
667    } else {
668        ExplicitLateBound::No
669    }
670}