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