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